From 9edbe6cc4bf8bcd790e3c6fdbbb2ff490e264030 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 6 May 2023 11:42:06 +0000 Subject: [PATCH] make id public, organigram impl. media password/encryption, settings bug fix, Money->FloatInt change, ... --- Account/Account.php | 45 ++++- Account/Group.php | 8 +- Account/PermissionAbstract.php | 2 +- Account/PermissionHandlingTrait.php | 2 +- Autoloader.php | 2 +- DataStorage/Database/GrammarAbstract.php | 42 ++-- .../Database/Mapper/DataMapperAbstract.php | 50 ++++- .../Database/Mapper/DataMapperFactory.php | 20 +- DataStorage/Database/Mapper/DeleteMapper.php | 8 +- DataStorage/Database/Mapper/ReadMapper.php | 187 ++++++++++-------- DataStorage/Database/Mapper/UpdateMapper.php | 10 +- DataStorage/Database/Mapper/WriteMapper.php | 28 +-- DataStorage/Database/Query/Builder.php | 6 +- .../Database/Query/Grammar/Grammar.php | 1 + Localization/BaseStringL11n.php | 6 +- Localization/BaseStringL11nType.php | 2 +- Localization/Defaults/City.php | 2 +- Localization/Defaults/Country.php | 2 +- Localization/Defaults/Currency.php | 2 +- Localization/Defaults/Iban.php | 2 +- Localization/Defaults/Language.php | 2 +- Localization/ISO4217CharEnum.php | 154 ++++++++++++++- Localization/ISO4217DecimalEnum.php | 24 +++ Localization/ISO4217Enum.php | 154 ++++++++++++++- Localization/ISO4217NumEnum.php | 12 ++ Localization/ISO4217SubUnitEnum.php | 70 +++++++ Localization/ISO4217SymbolEnum.php | 158 +++++++++++++++ Localization/ISO639x1Enum.php | 10 + Localization/L11nManager.php | 6 +- Localization/Localization.php | 66 +++++-- Localization/Money.php | 8 + Message/Http/HttpHeader.php | 15 +- Message/Http/HttpRequest.php | 46 ++--- Message/Mail/MailHandler.php | 2 +- Message/Mail/Smtp.php | 2 +- Message/RequestAbstract.php | 36 +++- Model/Message/NotifyType.php | 42 ---- Router/SocketRouter.php | 2 +- Router/WebRouter.php | 2 +- Security/EncryptionHelper.php | 88 +++++++++ Stdlib/Base/Enum.php | 11 +- Stdlib/Base/FloatInt.php | 6 +- Stdlib/Base/Location.php | 2 +- Uri/UriFactory.php | 14 +- Utils/TaskSchedule/SchedulerAbstract.php | 8 +- Views/View.php | 2 +- .../Database/TestModel/BaseModel.php | 2 +- tests/Localization/L11nManagerTest.php | 4 +- tests/Localization/LocalizationTest.php | 16 -- tests/Model/Message/NotifyTest.php | 14 +- tests/Model/Message/NotifyTypeTest.php | 54 ----- tests/Uri/UriFactoryTest.php | 10 +- tests/Views/ViewTest.php | 4 +- 53 files changed, 1076 insertions(+), 397 deletions(-) delete mode 100755 Model/Message/NotifyType.php delete mode 100755 tests/Model/Message/NotifyTypeTest.php diff --git a/Account/Account.php b/Account/Account.php index ebbbaff97..e4ba4393d 100755 --- a/Account/Account.php +++ b/Account/Account.php @@ -37,7 +37,7 @@ class Account implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Names. @@ -69,7 +69,7 @@ class Account implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $email = ''; + public string $email = ''; /** * Ip. @@ -79,7 +79,7 @@ class Account implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $origin = ''; + public string $origin = ''; /** * Login. @@ -95,7 +95,7 @@ class Account implements \JsonSerializable * @var \DateTime * @since 1.0.0 */ - protected \DateTime $lastActive; + public \DateTime $lastActive; /** * Last activity. @@ -111,7 +111,7 @@ class Account implements \JsonSerializable * @var Group[] * @since 1.0.0 */ - protected array $groups = []; + public array $groups = []; /** * Password. @@ -119,7 +119,7 @@ class Account implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $password = ''; + public string $password = ''; /** * Account type. @@ -127,7 +127,7 @@ class Account implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $type = AccountType::USER; + public int $type = AccountType::USER; /** * Account status. @@ -135,7 +135,7 @@ class Account implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $status = AccountStatus::INACTIVE; + public int $status = AccountStatus::INACTIVE; /** * Localization. @@ -147,6 +147,31 @@ class Account implements \JsonSerializable use PermissionHandlingTrait; + public function hasPermission( + int $permission, + int $unit = null, + int $app = null, + string $module = null, + int $category = null, + int $element = null, + int $component = null + ) : bool + { + foreach ($this->groups as $group) { + if ($group->hasPermission($permission, $unit, $app, $module, $category, $element, $component)) { + return true; + } + } + + foreach ($this->permissions as $p) { + if ($p->hasPermission($permission, $unit, $app, $module, $category, $element, $component)) { + return true; + } + } + + return false; + } + /** * Constructor. * @@ -203,7 +228,7 @@ class Account implements \JsonSerializable /* $ids = []; foreach ($this->groups as $group) { - $ids[] = $group->getId(); + $ids[] = $group->id; } return $ids; @@ -237,7 +262,7 @@ class Account implements \JsonSerializable public function hasGroup(int $id) : bool { foreach ($this->groups as $group) { - if ($group->getId() === $id) { + if ($group->id === $id) { return true; } } diff --git a/Account/Group.php b/Account/Group.php index 6572fbc65..30b3e99a9 100755 --- a/Account/Group.php +++ b/Account/Group.php @@ -32,7 +32,7 @@ class Group implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Group name. @@ -56,7 +56,7 @@ class Group implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $members = []; + public array $members = []; /** * Parents. @@ -64,7 +64,7 @@ class Group implements \JsonSerializable * @var int[] * @since 1.0.0 */ - protected array $parents = []; + public array $parents = []; /** * Group status. @@ -72,7 +72,7 @@ class Group implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $status = GroupStatus::INACTIVE; + public int $status = GroupStatus::INACTIVE; use PermissionHandlingTrait; diff --git a/Account/PermissionAbstract.php b/Account/PermissionAbstract.php index abe242cb1..2ba925c96 100755 --- a/Account/PermissionAbstract.php +++ b/Account/PermissionAbstract.php @@ -33,7 +33,7 @@ class PermissionAbstract implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Unit id. diff --git a/Account/PermissionHandlingTrait.php b/Account/PermissionHandlingTrait.php index 0da0235a1..d850ca4b4 100755 --- a/Account/PermissionHandlingTrait.php +++ b/Account/PermissionHandlingTrait.php @@ -30,7 +30,7 @@ trait PermissionHandlingTrait * @var PermissionAbstract[] * @since 1.0.0 */ - protected array $permissions = []; + public array $permissions = []; /** * Set permissions. diff --git a/Autoloader.php b/Autoloader.php index 1bb0827e1..94d402617 100755 --- a/Autoloader.php +++ b/Autoloader.php @@ -118,7 +118,7 @@ final class Autoloader foreach (self::$paths as $path) { if (\is_file($file = $path . $class . '.php')) { - include $file; + include_once $file; return; } diff --git a/DataStorage/Database/GrammarAbstract.php b/DataStorage/Database/GrammarAbstract.php index 6bb103cb8..dd84dec70 100755 --- a/DataStorage/Database/GrammarAbstract.php +++ b/DataStorage/Database/GrammarAbstract.php @@ -193,10 +193,17 @@ abstract class GrammarAbstract $expression = ''; foreach ($elements as $key => $element) { - if (\is_string($element) && $element !== '*') { - $expression .= $this->compileSystem($element) . (\is_string($key) ? ' as ' . $key : '') . ', '; - } elseif ($element === '*') { - $expression .= '*, '; + if (\is_string($element)) { + // @note: Replaced $this->compileSystem with $element + // This causes problems for tables or columns which use keywords such as count, + // but they are rare and should be handled somewhere else if it actually is such a case + if (\in_array($element, ['group', 'id', 'where', 'order'])) { + $expression .= $this->compileSystem($element) + . (\is_string($key) ? ' as ' . $key : '') . ', '; + } else { + $expression .= $element + . (\is_string($key) ? ' as ' . $key : '') . ', '; + } } elseif ($element instanceof \Closure) { $expression .= $element() . (\is_string($key) ? ' as ' . $key : '') . ', '; } elseif ($element instanceof BuilderAbstract) { @@ -226,7 +233,7 @@ abstract class GrammarAbstract $identifierEnd = $this->systemIdentifierEnd; foreach ($this->specialKeywords as $keyword) { - if (\strrpos($system, $keyword, -\strlen($system)) !== false) { + if (\stripos($system, $keyword) !== false) { $identifierStart = ''; $identifierEnd = ''; @@ -240,18 +247,25 @@ abstract class GrammarAbstract if (($pos = \stripos($system, '.')) !== false) { $split = [\substr($system, 0, $pos), \substr($system, $pos + 1)]; - return ($split[0] !== '*' ? $identifierStart : '') - . $split[0] - . ($split[0] !== '*' ? $identifierEnd : '') + $identifierTwoStart = $identifierStart; + $identifierTwoEnd = $identifierEnd; + + if ($split[1] === '*') { + $identifierTwoStart = ''; + $identifierTwoEnd = ''; + } + + return $identifierStart . $split[0] . $identifierEnd . '.' - . ($split[1] !== '*' ? $identifierStart : '') - . $split[1] - . ($split[1] !== '*' ? $identifierEnd : ''); + . $identifierTwoStart . $split[1] . $identifierTwoEnd; } - return ($system !== '*' ? $identifierStart : '') - . $system - . ($system !== '*' ? $identifierEnd : ''); + if ($system === '*') { + $identifierStart = ''; + $identifierEnd = ''; + } + + return $identifierStart . $system . $identifierEnd; } /** diff --git a/DataStorage/Database/Mapper/DataMapperAbstract.php b/DataStorage/Database/Mapper/DataMapperAbstract.php index d492b7833..4c6c461b3 100755 --- a/DataStorage/Database/Mapper/DataMapperAbstract.php +++ b/DataStorage/Database/Mapper/DataMapperAbstract.php @@ -16,6 +16,7 @@ namespace phpOMS\DataStorage\Database\Mapper; use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; use phpOMS\DataStorage\Database\Query\Builder; +use phpOMS\DataStorage\Database\Query\JoinType; use phpOMS\DataStorage\Database\Query\OrderType; /** @@ -103,6 +104,14 @@ abstract class DataMapperAbstract */ protected array $join = []; + /** + * Join conditions + * + * @var array + * @since 1.0.0 + */ + protected array $on = []; + /** * Base query which is merged with the query in the mapper * @@ -328,7 +337,7 @@ abstract class DataMapperAbstract * * @since 1.0.0 */ - public function join(string $member, string $mapper, mixed $value, string $logic = '=', string $type = 'left') : self + public function join(string $member, string $mapper, mixed $value, string $logic = '=', string $type = JoinType::LEFT_JOIN) : self { $split = \explode('/', $member); $memberSplit = \array_shift($split); @@ -344,6 +353,19 @@ abstract class DataMapperAbstract return $this; } + public function on(string $member, mixed $value, string $logic = '=', string $connector = 'AND', string $relation = '') : self + { + $this->on[$relation][] = [ + 'child' => '', + 'member' => $member, + 'value' => $value, + 'logic' => $logic, + 'comparison' => $connector, + ]; + + return $this; + } + /** * Define the joining data * @@ -358,7 +380,7 @@ abstract class DataMapperAbstract */ public function leftJoin(string $member, string $mapper, mixed $value, string $logic = '=') : self { - return $this->join($member, $mapper, $value, $logic, 'left'); + return $this->join($member, $mapper, $value, $logic, JoinType::LEFT_JOIN); } /** @@ -375,7 +397,7 @@ abstract class DataMapperAbstract */ public function rightJoin(string $member, string $mapper, mixed $value, string $logic = '=') : self { - return $this->join($member, $mapper, $value, $logic, 'right'); + return $this->join($member, $mapper, $value, $logic, JoinType::RIGHT_JOIN); } /** @@ -392,7 +414,7 @@ abstract class DataMapperAbstract */ public function innerJoin(string $member, string $mapper, mixed $value, string $logic = '=') : self { - return $this->join($member, $mapper, $value, $logic, 'inner'); + return $this->join($member, $mapper, $value, $logic, JoinType::INNER_JOIN); } /** @@ -461,6 +483,26 @@ abstract class DataMapperAbstract } } + if (isset($this->join[$member])) { + foreach ($this->join[$member] as $join) { + if ($join['child'] === '') { + continue; + } + + $relMapper->join($join['child'], $join['mapper'], $join['value'], $join['logic'], $join['type']); + } + } + + if (isset($this->on[$member])) { + foreach ($this->on[$member] as $on) { + if ($on['child'] === '') { + continue; + } + + $relMapper->on($on['child'], $on['value'], $on['logic'], $on['comparison'], $on['field']); + } + } + return $relMapper; } diff --git a/DataStorage/Database/Mapper/DataMapperFactory.php b/DataStorage/Database/Mapper/DataMapperFactory.php index 33c052adc..4c978b19f 100755 --- a/DataStorage/Database/Mapper/DataMapperFactory.php +++ b/DataStorage/Database/Mapper/DataMapperFactory.php @@ -427,28 +427,17 @@ class DataMapperFactory * Get id of object * * @param object $obj Model to create - * @param \ReflectionClass $refClass Reflection class * @param string $member Member name for the id, if it is not the primary key * * @return mixed * * @since 1.0.0 */ - public static function getObjectId(object $obj, \ReflectionClass $refClass = null, string $member = null) : mixed + public static function getObjectId(object $obj, string $member = null) : mixed { - $refClass ??= new \ReflectionClass($obj); $propertyName = $member ?? static::COLUMNS[static::PRIMARYFIELD]['internal']; - $refProp = $refClass->getProperty($propertyName); - if (!$refProp->isPublic()) { - $refProp->setAccessible(true); - $objectId = $refProp->getValue($obj); - $refProp->setAccessible(false); - } else { - $objectId = $obj->{$propertyName}; - } - - return $objectId; + return $obj->{$propertyName}; } /** @@ -469,9 +458,7 @@ class DataMapperFactory \settype($objId, static::COLUMNS[static::PRIMARYFIELD]['type']); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $refProp->setValue($obj, $objId); - $refProp->setAccessible(false); } else { $obj->{$propertyName} = $objId; } @@ -615,8 +602,7 @@ class DataMapperFactory $secondaryId ); - $cloned - ->where('', $where) + $cloned->where('', $where) ->sort($primarySortField, OrderType::DESC); } diff --git a/DataStorage/Database/Mapper/DeleteMapper.php b/DataStorage/Database/Mapper/DeleteMapper.php index aa495f114..5c78b836c 100755 --- a/DataStorage/Database/Mapper/DeleteMapper.php +++ b/DataStorage/Database/Mapper/DeleteMapper.php @@ -72,7 +72,7 @@ final class DeleteMapper extends DataMapperAbstract public function executeDelete(object $obj) : mixed { $refClass = new \ReflectionClass($obj); - $objId = $this->mapper::getObjectId($obj, $refClass); + $objId = $this->mapper::getObjectId($obj); if (empty($objId)) { return null; @@ -139,9 +139,7 @@ final class DeleteMapper extends DataMapperAbstract $refProp = $refClass->getProperty($member); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $relMapper->execute($refProp->getValue($obj)); - $refProp->setAccessible(false); } else { $relMapper->execute($obj->{$member}); } @@ -174,9 +172,7 @@ final class DeleteMapper extends DataMapperAbstract $objIds = []; $refProp = $refClass->getProperty($member); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $values = $refProp->getValue($obj); - $refProp->setAccessible(false); } else { $values = $obj->{$member}; } @@ -198,7 +194,7 @@ final class DeleteMapper extends DataMapperAbstract continue; } - $objIds[$key] = $mapper::getObjectId($value, $relReflectionClass); + $objIds[$key] = $mapper::getObjectId($value); } // delete relation tables diff --git a/DataStorage/Database/Mapper/ReadMapper.php b/DataStorage/Database/Mapper/ReadMapper.php index a5475a035..8b5c63d0c 100755 --- a/DataStorage/Database/Mapper/ReadMapper.php +++ b/DataStorage/Database/Mapper/ReadMapper.php @@ -26,6 +26,9 @@ use phpOMS\Utils\ArrayUtils; * @link https://jingga.app * @since 1.0.0 * + * @todo Add memory cache per read mapper parent call (These should be cached: attribute types, file types, etc.) + * @todo Add getArray functions to get array instead of object + * * @template R */ final class ReadMapper extends DataMapperAbstract @@ -330,20 +333,57 @@ final class ReadMapper extends DataMapperAbstract } /* variable in model */ + // @todo: join handling is extremely ugly, needs to be refactored foreach ($values as $join) { // @todo: the has many, etc. if checks only work if it is a relation on the first level, if we have a deeper where condition nesting this fails if ($join['child'] !== '') { continue; } - $query->join($join['mapper']::TABLE, $join['type'], $join['mapper']::TABLE . '_d' . ($this->depth + 1)) - ->on( - $this->mapper::TABLE . '_d' . $this->depth . '.' . $col, - '=', - $join['mapper']::TABLE . '_d' . ($this->depth + 1) . '.' . $join['mapper']::getColumnByMember($join['value']), - 'and', - $join['mapper']::TABLE . '_d' . ($this->depth + 1) - ); + if (isset($join['mapper']::HAS_MANY[$join['value']])) { + if (isset($join['mapper']::HAS_MANY[$join['value']]['external'])) { + // join with relation table + $query->join($join['mapper']::HAS_MANY[$join['value']]['table'], $join['type'], $join['mapper']::HAS_MANY[$join['value']]['table'] . '_d' . ($this->depth + 1)) + ->on( + $this->mapper::TABLE . '_d' . $this->depth . '.' . $col, + '=', + $join['mapper']::HAS_MANY[$join['value']]['table'] . '_d' . ($this->depth + 1) . '.' . $join['mapper']::HAS_MANY[$join['value']]['external'], + 'AND', + $join['mapper']::HAS_MANY[$join['value']]['table'] . '_d' . ($this->depth + 1) + ); + + // join with model table + $query->join($join['mapper']::TABLE, $join['type'], $join['mapper']::TABLE . '_d' . ($this->depth + 1)) + ->on( + $join['mapper']::HAS_MANY[$join['value']]['table'] . '_d' . ($this->depth + 1) . '.' . $join['mapper']::HAS_MANY[$join['value']]['self'], + '=', + $join['mapper']::TABLE . '_d' . ($this->depth + 1) . '.' . $join['mapper']::PRIMARYFIELD, + 'AND', + $join['mapper']::TABLE . '_d' . ($this->depth + 1) + ); + + if (isset($this->on[$join['value']])) { + foreach ($this->on[$join['value']] as $on) { + $query->where( + $join['mapper']::TABLE . '_d' . ($this->depth + 1) . '.' . $join['mapper']::getColumnByMember($on['member']), + '=', + $on['value'], + 'AND' + ); + } + } + } + } else { + $query->join($join['mapper']::TABLE, $join['type'], $join['mapper']::TABLE . '_d' . ($this->depth + 1)) + ->on( + $this->mapper::TABLE . '_d' . $this->depth . '.' . $col, + '=', + $join['mapper']::TABLE . '_d' . ($this->depth + 1) . '.' . $join['mapper']::getColumnByMember($join['value']), + 'AND', + $join['mapper']::TABLE . '_d' . ($this->depth + 1) + ); + } + } } @@ -356,57 +396,59 @@ final class ReadMapper extends DataMapperAbstract continue; } - if (($col = $this->mapper::getColumnByMember($member)) !== null) { - // In case alternative where values are allowed - // This is different from normal or conditions as these are exclusive or conditions - // This means they are only selected IFF the previous where clause fails - $alt = []; + if (($col = $this->mapper::getColumnByMember($member)) === null) { + continue; + } - /* variable in model */ - $previous = null; - foreach ($values as $where) { - // @todo: the has many, etc. if checks only work if it is a relation on the first level, if we have a deeper where condition nesting this fails - if ($where['child'] !== '') { - continue; + // In case alternative where values are allowed + // This is different from normal or conditions as these are exclusive or conditions + // This means they are only selected IFF the previous where clause fails + $alt = []; + + /* variable in model */ + $previous = null; + foreach ($values as $where) { + // @todo: the has many, etc. if checks only work if it is a relation on the first level, if we have a deeper where condition nesting this fails + if ($where['child'] !== '') { + continue; + } + + $comparison = \is_array($where['value']) && \count($where['value']) > 1 ? 'in' : $where['logic']; + if ($where['comparison'] === 'ALT') { + // This uses an alternative value if the previous value(s) in the where clause don't exist (e.g. for localized results where you allow a user language, alternatively a primary language, and then alternatively any language if the first two don't exist). + + // is first value + if (empty($alt)) { + $alt[] = $previous['value']; } - $comparison = \is_array($where['value']) && \count($where['value']) > 1 ? 'in' : $where['logic']; - if ($where['comparison'] === 'ALT') { - // This uses an alternative value if the previous value(s) in the where clause don't exist (e.g. for localized results where you allow a user language, alternatively a primary language, and then alternatively any language if the first two don't exist). - - // is first value - if (empty($alt)) { - $alt[] = $previous['value']; - } - - /* - select * from table_name - where // where starts here - field1 = 'value1' // comes from normal where - or ( // where1 starts here - field1 = 'default' - and NOT EXISTS ( // where2 starts here - select 1 from table_name where field1 = 'value1' - ) + /* + select * from table_name + where // where starts here + field1 = 'value1' // comes from normal where + or ( // where1 starts here + field1 = 'default' + and NOT EXISTS ( // where2 starts here + select 1 from table_name where field1 = 'value1' ) - */ - $where1 = new Where($this->db); - $where1->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where['value'], 'and'); + ) + */ + $where1 = new Where($this->db); + $where1->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where['value'], 'and'); - $where2 = new Builder($this->db); - $where2->select('1') - ->from($this->mapper::TABLE . '_d' . $this->depth) - ->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, 'in', $alt); + $where2 = new Builder($this->db); + $where2->select('1') + ->from($this->mapper::TABLE . '_d' . $this->depth) + ->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, 'in', $alt); - $where1->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, 'not exists', $where2, 'and'); + $where1->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, 'not exists', $where2, 'and'); - $query->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where1, 'or'); + $query->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where1, 'or'); - $alt[] = $where['value']; - } else { - $previous = $where; - $query->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where['value'], $where['comparison']); - } + $alt[] = $where['value']; + } else { + $previous = $where; + $query->where($this->mapper::TABLE . '_d' . $this->depth . '.' . $col, $comparison, $where['value'], $where['comparison']); } } } @@ -529,20 +571,15 @@ final class ReadMapper extends DataMapperAbstract $member = $path[0]; $refProp = $refClass->getProperty($path[0]); - if (!($isPublic = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + $isPublic = $refProp->isPublic(); + $aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj); \array_shift($path); $arrayPath = \implode('/', $path); - $aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj); } else { - $refProp = $refClass->getProperty($def['internal']); - $member = $def['internal']; - - if (!($isPublic = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + $refProp = $refClass->getProperty($def['internal']); + $isPublic = $refProp->isPublic(); + $member = $def['internal']; } if (isset($this->mapper::OWNS_ONE[$def['internal']])) { @@ -621,10 +658,6 @@ final class ReadMapper extends DataMapperAbstract $member->unserialize($value); } } - - if (!$isPublic) { - $refProp->setAccessible(false); - } } foreach ($this->mapper::HAS_MANY as $member => $def) { @@ -641,23 +674,17 @@ final class ReadMapper extends DataMapperAbstract $arrayPath = '/'; if (\stripos($member, '/') !== false) { - $hasPath = true; - $path = \explode('/', $member); - $refProp = $refClass->getProperty($path[0]); - - if (!($isPublic = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + $hasPath = true; + $path = \explode('/', $member); + $refProp = $refClass->getProperty($path[0]); + $isPublic = $refProp->isPublic(); \array_shift($path); $arrayPath = \implode('/', $path); $aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj); } else { $refProp = $refClass->getProperty($member); - - if (!($isPublic = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + $isPublic = $refProp->isPublic(); } if (\in_array($def['mapper']::COLUMNS[$column]['type'], ['string', 'int', 'float', 'bool'])) { @@ -694,10 +721,6 @@ final class ReadMapper extends DataMapperAbstract $member = $isPublic ? $obj->{$member} : $refProp->getValue($obj); $member->unserialize($value); } - - if (!$isPublic) { - $refProp->setAccessible(false); - } } return $obj; @@ -874,12 +897,10 @@ final class ReadMapper extends DataMapperAbstract $refProp = $refClass->getProperty($member); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $refProp->setValue($obj, !\is_array($objects) && ($many['conditional'] ?? false) === false ? [$many['mapper']::getObjectId($objects) => $objects] : $objects // if conditional === true the obj will be asigned (e.g. has many localizations but only one is loaded for the model) ); - $refProp->setAccessible(false); } else { $obj->{$member} = !\is_array($objects) && ($many['conditional'] ?? false) === false ? [$many['mapper']::getObjectId($objects) => $objects] @@ -907,9 +928,7 @@ final class ReadMapper extends DataMapperAbstract $refProp = $refClass->getProperty($member); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $relMapper->loadHasManyRelations($refProp->getValue($obj)); - $refProp->setAccessible(false); } else { $relMapper->loadHasManyRelations($obj->{$member}); } diff --git a/DataStorage/Database/Mapper/UpdateMapper.php b/DataStorage/Database/Mapper/UpdateMapper.php index f11171bb8..37e552b3e 100755 --- a/DataStorage/Database/Mapper/UpdateMapper.php +++ b/DataStorage/Database/Mapper/UpdateMapper.php @@ -74,7 +74,7 @@ final class UpdateMapper extends DataMapperAbstract public function executeUpdate(object $obj) : mixed { $refClass = new \ReflectionClass($obj); - $objId = $this->mapper::getObjectId($obj, $refClass); + $objId = $this->mapper::getObjectId($obj); if ($this->mapper::isNullModel($obj)) { return $objId === 0 ? null : $objId; @@ -128,9 +128,7 @@ final class UpdateMapper extends DataMapperAbstract $property = $refClass->getProperty($propertyName); if (!($property->isPublic())) { - $property->setAccessible(true); $tValue = $property->getValue($obj); - $property->setAccessible(false); } else { $tValue = $obj->{$propertyName}; } @@ -244,9 +242,7 @@ final class UpdateMapper extends DataMapperAbstract $property = $refClass->getProperty($propertyName); if (!($isPublic = $property->isPublic())) { - $property->setAccessible(true); $values = $property->getValue($obj); - $property->setAccessible(false); } else { $values = $obj->{$propertyName}; } @@ -268,7 +264,7 @@ final class UpdateMapper extends DataMapperAbstract continue; } - $primaryKey = $mapper::getObjectId($value, $relReflectionClass); + $primaryKey = $mapper::getObjectId($value); // already in db if (!empty($primaryKey)) { @@ -290,9 +286,7 @@ final class UpdateMapper extends DataMapperAbstract $relProperty = $relReflectionClass->getProperty($mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']); if (!$isPublic) { - $relProperty->setAccessible(true); $relProperty->setValue($value, $objId); - $relProperty->setAccessible(false); } else { $value->{$mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']} = $objId; } diff --git a/DataStorage/Database/Mapper/WriteMapper.php b/DataStorage/Database/Mapper/WriteMapper.php index 6fe1d11e8..b6177680f 100755 --- a/DataStorage/Database/Mapper/WriteMapper.php +++ b/DataStorage/Database/Mapper/WriteMapper.php @@ -77,12 +77,12 @@ final class WriteMapper extends DataMapperAbstract $refClass = new \ReflectionClass($obj); if ($this->mapper::isNullModel($obj)) { - $objId = $this->mapper::getObjectId($obj, $refClass); + $objId = $this->mapper::getObjectId($obj); return $objId === 0 ? null : $objId; } - if (!empty($id = $this->mapper::getObjectId($obj, $refClass)) && $this->mapper::AUTOINCREMENT) { + if (!empty($id = $this->mapper::getObjectId($obj)) && $this->mapper::AUTOINCREMENT) { $objId = $id; } else { $objId = $this->createModel($obj, $refClass); @@ -163,7 +163,7 @@ final class WriteMapper extends DataMapperAbstract $sth = $this->db->con->prepare($a = $query->toSql()); $sth->execute(); - $objId = empty($id = $this->mapper::getObjectId($obj, $refClass)) ? $this->db->con->lastInsertId() : $id; + $objId = empty($id = $this->mapper::getObjectId($obj)) ? $this->db->con->lastInsertId() : $id; \settype($objId, $this->mapper::COLUMNS[$this->mapper::PRIMARYFIELD]['type']); return $objId; @@ -231,9 +231,7 @@ final class WriteMapper extends DataMapperAbstract $refProp = $refClass->getProperty($this->mapper::BELONGS_TO[$propertyName]['by']); if (!$refProp->isPublic()) { - $refProp->setAccessible(true); $obj = $refProp->getValue($obj); - $refProp->setAccessible(false); } else { $obj = $obj->{$this->mapper::BELONGS_TO[$propertyName]['by']}; } @@ -267,7 +265,6 @@ final class WriteMapper extends DataMapperAbstract $property = $refClass->getProperty($propertyName); if (!($isPublic = $property->isPublic())) { - $property->setAccessible(true); $values = $property->getValue($obj); } else { $values = $obj->{$propertyName}; @@ -294,25 +291,13 @@ final class WriteMapper extends DataMapperAbstract $values->{$internalName} = $objId; } - if (!$isPublic) { - $property->setAccessible(false); - } - $mapper::create(db: $this->db)->execute($values); continue; } elseif (!\is_array($values)) { - if (!$isPublic) { - $property->setAccessible(false); - } - // @todo: conditionals??? continue; } - if (!$isPublic) { - $property->setAccessible(false); - } - $objsIds = []; $relReflectionClass = !empty($values) ? new \ReflectionClass(\reset($values)) : null; @@ -325,7 +310,7 @@ final class WriteMapper extends DataMapperAbstract } /** @var \ReflectionClass $relReflectionClass */ - $primaryKey = $mapper::getObjectId($value, $relReflectionClass); + $primaryKey = $mapper::getObjectId($value); // already in db if (!empty($primaryKey)) { @@ -337,10 +322,7 @@ final class WriteMapper extends DataMapperAbstract // Setting relation value (id) for relation (since the relation is not stored in an extra relation table) if (!isset($this->mapper::HAS_MANY[$propertyName]['external'])) { $relProperty = $relReflectionClass->getProperty($internalName); - - if (!($isRelPublic = $relProperty->isPublic())) { - $relProperty->setAccessible(true); - } + $isRelPublic = $relProperty->isPublic(); // todo maybe consider to just set the column type to object, and then check for that (might be faster) if (isset($mapper::BELONGS_TO[$internalName]) diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index ffddecb98..0f1a55af5 100755 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -378,6 +378,10 @@ class Builder extends BuilderAbstract $dependencies[$table] = []; foreach ($this->ons[$table] as $on) { + if (!\is_string($on)) { + continue; + } + if (\stripos($on['column'], '.')) { $dependencies[$table][] = \explode('.', $on['column'])[0]; } @@ -1294,7 +1298,7 @@ class Builder extends BuilderAbstract * * @since 1.0.0 */ - public function on(string | array $columns, string | array $operator = null, string | array $values = null, string | array $boolean = 'and', string $table = null) : self + public function on(string | array $columns, string | array $operator = null, mixed $values = null, string | array $boolean = 'and', string $table = null) : self { if (!\is_array($columns)) { $columns = [$columns]; diff --git a/DataStorage/Database/Query/Grammar/Grammar.php b/DataStorage/Database/Query/Grammar/Grammar.php index 2125b65b2..d1f5f795b 100755 --- a/DataStorage/Database/Query/Grammar/Grammar.php +++ b/DataStorage/Database/Query/Grammar/Grammar.php @@ -452,6 +452,7 @@ class Grammar extends GrammarAbstract $expression .= '(' . \rtrim($this->compileWhereQuery($element['column']), ';') . ')'; } + // @todo: on doesn't allow values as value (only table column names). This is bad and needs to be fixed! if (isset($element['value'])) { $expression .= ' ' . \strtoupper($element['operator']) . ' ' . $this->compileSystem($element['value']); } else { diff --git a/Localization/BaseStringL11n.php b/Localization/BaseStringL11n.php index 80b8d3a33..c063318bc 100755 --- a/Localization/BaseStringL11n.php +++ b/Localization/BaseStringL11n.php @@ -33,7 +33,7 @@ class BaseStringL11n implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Name. @@ -63,7 +63,7 @@ class BaseStringL11n implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $language = ISO639x1Enum::_EN; + public string $language = ISO639x1Enum::_EN; /** * Country. @@ -71,7 +71,7 @@ class BaseStringL11n implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $country = ISO3166TwoEnum::_USA; + public string $country = ISO3166TwoEnum::_USA; /** * Content. diff --git a/Localization/BaseStringL11nType.php b/Localization/BaseStringL11nType.php index 47b177dd5..789251043 100644 --- a/Localization/BaseStringL11nType.php +++ b/Localization/BaseStringL11nType.php @@ -30,7 +30,7 @@ class BaseStringL11nType implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Identifier for the l11n type. diff --git a/Localization/Defaults/City.php b/Localization/Defaults/City.php index 90f5bcd9c..10d0b7f9c 100755 --- a/Localization/Defaults/City.php +++ b/Localization/Defaults/City.php @@ -30,7 +30,7 @@ class City * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Country code. diff --git a/Localization/Defaults/Country.php b/Localization/Defaults/Country.php index 517972458..e6a20fd54 100755 --- a/Localization/Defaults/Country.php +++ b/Localization/Defaults/Country.php @@ -30,7 +30,7 @@ class Country * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Country name. diff --git a/Localization/Defaults/Currency.php b/Localization/Defaults/Currency.php index 221b63c3c..639c8845e 100755 --- a/Localization/Defaults/Currency.php +++ b/Localization/Defaults/Currency.php @@ -30,7 +30,7 @@ class Currency * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Currency name. diff --git a/Localization/Defaults/Iban.php b/Localization/Defaults/Iban.php index a027bf9f0..19b41cbc5 100755 --- a/Localization/Defaults/Iban.php +++ b/Localization/Defaults/Iban.php @@ -30,7 +30,7 @@ class Iban * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Iban country. diff --git a/Localization/Defaults/Language.php b/Localization/Defaults/Language.php index 3fd08a359..8ceb2ad54 100755 --- a/Localization/Defaults/Language.php +++ b/Localization/Defaults/Language.php @@ -30,7 +30,7 @@ class Language * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Language name. diff --git a/Localization/ISO4217CharEnum.php b/Localization/ISO4217CharEnum.php index 6289f7daa..ba424b879 100755 --- a/Localization/ISO4217CharEnum.php +++ b/Localization/ISO4217CharEnum.php @@ -26,12 +26,18 @@ use phpOMS\Stdlib\Base\Enum; */ class ISO4217CharEnum extends Enum { + public const _AED = 'AED'; + public const _ALL = 'ALL'; + public const _AMD = 'AMD'; + public const _AFN = 'AFN'; public const _ARS = 'ARS'; + public const _AOA = 'AOA'; + public const _AWG = 'AWG'; public const _AUD = 'AUD'; @@ -90,8 +96,6 @@ class ISO4217CharEnum extends Enum public const _SVC = 'SVC'; - public const _EEK = 'EEK'; - public const _EUR = 'EUR'; public const _FKP = 'FKP'; @@ -253,4 +257,150 @@ class ISO4217CharEnum extends Enum public const _YER = 'YER'; public const _ZWD = 'ZWD'; + + public const _ZMK = 'ZMK'; + + public const _ZWL = 'ZWL'; + + public const _BDT = 'BDT'; + + public const _BHD = 'BHD'; + + public const _BIF = 'BIF'; + + public const _BOV = 'BOV'; + + public const _BTN = 'BTN'; + + public const _CDF = 'CDF'; + + public const _CHE = 'CHE'; + + public const _CHW = 'CHW'; + + public const _CLF = 'CLF'; + + public const _COU = 'COU'; + + public const _CUC = 'CUC'; + + public const _CVE = 'CVE'; + + public const _DJF = 'DJF'; + + public const _DZD = 'DZD'; + + public const _ERN = 'ERN'; + + public const _ETB = 'ETB'; + + public const _GEL = 'GEL'; + + public const _GHS = 'GHS'; + + public const _GMD = 'GMD'; + + public const _GNF = 'GNF'; + + public const _HTG = 'HTG'; + + public const _IQD = 'IQD'; + + public const _JOD = 'JOD'; + + public const _KMF = 'KMF'; + + public const _KWD = 'KWD'; + + public const _LSL = 'LSL'; + + public const _LYD = 'LYD'; + + public const _MAD = 'MAD'; + + public const _MDL = 'MDL'; + + public const _MGA = 'MGA'; + + public const _MMK = 'MMK'; + + public const _MOP = 'MOP'; + + public const _MRO = 'MRO'; + + public const _MVR = 'MVR'; + + public const _MWK = 'MWK'; + + public const _MXV = 'MXV'; + + public const _PGK = 'PGK'; + + public const _RWF = 'RWF'; + + public const _SDG = 'SDG'; + + public const _SLL = 'SLL'; + + public const _SSP = 'SSP'; + + public const _STD = 'STD'; + + public const _SZL = 'SZL'; + + public const _TJS = 'TJS'; + + public const _TMT = 'TMT'; + + public const _TND = 'TND'; + + public const _TOP = 'TOP'; + + public const _TZS = 'TZS'; + + public const _UGX = 'UGX'; + + public const _USN = 'USN'; + + public const _USS = 'USS'; + + public const _UYI = 'UYI'; + + public const _VUV = 'VUV'; + + public const _WST = 'WST'; + + public const _XAF = 'XAF'; + + public const _XAG = 'XAG'; + + public const _XAU = 'XAU'; + + public const _XBA = 'XBA'; + + public const _XBB = 'XBB'; + + public const _XBC = 'XBC'; + + public const _XBD = 'XBD'; + + public const _XDR = 'XDR'; + + public const _XFU = 'XFU'; + + public const _XOF = 'XOF'; + + public const _XPD = 'XPD'; + + public const _XPF = 'XPF'; + + public const _XPT = 'XPT'; + + public const _XSU = 'XSU'; + + public const _XTS = 'XTS'; + + public const _XUA = 'XUA'; + + public const _ZMW = 'ZMW'; } diff --git a/Localization/ISO4217DecimalEnum.php b/Localization/ISO4217DecimalEnum.php index 194521ae2..72d31e288 100755 --- a/Localization/ISO4217DecimalEnum.php +++ b/Localization/ISO4217DecimalEnum.php @@ -381,4 +381,28 @@ class ISO4217DecimalEnum extends Enum public const _ZAR = 2; public const _ZMW = 2; + + public const _GGP = 2; + + public const _GHC = 2; + + public const _IMP = 2; + + public const _JEP = 2; + + public const _LTL = 2; + + public const _LVL = 2; + + public const _SVC = 2; + + public const _TRL = 2; + + public const _TVD = 2; + + public const _ZWD = 2; + + public const _ZMK = 2; + + public const _ZWL = 2; } diff --git a/Localization/ISO4217Enum.php b/Localization/ISO4217Enum.php index dd2a99446..164097436 100755 --- a/Localization/ISO4217Enum.php +++ b/Localization/ISO4217Enum.php @@ -26,8 +26,12 @@ use phpOMS\Stdlib\Base\Enum; */ class ISO4217Enum extends Enum { + public const _AED = 'United Arab Emirates, Dirham'; + public const _ALL = 'Albania, Leke'; + public const _AMD = 'Armenian, Dram'; + public const _AFN = 'Afghanistan, Afghanis'; public const _ARS = 'Argentina, Pesos'; @@ -38,6 +42,8 @@ class ISO4217Enum extends Enum public const _AZN = 'Azerbaijan, New Manats'; + public const _AOA = 'Angolan, Kwanza'; + public const _BSD = 'Bahamas, Dollars'; public const _BBD = 'Barbados, Dollars'; @@ -90,8 +96,6 @@ class ISO4217Enum extends Enum public const _SVC = 'El Salvador, Colones'; - public const _EEK = 'Estonia, Krooni'; - public const _EUR = 'Euro'; public const _FKP = 'Falkland Islands, Pounds'; @@ -253,4 +257,150 @@ class ISO4217Enum extends Enum public const _YER = 'Yemen, Rials'; public const _ZWD = 'Zimbabwe, Zimbabwe Dollars'; + + public const _ZMK = 'Zambian, Kwacha'; + + public const _ZWL = 'Zimbabwean, Dollar'; + + public const _BDT = 'Bangladeshi, Taka'; + + public const _BHD = 'Bahraini, Dinar'; + + public const _BIF = 'Burundian, Franc'; + + public const _BOV = 'Bolivian, Mvdol'; + + public const _BTN = 'Bhutanes,e Ngultrum'; + + public const _CDF = 'Congolese, Franc'; + + public const _CHE = 'WIR Euro (complementary currency)'; + + public const _CHW = 'WIR Franc (complementary currency)'; + + public const _CLF = 'Unidad de Fomento (funds code)'; + + public const _COU = 'Unidad de Valor Real (UVR) (funds code)'; + + public const _CUC = 'Cuban convertible, Peso'; + + public const _CVE = 'Cape Verdean, Escudo'; + + public const _DJF = 'Djiboutian, Franc'; + + public const _DZD = 'Algerian, Dinar'; + + public const _ERN = 'Eritrean, Nakfa'; + + public const _ETB = 'Ethiopian, Birr'; + + public const _GEL = 'Georgian, Lari'; + + public const _GHS = 'Ghanaian, Cedi'; + + public const _GMD = 'Gambian, Dalasi'; + + public const _GNF = 'Guinean, Franc'; + + public const _HTG = 'Haitian, Gourde'; + + public const _IQD = 'Iraqi, Dinar'; + + public const _JOD = 'Jordanian, Dinar'; + + public const _KMF = 'Comorian, Franc'; + + public const _KWD = 'Kuwaiti, Dinar'; + + public const _LSL = 'Lesotho, Loti'; + + public const _LYD = 'Libyan, Dinar'; + + public const _MAD = 'Moroccan, Dirham'; + + public const _MDL = 'Moldovan, Leu'; + + public const _MGA = 'Malagasy, Ariary'; + + public const _MMK = 'Burmese, Kyat'; + + public const _MOP = 'Macanese, Pataca'; + + public const _MRO = 'Mauritanian, Ouguiya'; + + public const _MVR = 'Maldivian, Rufiyaa'; + + public const _MWK = 'Malawian, Kwacha'; + + public const _MXV = 'Mexican, Investment Unit'; + + public const _PGK = 'Papua New Guinean, Kina'; + + public const _RWF = 'Rwandan, Franc'; + + public const _SDG = 'Sudanese, Pound'; + + public const _SLL = 'Sierra Leonean, Leone'; + + public const _SSP = 'South Sudanese, Pound'; + + public const _STD = 'São Tomé and Príncipe, Dobra'; + + public const _SZL = 'Swazi, Lilangeni'; + + public const _TJS = 'Tajikistani, Somoni'; + + public const _TMT = 'Turkmenistani, Manat'; + + public const _TND = 'Tunisian, Dinar'; + + public const _TOP = 'Tongan, Paʻanga'; + + public const _TZS = 'Tanzanian, Shilling'; + + public const _UGX = 'Ugandan, Shilling'; + + public const _USN = 'United States dollar (next day) (funds code)'; + + public const _USS = 'United States dollar (same day) (funds code)'; + + public const _UYI = 'Uruguay Peso en Unidades Indexadas (URUIURUI) (funds code)'; + + public const _VUV = 'Vanuatu, Vatu'; + + public const _WST = 'Samoan, Tala'; + + public const _XAF = 'Central African, CFA Franc'; + + public const _XAG = 'Silver (one troy ounce)'; + + public const _XAU = 'Gold (one troy ounce)'; + + public const _XBA = 'European, Composite Unit (EURCO) (bond market unit)'; + + public const _XBB = 'European, Monetary Unit (E.M.U.-6) (bond market unit)'; + + public const _XBC = 'European, Unit of Account 9 (E.U.A.-9) (bond market unit)'; + + public const _XBD = 'European, Unit of Account 17 (E.U.A.-17) (bond market unit)'; + + public const _XDR = 'Special drawing rights'; + + public const _XFU = 'UIC franc (special settlement currency)'; + + public const _XOF = 'West African, CFA franc'; + + public const _XPD = 'Palladium'; + + public const _XPF = 'CFP franc'; + + public const _XPT = 'Platinum'; + + public const _XSU = 'Sucre'; + + public const _XTS = 'Testing Currency Code'; + + public const _XUA = 'ADB Unit of Account'; + + public const _ZMW = 'Zambian, kwacha'; } diff --git a/Localization/ISO4217NumEnum.php b/Localization/ISO4217NumEnum.php index 03e8be289..f6a2476b7 100755 --- a/Localization/ISO4217NumEnum.php +++ b/Localization/ISO4217NumEnum.php @@ -381,4 +381,16 @@ class ISO4217NumEnum extends Enum public const _ZAR = '710'; public const _ZMW = '967'; + + public const _GHC = '936'; + + public const _LTL = '440'; + + public const _LVL = '428'; + + public const _TRL = '949'; + + public const _ZMK = '894'; + + public const _ZWL = '932'; } diff --git a/Localization/ISO4217SubUnitEnum.php b/Localization/ISO4217SubUnitEnum.php index 0ce007f69..abed2bb14 100755 --- a/Localization/ISO4217SubUnitEnum.php +++ b/Localization/ISO4217SubUnitEnum.php @@ -40,6 +40,8 @@ class ISO4217SubUnitEnum extends Enum public const _AUD = 100; + public const _AOA = 100; + public const _AWG = 100; public const _BAM = 100; @@ -102,6 +104,8 @@ class ISO4217SubUnitEnum extends Enum public const _EGP = 100; + public const _GGP = 100; + public const _ERN = 100; public const _EUR = 100; @@ -333,4 +337,70 @@ class ISO4217SubUnitEnum extends Enum public const _ZMK = 100; public const _ZWL = 100; + + public const _GHC = 100; + + public const _IMP = 100; + + public const _JEP = 100; + + public const _TRL = 100; + + public const _TVD = 100; + + public const _ZWD = 100; + + public const _BOV = 100; + + public const _CHE = 100; + + public const _CHW = 100; + + public const _CLF = 10000; + + public const _COU = 100; + + public const _ETB = 100; + + public const _MXV = 100; + + public const _USN = 100; + + public const _USS = 100; + + public const _UYI = 0; + + public const _XAG = 0; + + public const _XAU = 0; + + public const _XBA = 0; + + public const _XBB = 0; + + public const _XBC = 0; + + public const _XBD = 0; + + public const _XDR = 0; + + public const _XFU = 0; + + public const _XPD = 0; + + public const _XPT = 0; + + public const _XSU = 0; + + public const _XTS = 0; + + public const _XUA = 0; + + public const _ZMW = 100; + + public const _AZN = 100; + + public const _CRC = 100; + + public const _GIP = 100; } diff --git a/Localization/ISO4217SymbolEnum.php b/Localization/ISO4217SymbolEnum.php index 23871f1de..83795e83e 100755 --- a/Localization/ISO4217SymbolEnum.php +++ b/Localization/ISO4217SymbolEnum.php @@ -26,8 +26,12 @@ use phpOMS\Stdlib\Base\Enum; */ class ISO4217SymbolEnum extends Enum { + public const _AED = 'د.إ'; + public const _ALL = 'Lek'; + public const _AMD = '֏'; + public const _AFN = '؋'; public const _ARS = '$'; @@ -38,6 +42,8 @@ class ISO4217SymbolEnum extends Enum public const _AZN = 'ман'; + public const _AOA = 'Kz'; + public const _BSD = '$'; public const _BBD = '$'; @@ -243,4 +249,156 @@ class ISO4217SymbolEnum extends Enum public const _YER = '﷼'; public const _ZWD = 'Z$'; + + public const _GHC = '₵'; + + public const _LTL = 'LTL'; + + public const _LVL = 'LVL'; + + public const _TRL = 'TRY'; + + public const _ZMK = 'ZK'; + + public const _ZWL = 'Z'; + + public const _BDT = '৳'; + + public const _BHD = 'BHD'; + + public const _BIF = 'BIF'; + + public const _BOV = 'BOV'; + + public const _BTN = '₹'; + + public const _CDF = 'CDF'; + + public const _CHE = 'CHF'; + + public const _CHW = 'CHF'; + + public const _CLF = 'CLF'; + + public const _COU = 'COU'; + + public const _CUC = '$;'; + + public const _CVE = '$;'; + + public const _DJF = 'DJF'; + + public const _DZD = 'DZD'; + + public const _ERN = 'ERN'; + + public const _ETB = 'ETB'; + + public const _GEL = '₾'; + + public const _GNF = 'GNF'; + + public const _HTG = 'HTG'; + + public const _IQD = 'IQD'; + + public const _JOD = 'JOD'; + + public const _KMF = 'KMF'; + + public const _KWD = 'KWD'; + + public const _LSL = 'LSL'; + + public const _LYD = 'LYD'; + + public const _MAD = 'MAD'; + + public const _MDL = 'MDL'; + + public const _MGA = 'MGA'; + + public const _MMK = 'MMK'; + + public const _MOP = 'MOP'; + + public const _MRO = 'MRO'; + + public const _MVR = 'MVR'; + + public const _MWK = 'MWK'; + + public const _MXV = 'MXV'; + + public const _PGK = 'PGK'; + + public const _RWF = 'RWF'; + + public const _SDG = '£'; + + public const _SLL = 'SLL'; + + public const _SSP = '£'; + + public const _STD = 'STD'; + + public const _SZL = 'SZL'; + + public const _TJS = 'TJS'; + + public const _TMT = 'TMT'; + + public const _TND = 'TND'; + + public const _TOP = 'T'; + + public const _TZS = 'TZS'; + + public const _UGX = 'UGX'; + + public const _USN = 'USN'; + + public const _USS = 'USS'; + + public const _UYI = 'UYI'; + + public const _VUV = 'VUV'; + + public const _WST = 'WST'; + + public const _XAF = 'XAF'; + + public const _XAG = 'XAG'; + + public const _XAU = 'XAU'; + + public const _XBA = 'XBA'; + + public const _XBB = 'XBB'; + + public const _XBC = 'XBC'; + + public const _XBD = 'XBD'; + + public const _XDR = 'XDR'; + + public const _XFU = 'XFU'; + + public const _XOF = 'XOF'; + + public const _XPD = 'XPD'; + + public const _XPF = 'XPF'; + + public const _XPT = 'XPT'; + + public const _XSU = 'XSU'; + + public const _XTS = 'XTS'; + + public const _XUA = 'XUA'; + + public const _ZMW = 'ZK'; + + public const _KES = 'KSh'; } diff --git a/Localization/ISO639x1Enum.php b/Localization/ISO639x1Enum.php index b787646e8..5ff3ec790 100755 --- a/Localization/ISO639x1Enum.php +++ b/Localization/ISO639x1Enum.php @@ -186,6 +186,8 @@ class ISO639x1Enum extends Enum public const _KR = 'kr'; + public const _KS = 'ks'; + public const _KK = 'kk'; public const _KM = 'km'; @@ -216,6 +218,8 @@ class ISO639x1Enum extends Enum public const _LT = 'lt'; + public const _LU = 'lu'; + public const _LV = 'lv'; public const _GV = 'gv'; @@ -294,6 +298,8 @@ class ISO639x1Enum extends Enum public const _SC = 'sc'; + public const _SD = 'sd'; + public const _SE = 'se'; public const _SM = 'sm'; @@ -350,10 +356,14 @@ class ISO639x1Enum extends Enum public const _TS = 'ts'; + public const _TT = 'tt'; + public const _TW = 'tw'; public const _TY = 'ty'; + public const _UG = 'ug'; + public const _UK = 'uk'; public const _UR = 'ur'; diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index ba2c873e4..4a4ef2ca7 100755 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -269,7 +269,7 @@ final class L11nManager */ public function getCurrency( Localization $l11n, - int | float | Money $currency, + int | float | Money | FloatInt $currency, string $symbol = null, string $format = null, int $divide = 1 @@ -292,6 +292,10 @@ final class L11nManager } } + if ($currency instanceof FloatInt) { + $currency = $currency->value; + } + $money = !($currency instanceof Money) ? new Money((int) ($currency / $divide)) : $currency; diff --git a/Localization/Localization.php b/Localization/Localization.php index fa20b8bc4..286dbd3c7 100755 --- a/Localization/Localization.php +++ b/Localization/Localization.php @@ -42,7 +42,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $country = ISO3166TwoEnum::_XXX; + public string $country = ISO3166TwoEnum::_XXX; /** * Timezone. @@ -50,7 +50,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $timezone = 'America/New_York'; + public string $timezone = 'America/New_York'; /** * Language ISO code. @@ -58,7 +58,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $language = ISO639x1Enum::_EN; + public string $language = ISO639x1Enum::_EN; /** * Currency. @@ -66,7 +66,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $currency = ISO4217CharEnum::_USD; + public string $currency = ISO4217CharEnum::_USD; /** * Currency format. @@ -74,7 +74,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $currencyFormat = '0'; + public string $currencyFormat = '0'; /** * Number format. @@ -82,7 +82,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $decimal = '.'; + public string $decimal = '.'; /** * Number format. @@ -90,7 +90,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $thousands = ','; + public string $thousands = ','; /** * Angle type. @@ -98,7 +98,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $angle = AngleType::DEGREE; + public string $angle = AngleType::DEGREE; /** * Temperature type. @@ -106,7 +106,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $temperature = TemperatureType::CELSIUS; + public string $temperature = TemperatureType::CELSIUS; /** * Precision. @@ -114,7 +114,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $precision = []; + public array $precision = []; /** * Time format. @@ -122,7 +122,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $datetime = []; + public array $datetime = []; /** * Weight. @@ -130,7 +130,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $weight = []; + public array $weight = []; /** * Speed. @@ -138,7 +138,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $speed = []; + public array $speed = []; /** * Length. @@ -146,7 +146,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $length = []; + public array $length = []; /** * Area. @@ -154,7 +154,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $area = []; + public array $area = []; /** * Volume. @@ -162,7 +162,7 @@ class Localization implements \JsonSerializable * @var array * @since 1.0.0 */ - protected array $volume = []; + public array $volume = []; /** * Country id. @@ -170,7 +170,7 @@ class Localization implements \JsonSerializable * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Get id @@ -273,7 +273,21 @@ class Localization implements \JsonSerializable return; } - $this->importLocale($json); + $this->language = $json['language'] ?? 'en'; + $this->country = $json['country'] ?? 'US'; + $this->currency = $json['currency']['code'] ?? ISO4217Enum::_USD; + $this->thousands = $json['thousand'] ?? ','; + $this->decimal = $json['decimal'] ?? '.'; + $this->angle = $json['angle'] ?? AngleType::DEGREE; + $this->temperature = $json['temperature'] ?? TemperatureType::CELSIUS; + $this->weight = $json['weight'] ?? []; + $this->speed = $json['speed'] ?? []; + $this->length = $json['length'] ?? []; + $this->area = $json['area'] ?? []; + $this->volume = $json['volume'] ?? []; + $this->precision = $json['precision'] ?? []; + $this->timezone = $json['timezone'] ?? 'America/New_York'; + $this->datetime = $json['datetime'] ?? []; return; } @@ -288,7 +302,21 @@ class Localization implements \JsonSerializable return; } - $this->importLocale($json); + $this->language = $json['language'] ?? 'en'; + $this->country = $json['country'] ?? 'US'; + $this->currency = $json['currency']['code'] ?? ISO4217Enum::_USD; + $this->thousands = $json['thousand'] ?? ','; + $this->decimal = $json['decimal'] ?? '.'; + $this->angle = $json['angle'] ?? AngleType::DEGREE; + $this->temperature = $json['temperature'] ?? TemperatureType::CELSIUS; + $this->weight = $json['weight'] ?? []; + $this->speed = $json['speed'] ?? []; + $this->length = $json['length'] ?? []; + $this->area = $json['area'] ?? []; + $this->volume = $json['volume'] ?? []; + $this->precision = $json['precision'] ?? []; + $this->timezone = $json['timezone'] ?? 'America/New_York'; + $this->datetime = $json['datetime'] ?? []; } /** diff --git a/Localization/Money.php b/Localization/Money.php index 76dc71f7b..b0992de55 100755 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -90,4 +90,12 @@ final class Money extends FloatInt { return $this->symbol; } + + public static function fromFloatInt(FloatInt $value) : self + { + $money = new self(); + $money->value = $value->value; + + return $money; + } } diff --git a/Message/Http/HttpHeader.php b/Message/Http/HttpHeader.php index 2f457d249..a97f34ffd 100755 --- a/Message/Http/HttpHeader.php +++ b/Message/Http/HttpHeader.php @@ -62,18 +62,23 @@ final class HttpHeader extends HeaderAbstract return false; } - $key = \strtolower($key); - if (self::isSecurityHeader($key) && isset($this->header[$key])) { + $key = \strtolower($key); + $exists = isset($this->header[$key]); + + if (!$overwrite && $exists) { return false; } - if (!$overwrite && isset($this->header[$key])) { + if ($exists && self::isSecurityHeader($key)) { return false; } - unset($this->header[$key]); + if ($exists && $overwrite) { + unset($this->header[$key]); + $exists = false; + } - if (!isset($this->header[$key])) { + if (!$exists) { $this->header[$key] = []; } diff --git a/Message/Http/HttpRequest.php b/Message/Http/HttpRequest.php index cbe51b744..322395dda 100755 --- a/Message/Http/HttpRequest.php +++ b/Message/Http/HttpRequest.php @@ -368,22 +368,11 @@ final class HttpRequest extends RequestAbstract * * @since 1.0.0 */ - public function getRequestLanguage() : string + private function getRequestLanguage() : string { - if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - return 'en'; - } - - // @codeCoverageIgnoreStart - $components = \explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']); - $locals = \stripos($components[0], ',') !== false - ? $locals = \explode(',', $components[0]) - : $components; - - $firstLocalComponents = \explode('-', $locals[0]); - // @codeCoverageIgnoreEnd - - $language = \strtolower($firstLocalComponents[0]); + $locale = $this->getLocale(); + $firstLocalComponents = \explode('_', $locale); + $language = \strtolower($firstLocalComponents[0]); return ISO639x1Enum::isValidValue($language) ? $language : 'en'; } @@ -395,22 +384,11 @@ final class HttpRequest extends RequestAbstract * * @since 1.0.0 */ - public function getRequestCountry() : string + private function getRequestCountry() : string { - if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - return ''; - } - - // @codeCoverageIgnoreStart - $components = \explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']); - $locals = \stripos($components[0], ',') !== false - ? $locals = \explode(',', $components[0]) - : $components; - - $firstLocalComponents = \explode('-', $locals[0]); - // @codeCoverageIgnoreEnd - - $country = \strtoupper($firstLocalComponents[1] ?? ''); + $locale = $this->getLocale(); + $firstLocalComponents = \explode('_', $locale); + $country = \strtoupper($firstLocalComponents[1] ?? ''); return ISO3166TwoEnum::isValidValue($country) ? $country : 'US'; } @@ -424,6 +402,10 @@ final class HttpRequest extends RequestAbstract */ public function getLocale() : string { + if (!empty($this->locale)) { + return $this->locale = $this->header->l11n->getLanguage() . '_' . $this->header->l11n->getCountry(); + } + if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { return 'en_US'; } @@ -435,7 +417,9 @@ final class HttpRequest extends RequestAbstract : $components; // @codeCoverageIgnoreEnd - return \str_replace('-', '_', $locals[0]); // @codeCoverageIgnore + $this->locale = \str_replace('-', '_', $locals[0]); // @codeCoverageIgnore + + return $this->locale; } /** diff --git a/Message/Mail/MailHandler.php b/Message/Mail/MailHandler.php index 5558f4873..c11dc55a9 100755 --- a/Message/Mail/MailHandler.php +++ b/Message/Mail/MailHandler.php @@ -170,7 +170,7 @@ class MailHandler * @var string * @since 1.0.0 */ - public string $dsn = DsnNotificationType::NONE; + public string $dsn = DsnNotificationLevel:NONE; /** * Keep connection alive. diff --git a/Message/Mail/Smtp.php b/Message/Mail/Smtp.php index 1d84830b9..d92195942 100755 --- a/Message/Mail/Smtp.php +++ b/Message/Mail/Smtp.php @@ -609,7 +609,7 @@ class Smtp * * @since 1.0.0 */ - public function recipient(string $address, string $dsn = DsnNotificationType::NONE) : bool + public function recipient(string $address, string $dsn = DsnNotificationLevel:NONE) : bool { if ($dsn === '') { $rcpt = 'RCPT TO:<' . $address . '>'; diff --git a/Message/RequestAbstract.php b/Message/RequestAbstract.php index 6645d2627..2ba5f80ec 100755 --- a/Message/RequestAbstract.php +++ b/Message/RequestAbstract.php @@ -66,6 +66,14 @@ abstract class RequestAbstract implements MessageInterface */ public HeaderAbstract $header; + /** + * Local + * + * @var string + * @since 1.0.0 + */ + protected string $locale = ''; + /** * Request hash. * @@ -141,7 +149,11 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - return isset($this->data[$key]) ? (string) $this->data[$key] : null; + if (($this->data[$key] ?? '') === '') { + return null; + } + + return (string) $this->data[$key]; } /** @@ -157,7 +169,11 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - return isset($this->data[$key]) ? (int) $this->data[$key] : null; + if (($this->data[$key] ?? '') === '') { + return null; + } + + return (int) $this->data[$key]; } /** @@ -173,7 +189,11 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - return isset($this->data[$key]) ? (float) $this->data[$key] : null; + if (($this->data[$key] ?? '') === '') { + return null; + } + + return (float) $this->data[$key]; } /** @@ -189,7 +209,11 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - return isset($this->data[$key]) ? (bool) $this->data[$key] : null; + if (($this->data[$key] ?? '') === '') { + return null; + } + + return (bool) $this->data[$key]; } /** @@ -221,7 +245,7 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - if (!isset($this->data[$key])) { + if (($this->data[$key] ?? '') === '') { return []; } @@ -244,7 +268,7 @@ abstract class RequestAbstract implements MessageInterface { $key = \mb_strtolower($key); - if (!isset($this->data[$key])) { + if (($this->data[$key] ?? '') === '') { return []; } diff --git a/Model/Message/NotifyType.php b/Model/Message/NotifyType.php deleted file mode 100755 index adc814d5f..000000000 --- a/Model/Message/NotifyType.php +++ /dev/null @@ -1,42 +0,0 @@ -getId() === 0) ) { return ['dest' => RouteStatus::NOT_LOGGED_IN]; } elseif (isset($d['permission']) && !empty($d['permission']) diff --git a/Router/WebRouter.php b/Router/WebRouter.php index f26b2f281..cd355f188 100755 --- a/Router/WebRouter.php +++ b/Router/WebRouter.php @@ -139,7 +139,7 @@ final class WebRouter implements RouterInterface // if permission check is invalid if (isset($d['permission']) && !empty($d['permission']) - && ($account === null || $account instanceof NullAccount) + && ($account === null || $account->getId() === 0) ) { return ['dest' => RouteStatus::NOT_LOGGED_IN]; } elseif (isset($d['permission']) && !empty($d['permission']) diff --git a/Security/EncryptionHelper.php b/Security/EncryptionHelper.php index 57321c18c..75bfaff5f 100755 --- a/Security/EncryptionHelper.php +++ b/Security/EncryptionHelper.php @@ -68,6 +68,45 @@ final class EncryptionHelper return $result; } + public static function encryptFile(string $in, string $out, string $keyHex) : bool + { + $fpSource = \fopen($in, 'r+'); + $fpEncoded = \fopen($out . '.tmp', 'w'); + + if ($fpSource === false || $fpEncoded === false) { + return false; + } + + $secretKey = \sodium_hex2bin($keyHex); + $nonce = \random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); + + while (($buffer = \fgets($fpSource, 4096)) !== false) { + $ciphertext = \sodium_crypto_secretbox($buffer, $nonce, $keyHex); + + \fwrite($fpEncoded, $ciphertext); + } + + \fclose($fpSource); + \fclose($fpEncoded); + + if ($in === $out) { + \unlink($in); + } + + \rename($out . '.tmp', $out); + + \sodium_memzero($nonce); + \sodium_memzero($secretKey); + \sodium_memzero($ciphertext); + + /* + \sodium_memzero($message); + \sodium_memzero($keyHex); + */ + + return true; + } + /** * Decrypt an encrypted message * @@ -80,6 +119,10 @@ final class EncryptionHelper */ public static function decryptShared(string $encrypted, string $keyHex) : string { + if ($encrypted === '' || $keyHex === '') { + return $encrypted; + } + $secretKey = \sodium_hex2bin($keyHex); $ciphertext = \sodium_base642bin($encrypted, SODIUM_BASE64_VARIANT_ORIGINAL); @@ -99,6 +142,47 @@ final class EncryptionHelper return $plaintext === false ? '' : $plaintext; } + public static function decryptFile(string $in, string $out, string $keyHex) : bool + { + $fpSource = \fopen($in, 'r+'); + $fpDecoded = \fopen($out . '.tmp', 'w'); + + if ($fpSource === false || $fpDecoded === false) { + return false; + } + + $secretKey = \sodium_hex2bin($keyHex); + + while (($buffer = \fgets($fpSource, 4096)) !== false) { + $ciphertext = \sodium_base642bin($buffer, SODIUM_BASE64_VARIANT_ORIGINAL); + $nonce = \mb_substr($ciphertext, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); + $ciphertext = \mb_substr($ciphertext, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit'); + + $plaintext = \sodium_crypto_secretbox_open($ciphertext, $nonce, $secretKey); + + \fwrite($fpDecoded, $plaintext); + } + + \fclose($fpSource); + \fclose($fpDecoded); + + if ($in === $out) { + \unlink($in); + } + + \rename($out . '.tmp', $out); + + \sodium_memzero($nonce); + \sodium_memzero($secretKey); + \sodium_memzero($ciphertext); + + /* + \sodium_memzero($keyHex); + */ + + return true; + } + /** * Create a paired keys. * @@ -174,6 +258,10 @@ final class EncryptionHelper */ public static function decryptSecret(string $encrypted, string $privateKeyHex, string $publicKeyHex) : string { + if ($encrypted === '' || $privateKeyHex === '' || $publicKeyHex === '') { + return $encrypted; + } + $privateKey = \sodium_hex2bin($privateKeyHex); $publicKey = \sodium_hex2bin($publicKeyHex); diff --git a/Stdlib/Base/Enum.php b/Stdlib/Base/Enum.php index f4026e93a..d38669fc8 100755 --- a/Stdlib/Base/Enum.php +++ b/Stdlib/Base/Enum.php @@ -39,7 +39,8 @@ abstract class Enum */ public static function isValidValue(mixed $value) : bool { - $constants = self::getConstants(); + $reflect = new \ReflectionClass(static::class); + $constants = $reflect->getConstants(); return \in_array($value, $constants, true); } @@ -67,7 +68,8 @@ abstract class Enum */ public static function getRandom() : mixed { - $constants = self::getConstants(); + $reflect = new \ReflectionClass(static::class); + $constants = $reflect->getConstants(); $keys = \array_keys($constants); return $constants[$keys[\mt_rand(0, \count($constants) - 1)]]; @@ -104,9 +106,10 @@ abstract class Enum */ public static function getName(string $value) : bool | int | string { - $arr = self::getConstants(); + $reflect = new \ReflectionClass(static::class); + $constants = $reflect->getConstants(); - return \array_search($value, $arr); + return \array_search($value, $constants); } /** diff --git a/Stdlib/Base/FloatInt.php b/Stdlib/Base/FloatInt.php index 58687e10a..3a658b555 100755 --- a/Stdlib/Base/FloatInt.php +++ b/Stdlib/Base/FloatInt.php @@ -40,7 +40,7 @@ class FloatInt implements SerializableInterface * @var string * @since 1.0.0 */ - protected string $thousands = ','; + public string $thousands = ','; /** * Decimal separator. @@ -48,7 +48,7 @@ class FloatInt implements SerializableInterface * @var string * @since 1.0.0 */ - protected string $decimal = '.'; + public string $decimal = '.'; /** * Value. @@ -56,7 +56,7 @@ class FloatInt implements SerializableInterface * @var int * @since 1.0.0 */ - protected int $value = 0; + public int $value = 0; /** * Constructor. diff --git a/Stdlib/Base/Location.php b/Stdlib/Base/Location.php index 27f96e3e6..4913b4368 100755 --- a/Stdlib/Base/Location.php +++ b/Stdlib/Base/Location.php @@ -33,7 +33,7 @@ class Location implements \JsonSerializable, SerializableInterface * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Zip or postal. diff --git a/Uri/UriFactory.php b/Uri/UriFactory.php index 3b3bbc78e..f07fd3e12 100755 --- a/Uri/UriFactory.php +++ b/Uri/UriFactory.php @@ -34,6 +34,8 @@ final class UriFactory */ private static array $uri = []; + private static ?\Closure $replaceFunction = null; + /** * Constructor. * @@ -299,9 +301,8 @@ final class UriFactory return $uri; } - $parsed = \preg_replace_callback( - '(\{[\/#\?%@\.\$][a-zA-Z0-9_\-]*\})', - function ($match) use ($toMatch) : string { + if (self::$replaceFunction === null) { + self::$replaceFunction = static function ($match) use ($toMatch) : string { $match = \substr($match[0], 1, \strlen($match[0]) - 2); return (string) ($toMatch[$match] @@ -311,7 +312,12 @@ final class UriFactory : '' ) )); - }, + }; + } + + $parsed = \preg_replace_callback( + '(\{[\/#\?%@\.\$][a-zA-Z0-9_\-]*\})', + self::$replaceFunction, $uri ); diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 2af6ee7d8..894054766 100755 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -76,6 +76,10 @@ abstract class SchedulerAbstract */ public static function guessBin() : bool { + if (self::$bin !== '') { + return true; + } + $paths = [ 'c:/WINDOWS/system32/schtasks.exe', 'd:/WINDOWS/system32/schtasks.exe', @@ -135,7 +139,7 @@ abstract class SchedulerAbstract $status = \proc_close($resource); - if ($status === -1) { + if ($status === -1 || $stderr !== '') { throw new \Exception((string) $stderr); } @@ -214,7 +218,7 @@ abstract class SchedulerAbstract /**+ * Reload the jobs - * + * * @return void * @since 1.0.0 */ diff --git a/Views/View.php b/Views/View.php index 03638df8f..861fab93c 100755 --- a/Views/View.php +++ b/Views/View.php @@ -350,7 +350,7 @@ class View extends ViewAbstract * @since 1.0.0 */ public function getCurrency( - int | float | Money $currency, + int | float | Money | FloatInt $currency, string $symbol = null, string $format = null, int $divide = 1 diff --git a/tests/DataStorage/Database/TestModel/BaseModel.php b/tests/DataStorage/Database/TestModel/BaseModel.php index 017de850f..276f4c075 100755 --- a/tests/DataStorage/Database/TestModel/BaseModel.php +++ b/tests/DataStorage/Database/TestModel/BaseModel.php @@ -18,7 +18,7 @@ use phpOMS\Contract\SerializableInterface; class BaseModel { - protected int $id = 0; + public int $id = 0; public string $string = 'Base'; diff --git a/tests/Localization/L11nManagerTest.php b/tests/Localization/L11nManagerTest.php index feb7f0ee2..26ae85f05 100755 --- a/tests/Localization/L11nManagerTest.php +++ b/tests/Localization/L11nManagerTest.php @@ -155,8 +155,8 @@ final class L11nManagerTest extends \PHPUnit\Framework\TestCase public function testGetCurrency() : void { $l11n = Localization::fromLanguage('en'); - self::assertEquals('USD 1.23', $this->l11nManager->getCurrency($l11n, 1.2345, 'medium')); - self::assertEquals('USD 1.235', $this->l11nManager->getCurrency($l11n, 1.2345, 'long')); + self::assertEquals('USD 1.23', $this->l11nManager->getCurrency($l11n, 1.2345, 'USD')); + self::assertEquals('USD 1.235', $this->l11nManager->getCurrency($l11n, 1.2345, 'USD')); $this->l11nManager->loadLanguage('en', '0', ['0' => ['CurrencyK' => 'K']]); $this->l11nManager->loadLanguage('en', '0', ['0' => ['CurrencyM' => 'M']]); diff --git a/tests/Localization/LocalizationTest.php b/tests/Localization/LocalizationTest.php index 558f7fd31..87499833b 100755 --- a/tests/Localization/LocalizationTest.php +++ b/tests/Localization/LocalizationTest.php @@ -41,22 +41,6 @@ final class LocalizationTest extends \PHPUnit\Framework\TestCase $this->localization = new Localization(); } - /** - * @testdox The localization has the expected member variables - * @covers phpOMS\Localization\Localization - * @group framework - */ - public function testAttributes() : void - { - self::assertObjectHasAttribute('country', $this->localization); - self::assertObjectHasAttribute('timezone', $this->localization); - self::assertObjectHasAttribute('language', $this->localization); - self::assertObjectHasAttribute('currency', $this->localization); - self::assertObjectHasAttribute('decimal', $this->localization); - self::assertObjectHasAttribute('thousands', $this->localization); - self::assertObjectHasAttribute('datetime', $this->localization); - } - /** * @testdox The localization has the expected default values after initialization * @covers phpOMS\Localization\Localization diff --git a/tests/Model/Message/NotifyTest.php b/tests/Model/Message/NotifyTest.php index 8e7c5f0cc..3bfbcf379 100755 --- a/tests/Model/Message/NotifyTest.php +++ b/tests/Model/Message/NotifyTest.php @@ -14,8 +14,8 @@ declare(strict_types=1); namespace phpOMS\tests\phpOMS\Model\Message; +use phpOMS\Message\NotificationLevel; use phpOMS\Model\Message\Notify; -use phpOMS\Model\Message\NotifyType; /** * @internal @@ -35,7 +35,7 @@ final class NotifyTest extends \PHPUnit\Framework\TestCase self::assertEquals('', $obj->toArray()['title']); self::assertEquals('', $obj->toArray()['msg']); self::assertEquals(0, $obj->toArray()['stay']); - self::assertEquals(NotifyType::INFO, $obj->toArray()['level']); + self::assertEquals(NotificationLevel::INFO, $obj->toArray()['level']); } /** @@ -44,10 +44,10 @@ final class NotifyTest extends \PHPUnit\Framework\TestCase */ public function testSetGet() : void { - $obj = new Notify('message', NotifyType::WARNING); + $obj = new Notify('message', NotificationLevel::WARNING); $obj->delay = 3; $obj->stay = 5; - $obj->level = NotifyType::ERROR; + $obj->level = NotificationLevel::ERROR; $obj->message ='msg'; $obj->title = 'title'; @@ -57,7 +57,7 @@ final class NotifyTest extends \PHPUnit\Framework\TestCase 'stay' => 5, 'msg' => 'msg', 'title' => 'title', - 'level' => NotifyType::ERROR, + 'level' => NotificationLevel::ERROR, ], $obj->toArray()); self::assertEquals(\json_encode([ @@ -66,7 +66,7 @@ final class NotifyTest extends \PHPUnit\Framework\TestCase 'stay' => 5, 'msg' => 'msg', 'title' => 'title', - 'level' => NotifyType::ERROR, + 'level' => NotificationLevel::ERROR, ]), $obj->serialize()); self::assertEquals([ @@ -75,7 +75,7 @@ final class NotifyTest extends \PHPUnit\Framework\TestCase 'stay' => 5, 'msg' => 'msg', 'title' => 'title', - 'level' => NotifyType::ERROR, + 'level' => NotificationLevel::ERROR, ], $obj->jsonSerialize()); $obj2 = new Notify(); diff --git a/tests/Model/Message/NotifyTypeTest.php b/tests/Model/Message/NotifyTypeTest.php deleted file mode 100755 index 6129d60b4..000000000 --- a/tests/Model/Message/NotifyTypeTest.php +++ /dev/null @@ -1,54 +0,0 @@ -app->l11nManager, null, new HttpResponse(Localization::fromLanguage('en'))); - self::assertEquals('USD 1.23', $view->getCurrency(1.2345, 'medium')); - self::assertEquals('USD 1.235', $view->getCurrency(1.2345, 'long')); + self::assertEquals('USD 1.23', $view->getCurrency(1.2345, 'USD')); + self::assertEquals('USD 1.235', $view->getCurrency(1.2345, 'USD')); $this->app->l11nManager->loadLanguage('en', '0', ['0' => ['CurrencyK' => 'K']]); self::assertEquals('K$ 12.345', $view->getCurrency(12345.0, 'long', '$', 1000));