mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
many fixes and expands and module expansions
This commit is contained in:
parent
02313d3a33
commit
67f969a6b8
|
|
@ -62,10 +62,10 @@ class PermissionAbstract implements \JsonSerializable
|
|||
/**
|
||||
* Providing module id.
|
||||
*
|
||||
* @var int
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $from = 0;
|
||||
protected ?string $from = null;
|
||||
|
||||
/**
|
||||
* Type.
|
||||
|
|
@ -105,7 +105,7 @@ class PermissionAbstract implements \JsonSerializable
|
|||
* @param null|int $unit Unit Unit to check (null if all are acceptable)
|
||||
* @param null|string $app App App to check (null if all are acceptable)
|
||||
* @param null|string $module Module Module to check (null if all are acceptable)
|
||||
* @param int $from Provided by which module
|
||||
* @param null|string $from Provided by which module
|
||||
* @param null|int $type Type (e.g. customer) (null if all are acceptable)
|
||||
* @param null|int $element (e.g. customer id) (null if all are acceptable)
|
||||
* @param null|int $component (e.g. address) (null if all are acceptable)
|
||||
|
|
@ -117,7 +117,7 @@ class PermissionAbstract implements \JsonSerializable
|
|||
int $unit = null,
|
||||
string $app = null,
|
||||
string $module = null,
|
||||
int $from = 0,
|
||||
string $from = null,
|
||||
int $type = null,
|
||||
int $element = null,
|
||||
int $component = null,
|
||||
|
|
@ -226,11 +226,11 @@ class PermissionAbstract implements \JsonSerializable
|
|||
/**
|
||||
* Get providing module id.
|
||||
*
|
||||
* @return int Returns the module responsible for setting this permission
|
||||
* @return null|string Returns the module responsible for setting this permission
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getFrom() : int
|
||||
public function getFrom() : ?string
|
||||
{
|
||||
return $this->from;
|
||||
}
|
||||
|
|
@ -238,13 +238,13 @@ class PermissionAbstract implements \JsonSerializable
|
|||
/**
|
||||
* Set providing module id.
|
||||
*
|
||||
* @param int $from Providing module
|
||||
* @param null|string $from Providing module
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setFrom(int $from = 0) : void
|
||||
public function setFrom(string $from = null) : void
|
||||
{
|
||||
$this->from = $from;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* MIT License
|
||||
* © 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* © PathFinding.js
|
||||
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* (c) PathFinding.js
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* MIT License
|
||||
* © 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* © PathFinding.js
|
||||
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* (c) PathFinding.js
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* MIT License
|
||||
* © 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* © PathFinding.js
|
||||
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* (c) PathFinding.js
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* MIT License
|
||||
* © 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* © PathFinding.js
|
||||
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
|
||||
* (c) PathFinding.js
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ final class CustomerValue
|
|||
*
|
||||
* Hazard Model, same as $margin * (1 + $discountRate) / (1 + $discountRate - $retentionRate)
|
||||
*
|
||||
* @param float $margin Margin per period
|
||||
* @param float $margin Margin per period (or revenue/sales)
|
||||
* @param float $retentionRate Rate of remaining customers per period (= average lifetime / (1 + average lifetime))
|
||||
* @param float $discountRate Cost of capital to discount future revenue
|
||||
*
|
||||
|
|
@ -42,6 +42,32 @@ final class CustomerValue
|
|||
return $margin * $retentionRate / (1 + $discountRate - $retentionRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic customer lifetime value
|
||||
*
|
||||
* Hazard Model, same as $margin * (1 + $discountRate) / (1 + $discountRate - $retentionRate)
|
||||
*
|
||||
* @param array $margins Margin per period (or revenue/sales)
|
||||
* @param float $retentionRate Rate of remaining customers per period (= average lifetime / (1 + average lifetime))
|
||||
* @param float $discountRate Cost of capital to discount future revenue
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getBasicCLV(array $margins, float $retentionRate, float $discountRate) : float
|
||||
{
|
||||
$clv = 0.0;
|
||||
$c = 1;
|
||||
foreach ($margins as $margin) {
|
||||
$clv += ($retentionRate ** $c) * $margin * \pow(1 / (1 + $discountRate), $c);
|
||||
|
||||
++$c;
|
||||
}
|
||||
|
||||
return $clv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalized measure of recurring revenue
|
||||
*
|
||||
|
|
|
|||
|
|
@ -58,6 +58,68 @@ final class Metrics
|
|||
return ($ce - $cn) / $cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcualte the coefficient of retention
|
||||
*
|
||||
* @param float $retentionRate Observed retention rate (optionally use the average)
|
||||
* @param float $rc Retention rate ceiling
|
||||
* @param int $t Period
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getCoefficientOfRetention(float $retentionRate, float $rc, int $t) : float
|
||||
{
|
||||
return 1 / $t * \log($rc - $retentionRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict the retention rate for period t
|
||||
*
|
||||
* @param float $rc Retention rate ceiling
|
||||
* @param float $r Coefficient of retention
|
||||
* @param int $t Period t
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function predictCustomerRetention(float $rc, float $r, int $t) : float
|
||||
{
|
||||
return $rc * (1 - \exp(-$r * $t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the average lifetime duration
|
||||
*
|
||||
* @param array $retainedCustomers Retained customers per period
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function averageLifetimeDuration(array $retainedCustomers) : float
|
||||
{
|
||||
return \array_sum($retainedCustomers) / \count($retainedCustomers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the probability of a customer being active
|
||||
*
|
||||
* @param int $purchases Number of purchases during the periods
|
||||
* @param int $periods Number of periods (e.g. number of months)
|
||||
* @param int $lastPurchase In which period was the last purchase
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function customerActiveProbability(int $purchases, int $periods, int $lastPurchase) : float
|
||||
{
|
||||
return \pow($lastPurchase / $periods, $purchases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the customer profits
|
||||
*
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
}
|
||||
|
||||
if ($condValue['orderBy'] !== null) {
|
||||
$where1->orderBy(static::$table . '_' . $searchDepth . '.' . static::$columns[$condValue['orderBy']], $condValue['sortOrder']);
|
||||
$where1->orderBy(static::$table . '_' . $searchDepth . '.' . static::getColumnByMember($condValue['orderBy']), $condValue['sortOrder']);
|
||||
}
|
||||
|
||||
if ($condValue['limit'] !== null) {
|
||||
|
|
@ -899,14 +899,6 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
/** @var self $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
|
||||
if (\is_object($values)) {
|
||||
// conditionals
|
||||
TestUtils::setMember($values, $mapper::$columns[static::$hasMany[$propertyName]['self']]['internal'], $objId);
|
||||
|
||||
$mapper::createArray($values);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!\is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1160,14 +1152,13 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
$values = $obj->{$propertyName};
|
||||
}
|
||||
|
||||
if (!\is_array($values)) {
|
||||
// conditionals
|
||||
if (!\is_array($values) || empty($values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var self $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
$relReflectionClass = !empty($values) ? new \ReflectionClass(\reset($values)) : null;
|
||||
$relReflectionClass = new \ReflectionClass(\reset($values));
|
||||
$objsIds[$propertyName] = [];
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
|
|
@ -1178,7 +1169,6 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
continue;
|
||||
}
|
||||
|
||||
/** @var \ReflectionClass @relReflectionClass */
|
||||
$primaryKey = $mapper::getObjectId($value, $relReflectionClass);
|
||||
|
||||
// already in db
|
||||
|
|
@ -2081,7 +2071,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*/
|
||||
public static function populateOwnsOne(string $member, array $result, int $depth = 3, mixed $default = null) : mixed
|
||||
{
|
||||
/** @var self $mapper */
|
||||
/** @var self|string $mapper */
|
||||
$mapper = static::$ownsOne[$member]['mapper'];
|
||||
|
||||
if ($depth < 1) {
|
||||
|
|
@ -2121,7 +2111,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*/
|
||||
public static function populateOwnsOneArray(string $member, array $result, int $depth = 3, mixed $default = null) : array
|
||||
{
|
||||
/** @var self $mapper */
|
||||
/** @var self|string $mapper */
|
||||
$mapper = static::$ownsOne[$member]['mapper'];
|
||||
|
||||
if ($depth < 1) {
|
||||
|
|
@ -2162,7 +2152,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*/
|
||||
public static function populateBelongsTo(string $member, array $result, int $depth = 3, mixed $default = null) : mixed
|
||||
{
|
||||
/** @var self $mapper */
|
||||
/** @var self|string $mapper */
|
||||
$mapper = static::$belongsTo[$member]['mapper'];
|
||||
|
||||
if ($depth < 1) {
|
||||
|
|
@ -2202,7 +2192,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*/
|
||||
public static function populateBelongsToArray(string $member, array $result, int $depth = 3, mixed $default = null) : array
|
||||
{
|
||||
/** @var self $mapper */
|
||||
/** @var self|string $mapper */
|
||||
$mapper = static::$belongsTo[$member]['mapper'];
|
||||
|
||||
if ($depth < 1) {
|
||||
|
|
@ -3111,6 +3101,8 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
try {
|
||||
$results = false;
|
||||
|
||||
$t = $query->toSql();
|
||||
|
||||
$sth = self::$db->con->prepare($query->toSql());
|
||||
if ($sth !== false) {
|
||||
$sth->execute();
|
||||
|
|
@ -3323,7 +3315,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
// get BelognsToQuery
|
||||
if ($depth > 1 && self::$relations === RelationType::ALL) {
|
||||
foreach (static::$belongsTo as $rel) {
|
||||
foreach (static::$belongsTo as $key => $rel) {
|
||||
if (isset(self::$withFields[$key]) && self::$withFields[$key]['ignore']) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3348,7 +3340,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
// get HasManyQuery (but only for elements which have a 'column' defined)
|
||||
if ($depth > 1 && self::$relations === RelationType::ALL) {
|
||||
foreach (static::$hasMany as $rel) {
|
||||
foreach (static::$hasMany as $key => $rel) {
|
||||
// @todo: impl. conditiona/with handling, sort, limit, filter or is this not required here?
|
||||
if (isset($rel['external']) || !isset($rel['column']) // @todo: conflict with getHasMany()???!?!?!?!
|
||||
|| (isset(self::$withFields[$key]) && self::$withFields[$key]['ignore'])
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@ use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
|||
*/
|
||||
class Builder extends BuilderAbstract
|
||||
{
|
||||
/**
|
||||
* Log queries.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static bool $log = false;
|
||||
|
||||
/**
|
||||
* Is read only.
|
||||
*
|
||||
|
|
@ -369,7 +377,13 @@ class Builder extends BuilderAbstract
|
|||
$this->resolveJoinDependencies();
|
||||
}
|
||||
|
||||
return $this->grammar->compileQuery($this);
|
||||
$query = $this->grammar->compileQuery($this);
|
||||
|
||||
if (self::$log) {
|
||||
\phpOMS\Log\FileLogger::getInstance()->debug($query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class Country
|
|||
/**
|
||||
* Country developed.
|
||||
*
|
||||
* @var string
|
||||
* @var bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected bool $isDeveloped = false;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace phpOMS\Localization;
|
||||
|
||||
use phpOMS\Stdlib\Base\FloatInt;
|
||||
|
||||
/**
|
||||
* Money class.
|
||||
*
|
||||
|
|
@ -22,32 +24,8 @@ namespace phpOMS\Localization;
|
|||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class Money implements \Serializable
|
||||
final class Money extends FloatInt
|
||||
{
|
||||
/**
|
||||
* Max amount of decimals.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const MAX_DECIMALS = 4;
|
||||
|
||||
/**
|
||||
* Thousands separator.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private string $thousands = ',';
|
||||
|
||||
/**
|
||||
* Decimal separator.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private string $decimal = '.';
|
||||
|
||||
/**
|
||||
* Currency symbol position
|
||||
*
|
||||
|
|
@ -64,14 +42,6 @@ final class Money implements \Serializable
|
|||
*/
|
||||
private string $symbol = ISO4217SymbolEnum::_USD;
|
||||
|
||||
/**
|
||||
* Value.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private int $value = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -85,48 +55,10 @@ final class Money implements \Serializable
|
|||
*/
|
||||
public function __construct(int | float | string $value = 0, string $thousands = ',', string $decimal = '.', string $symbol = '', int $position = 0)
|
||||
{
|
||||
$this->value = \is_int($value) ? $value : self::toInt((string) $value);
|
||||
$this->thousands = $thousands;
|
||||
$this->decimal = $decimal;
|
||||
$this->symbol = $symbol;
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Money to int.
|
||||
*
|
||||
* @param string $value Money value
|
||||
* @param string $thousands Thousands character
|
||||
* @param string $decimal Decimal character
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \Exception this exception is thrown if an internal explode or substr error occurs
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function toInt(string $value, string $thousands = ',', string $decimal = '.') : int
|
||||
{
|
||||
$split = \explode($decimal, $value);
|
||||
|
||||
if ($split === false) {
|
||||
throw new \Exception('Internal explode error.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$left = $split[0];
|
||||
$left = \str_replace($thousands, '', $left);
|
||||
$right = '';
|
||||
|
||||
if (\count($split) > 1) {
|
||||
$right = $split[1];
|
||||
}
|
||||
|
||||
$right = \substr($right, 0, self::MAX_DECIMALS);
|
||||
if ($right === false) {
|
||||
throw new \Exception('Internal substr error.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0');
|
||||
parent::__construct($value, $thousands, $decimal);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,30 +75,15 @@ final class Money implements \Serializable
|
|||
*/
|
||||
public function setLocalization(string $thousands = ',', string $decimal = '.', string $symbol = '', int $position = 0) : self
|
||||
{
|
||||
$this->thousands = $thousands;
|
||||
$this->decimal = $decimal;
|
||||
$this->symbol = $symbol;
|
||||
$this->position = $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value by string.
|
||||
*
|
||||
* @param string $value Money value
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setString(string $value) : self
|
||||
{
|
||||
$this->value = self::toInt($value, $this->thousands, $this->decimal);
|
||||
parent::setLocalization($thousands, $decimal);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get money.
|
||||
*
|
||||
|
|
@ -180,200 +97,4 @@ final class Money implements \Serializable
|
|||
{
|
||||
return ($this->position === 0 && !empty($this->symbol) ? $this->symbol . ' ' : '') . $this->getAmount($decimals) . ($this->position === 1 ? ' ' . $this->symbol : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get money.
|
||||
*
|
||||
* @param null|int $decimals Precision (null = auto decimals)
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Exception this exception is thrown if an internal substr error occurs
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getAmount(?int $decimals = 2) : string
|
||||
{
|
||||
$value = $this->value === 0
|
||||
? \str_repeat('0', self::MAX_DECIMALS)
|
||||
: (string) \round($this->value, -self::MAX_DECIMALS + $decimals);
|
||||
|
||||
$left = \substr($value, 0, -self::MAX_DECIMALS);
|
||||
|
||||
/** @var string $left */
|
||||
$left = $left === false ? '0' : $left;
|
||||
$right = \substr($value, -self::MAX_DECIMALS);
|
||||
|
||||
if ($right === false) {
|
||||
throw new \Exception(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if ($decimals === null) {
|
||||
$decimals = \strlen(\rtrim($right, '0'));
|
||||
}
|
||||
|
||||
return $decimals > 0
|
||||
? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals)
|
||||
: \str_pad($left, 1, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add money.
|
||||
*
|
||||
* @param int|float|string|Money $value Value to add
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function add(int | float | string | self $value) : self
|
||||
{
|
||||
if (\is_string($value) || \is_float($value)) {
|
||||
$this->value += self::toInt((string) $value, $this->thousands, $this->decimal);
|
||||
} elseif (\is_int($value)) {
|
||||
$this->value += $value;
|
||||
} else {
|
||||
$this->value += $value->getInt();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get money value.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getInt() : int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub money.
|
||||
*
|
||||
* @param int|float|string|Money $value Value to subtract
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function sub(int | float | string | self $value) : self
|
||||
{
|
||||
if (\is_string($value) || \is_float($value)) {
|
||||
$this->value -= self::toInt((string) $value, $this->thousands, $this->decimal);
|
||||
} elseif (\is_int($value)) {
|
||||
$this->value -= $value;
|
||||
} else {
|
||||
$this->value -= $value->getInt();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mult.
|
||||
*
|
||||
* @param int|float $value Value to multiply with
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function mult(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value * $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Div.
|
||||
*
|
||||
* @param int|float $value Value to divide by
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function div(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value / $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abs.
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function abs() : self
|
||||
{
|
||||
$this->value = \abs($this->value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Power.
|
||||
*
|
||||
* @param int|float $value Value to power
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function pow(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value ** $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searialze.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return (string) $this->getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize.
|
||||
*
|
||||
* @param mixed $value Value to unserialize
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
$this->setInt((int) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set money value.
|
||||
*
|
||||
* @param int $value Value
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setInt(int $value) : self
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ use phpOMS\Math\Functions\Gamma;
|
|||
/**
|
||||
* Chi squared distribution.
|
||||
*
|
||||
* Test if two variables are similarly distributed (goodness fit, test dependency of variables)
|
||||
*
|
||||
* @package phpOMS\Math\Stochastic\Distribution
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ declare(strict_types=1);
|
|||
namespace phpOMS\Math\Stochastic\Distribution;
|
||||
|
||||
/**
|
||||
* Bernulli distribution.
|
||||
* T distribution.
|
||||
*
|
||||
* Test the similarity of two means
|
||||
*
|
||||
* @package phpOMS\Math\Stochastic\Distribution
|
||||
* @license OMS License 1.0
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ use phpOMS\Math\Statistic\MeasureOfDispersion;
|
|||
/**
|
||||
* ZTest
|
||||
*
|
||||
* Test if the mean is the same as the population mean
|
||||
*
|
||||
* @package phpOMS\Math\Stochastic\Distribution
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* GLGPL 2.1 License
|
||||
* © 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* © PHPMailer
|
||||
* (c) 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* (c) PHPMailer
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* GLGPL 2.1 License
|
||||
* © 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* © PHPMailer
|
||||
* (c) 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* (c) PHPMailer
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
*
|
||||
* Extended based on:
|
||||
* GLGPL 2.1 License
|
||||
* © 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* © PHPMailer
|
||||
* (c) 2012 - 2015 Marcus Bointon, 2010 - 2012 Jim Jagielski, 2004 - 2009 Andy Prevost
|
||||
* (c) PHPMailer
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ final class PhpCode
|
|||
* Validate file integrety
|
||||
*
|
||||
* @param string $source Source code path
|
||||
* @param string $hash Source hash
|
||||
* @param string $hash Source hash (md5)
|
||||
*
|
||||
* @return bool Returns true if filee matches expected signature otherwise false is returned
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,4 +37,6 @@ abstract class AddressType extends Enum
|
|||
public const CONTRACT = 6;
|
||||
|
||||
public const OTHER = 7;
|
||||
|
||||
public const EDUCATION = 8;
|
||||
}
|
||||
|
|
|
|||
343
Stdlib/Base/FloatInt.php
Normal file
343
Stdlib/Base/FloatInt.php
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package phpOMS\Stdlib
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Stdlib\Base;
|
||||
|
||||
/**
|
||||
* FloatInt class.
|
||||
*
|
||||
* @package phpOMS\Stdlib
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class FloatInt implements \Serializable
|
||||
{
|
||||
/**
|
||||
* Max amount of decimals.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const MAX_DECIMALS = 4;
|
||||
|
||||
/**
|
||||
* Thousands separator.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected string $thousands = ',';
|
||||
|
||||
/**
|
||||
* Decimal separator.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected string $decimal = '.';
|
||||
|
||||
/**
|
||||
* Value.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $value = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int|float|string $value Value
|
||||
* @param string $thousands Thousands separator
|
||||
* @param string $decimal Decimal separator
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(int | float | string $value = 0, string $thousands = ',', string $decimal = '.')
|
||||
{
|
||||
$this->value = \is_int($value) ? $value : self::toInt((string) $value);
|
||||
$this->thousands = $thousands;
|
||||
$this->decimal = $decimal;
|
||||
}
|
||||
|
||||
/**
|
||||
* FloatInt to int.
|
||||
*
|
||||
* @param string $value FloatInt value
|
||||
* @param string $thousands Thousands character
|
||||
* @param string $decimal Decimal character
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \Exception this exception is thrown if an internal explode or substr error occurs
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function toInt(string $value, string $thousands = ',', string $decimal = '.') : int
|
||||
{
|
||||
$split = \explode($decimal, $value);
|
||||
|
||||
if ($split === false) {
|
||||
throw new \Exception('Internal explode error.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$left = $split[0];
|
||||
$left = \str_replace($thousands, '', $left);
|
||||
$right = '';
|
||||
|
||||
if (\count($split) > 1) {
|
||||
$right = $split[1];
|
||||
}
|
||||
|
||||
$right = \substr($right, 0, self::MAX_DECIMALS);
|
||||
if ($right === false) {
|
||||
throw new \Exception('Internal substr error.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set localization.
|
||||
*
|
||||
* @param string $thousands Thousands separator
|
||||
* @param string $decimal Decimal separator
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setLocalization(string $thousands = ',', string $decimal = '.') : self
|
||||
{
|
||||
$this->thousands = $thousands;
|
||||
$this->decimal = $decimal;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value by string.
|
||||
*
|
||||
* @param string $value FloatInt value
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setString(string $value) : self
|
||||
{
|
||||
$this->value = self::toInt($value, $this->thousands, $this->decimal);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get money.
|
||||
*
|
||||
* @param null|int $decimals Precision (null = auto decimals)
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Exception this exception is thrown if an internal substr error occurs
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getAmount(?int $decimals = 2) : string
|
||||
{
|
||||
$isNegative = $this->value < 0 ? 1 : 0;
|
||||
|
||||
$value = $this->value === 0
|
||||
? \str_repeat('0', self::MAX_DECIMALS)
|
||||
: (string) \round($this->value, -self::MAX_DECIMALS + $decimals);
|
||||
|
||||
$left = \substr($value, 0, -self::MAX_DECIMALS + $isNegative);
|
||||
|
||||
/** @var string $left */
|
||||
$left = $left === false ? '0' : $left;
|
||||
$right = \substr($value, -self::MAX_DECIMALS + $isNegative);
|
||||
|
||||
if ($right === false) {
|
||||
throw new \Exception(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if ($decimals === null) {
|
||||
$decimals = \strlen(\rtrim($right, '0'));
|
||||
}
|
||||
|
||||
return $decimals > 0
|
||||
? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals)
|
||||
: \str_pad($left, 1, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add money.
|
||||
*
|
||||
* @param int|float|string|FloatInt $value Value to add
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function add(int | float | string | self $value) : self
|
||||
{
|
||||
if (\is_string($value) || \is_float($value)) {
|
||||
$this->value += self::toInt((string) $value, $this->thousands, $this->decimal);
|
||||
} elseif (\is_int($value)) {
|
||||
$this->value += $value;
|
||||
} else {
|
||||
$this->value += $value->getInt();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get money value.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getInt() : int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub money.
|
||||
*
|
||||
* @param int|float|string|FloatInt $value Value to subtract
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function sub(int | float | string | self $value) : self
|
||||
{
|
||||
if (\is_string($value) || \is_float($value)) {
|
||||
$this->value -= self::toInt((string) $value, $this->thousands, $this->decimal);
|
||||
} elseif (\is_int($value)) {
|
||||
$this->value -= $value;
|
||||
} else {
|
||||
$this->value -= $value->getInt();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mult.
|
||||
*
|
||||
* @param int|float $value Value to multiply with
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function mult(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value * $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Div.
|
||||
*
|
||||
* @param int|float $value Value to divide by
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function div(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value / $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abs.
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function abs() : self
|
||||
{
|
||||
$this->value = \abs($this->value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Power.
|
||||
*
|
||||
* @param int|float $value Value to power
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function pow(int | float $value) : self
|
||||
{
|
||||
$this->value = (int) ($this->value ** $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searialze.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return (string) $this->getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize.
|
||||
*
|
||||
* @param mixed $value Value to unserialize
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
$this->setInt((int) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set money value.
|
||||
*
|
||||
* @param int $value Value
|
||||
*
|
||||
* @return FloatInt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setInt(int $value) : self
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
@ -212,15 +212,17 @@ class Location implements \JsonSerializable, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
* @link http://php.net/manual/en/serializable.unserialize.php
|
||||
* @param string $serialized <p>
|
||||
* The string representation of the object.
|
||||
* </p>
|
||||
* @return void
|
||||
* @since 5.1.0
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unserialize($serialized) : void
|
||||
{
|
||||
$data = \json_decode($serialized, true);
|
||||
|
||||
$this->postal = $data['postal'];
|
||||
$this->city = $data['city'];
|
||||
$this->country = $data['country'];
|
||||
$this->address = $data['address'];
|
||||
$this->state = $data['state'];
|
||||
$this->geo = $data['geo'];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ final class FileUtils
|
|||
public static function absolute(string $origPath) : string
|
||||
{
|
||||
if (\file_exists($origPath) !== false) {
|
||||
return \realpath($origPath);
|
||||
$path = \realpath($origPath);
|
||||
|
||||
return $path === false ? '' : $path;
|
||||
}
|
||||
|
||||
$startsWithSlash = \strpos($origPath, '/') === 0 || \strpos($origPath, '\\') === 0 ? '/' : '';
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class MbStringUtilsTest extends \PHPUnit\Framework\TestCase
|
|||
*/
|
||||
public function testEntropy() : void
|
||||
{
|
||||
self::assertEqualsWithDelta(2.75, MbStringUtils::mb_entropy('akj@!©¥j'), 0.1);
|
||||
self::assertEqualsWithDelta(2.75, MbStringUtils::mb_entropy('akj@!(c)¥j'), 0.1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user