diff --git a/.github/ISSUE_TEMPLATE/bugs.yml b/.github/ISSUE_TEMPLATE/bugs.yml new file mode 100644 index 000000000..ad1e90422 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bugs.yml @@ -0,0 +1,64 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug"] +assignees: + - spl1nes +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you if we need more info? + placeholder: ex. email@example.com + validations: + required: false + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "A bug happened!" + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - Alpha (Default) + default: 0 + validations: + required: true + - type: dropdown + id: browsers + attributes: + label: What browsers are you seeing the problem on? + multiple: true + options: + - Firefox + - Chrome + - Safari + - Opera + - Microsoft Edge + - Other + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/Ai/Ocr/Tesseract/TesseractOcr.php b/Ai/Ocr/Tesseract/TesseractOcr.php index d846222fd..36624a9b1 100755 --- a/Ai/Ocr/Tesseract/TesseractOcr.php +++ b/Ai/Ocr/Tesseract/TesseractOcr.php @@ -85,14 +85,34 @@ final class TesseractOcr * * @since 1.0.0 */ - public function parseImage(string $image, array $languages = ['eng'], int $psm = 3, int $oem = 3) : string + public function parseImage(string $image, array $languages = ['eng', 'deu'], int $psm = 3, int $oem = 3) : string { $temp = \tempnam(\sys_get_temp_dir(), 'oms_ocr_'); if ($temp === false) { return ''; } + $extension = 'png'; try { + // Tesseract needs higher dpi to work properly (identify + adjust if necessary) + $dpi = (int) \trim(\implode('', SystemUtils::runProc( + 'identify', + '-quiet -format "%x" ' . $image + ))); + + if ($dpi < 300) { + $split = \explode('.', $image); + $extension = \end($split); + + SystemUtils::runProc( + 'convert', + '-units PixelsPerInch ' . $image . ' -resample 300 ' . $temp . '.' . $extension + ); + + $image = $temp . '.' . $extension; + } + + // Do actual parsing SystemUtils::runProc( self::$bin, $image . ' ' @@ -100,12 +120,20 @@ final class TesseractOcr . ' -c preserve_interword_spaces=1' . ' --psm ' . $psm . ' --oem ' . $oem - . ' -l ' . \implode('+', $languages) + . (empty($languages) ? '' : ' -l ' . \implode('+', $languages)) ); } catch (\Throwable $_) { + if (\is_file($temp . '.' . $extension)) { + \unlink($temp . '.' . $extension); + } + return ''; } + if (\is_file($temp . '.' . $extension)) { + \unlink($temp . '.' . $extension); + } + $filepath = \is_file($temp . '.txt') ? $temp . '.txt' : $temp; @@ -120,11 +148,7 @@ final class TesseractOcr $parsed = \file_get_contents($filepath); if ($parsed === false) { - // @codeCoverageIgnoreStart - \unlink($temp); - - return ''; - // @codeCoverageIgnoreEnd + $parsed = ''; } \unlink($filepath); diff --git a/DataStorage/Database/BuilderAbstract.php b/DataStorage/Database/BuilderAbstract.php index e793d55d5..34a120f64 100755 --- a/DataStorage/Database/BuilderAbstract.php +++ b/DataStorage/Database/BuilderAbstract.php @@ -35,14 +35,6 @@ abstract class BuilderAbstract */ protected bool $isReadOnly = false; - /** - * Grammar. - * - * @var GrammarAbstract - * @since 1.0.0 - */ - protected GrammarAbstract $grammar; - /** * Database connection. * diff --git a/DataStorage/Database/GrammarAbstract.php b/DataStorage/Database/GrammarAbstract.php index 2ae41d70d..5fcd1891a 100755 --- a/DataStorage/Database/GrammarAbstract.php +++ b/DataStorage/Database/GrammarAbstract.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database; use phpOMS\Contract\SerializableInterface; -use phpOMS\DataStorage\Database\Query\Column; use phpOMS\DataStorage\Database\Query\ColumnName; use phpOMS\DataStorage\Database\Query\Parameter; @@ -61,22 +60,6 @@ abstract class GrammarAbstract */ public string $systemIdentifierEnd = '"'; - /** - * And operator. - * - * @var string - * @since 1.0.0 - */ - public string $and = 'AND'; - - /** - * Or operator. - * - * @var string - * @since 1.0.0 - */ - public string $or = 'OR'; - /** * Special keywords. * @@ -88,9 +71,6 @@ abstract class GrammarAbstract 'MAX(', 'MIN(', 'SUM(', - 'DATE(', - 'YEAR(', - 'MONTH(', ]; /** @@ -116,30 +96,7 @@ abstract class GrammarAbstract } /** - * Compile to query. - * - * @param BuilderAbstract $query Builder - * - * @return string - * - * @since 1.0.0 - */ - public function compileQuery(BuilderAbstract $query) : string - { - $components = $this->compileComponents($query); - $queryString = ''; - - foreach ($components as $component) { - if ($component !== '') { - $queryString .= $component . ' '; - } - } - - return \substr($queryString, 0, -1) . ';'; - } - - /** - * Compile post querys. + * Compile post queries. * * These are queries, which should be run after the main query (e.g. table alters, trigger definitions etc.) * @@ -149,7 +106,7 @@ abstract class GrammarAbstract * * @since 1.0.0 */ - public function compilePostQuerys(BuilderAbstract $query) : array + public function compilePostQueries(BuilderAbstract $query) : array { return []; } @@ -165,7 +122,7 @@ abstract class GrammarAbstract * * @since 1.0.0 */ - abstract protected function compileComponents(BuilderAbstract $query) : array; + abstract public function compileComponents(BuilderAbstract $query) : array; /** * Get date format. @@ -191,23 +148,20 @@ abstract class GrammarAbstract * * @since 1.0.0 */ - protected function expressionizeTableColumn(array $elements, bool $column = true) : string + public function expressionizeTableColumn(array $elements, bool $column = true) : string { $expression = ''; foreach ($elements as $key => $element) { if (\is_string($element)) { - $expression .= $this->compileSystem($element) - . (\is_string($key) ? ' as ' . $key : '') . ', '; + $expression .= $this->compileSystem($element) . (\is_string($key) ? ' AS ' . $key : '') . ', '; } elseif (\is_int($element)) { // example: select 1 $expression .= $element . ', '; - } elseif ($element instanceof \Closure) { - $expression .= $element() . (\is_string($key) ? ' as ' . $key : '') . ', '; } elseif ($element instanceof BuilderAbstract) { - $expression .= $element->toSql() . (\is_string($key) ? ' as ' . $key : '') . ', '; - } elseif (\is_int($element)) { - $expression .= $element . ', '; + $expression .= $element->toSql() . (\is_string($key) ? ' AS ' . $key : '') . ', '; + } elseif ($element instanceof \Closure) { + $expression .= $element() . (\is_string($key) ? ' AS ' . $key : '') . ', '; } else { throw new \InvalidArgumentException(); } @@ -241,9 +195,9 @@ abstract class GrammarAbstract $identifierEnd = ''; } elseif ((\stripos($system, '.')) !== false) { // This is actually slower than \explode(), despite knowing the first index - //$split = [\substr($system, 0, $pos), \substr($system, $pos + 1)]; + // $split = [\substr($system, 0, $pos), \substr($system, $pos + 1)]; - // Faster! But might requires more memory? + // Faster! But might require more memory? $split = \explode('.', $system); $identifierTwoStart = $identifierStart; @@ -298,8 +252,6 @@ abstract class GrammarAbstract return (string) ((int) $value); } elseif (\is_float($value)) { return \rtrim(\rtrim(\number_format($value, 5, '.', ''), '0'), '.'); - } elseif ($value instanceof Column) { - return '(' . \rtrim($this->compileColumnQuery($value), ';') . ')'; } elseif ($value instanceof ColumnName) { return $this->compileSystem($value->name); } elseif ($value instanceof BuilderAbstract) { @@ -316,18 +268,4 @@ abstract class GrammarAbstract throw new \InvalidArgumentException(\gettype($value)); } } - - /** - * Compile column query. - * - * @param Column $column Where query - * - * @return string - * - * @since 1.0.0 - */ - protected function compileColumnQuery(Column $column) : string - { - return $column->toSql(); - } } diff --git a/DataStorage/Database/Mapper/ReadMapper.php b/DataStorage/Database/Mapper/ReadMapper.php index d96470bb8..6fec4a196 100755 --- a/DataStorage/Database/Mapper/ReadMapper.php +++ b/DataStorage/Database/Mapper/ReadMapper.php @@ -291,6 +291,8 @@ final class ReadMapper extends DataMapperAbstract if (!empty($this->indexedBy)) { return $indexed; + } elseif ($this->type === MapperType::GET_ALL) { + return $objs; } $countResults = \count($objs); @@ -377,6 +379,16 @@ final class ReadMapper extends DataMapperAbstract $query ??= $this->getQuery(); try { + /* + \phpOMS\Log\FileLogger::getInstance()->info( + \phpOMS\Log\FileLogger::MSG_FULL, [ + 'message' => $query->toSql(), + 'line' => __LINE__, + 'file' => self::class, + ] + ); + */ + $sth = $this->db->con->prepare($query->toSql()); if ($sth === false) { yield []; @@ -559,6 +571,7 @@ final class ReadMapper extends DataMapperAbstract // This is necessary for special cases, e.g. when joining in the other direction // Example: Show all profiles who have written a news article. // "with()" only allows to go from articles to accounts but we want to go the other way + // // @feature Create join functionality for mappers which supports joining and filtering based on other tables // Example: show all profiles which have written a news article // https://github.com/Karaka-Management/phpOMS/issues/253 @@ -1124,8 +1137,9 @@ final class ReadMapper extends DataMapperAbstract $refClass = null; - // @todo check if there are more cases where the relation is already loaded with joins etc. - // there can be pseudo hasMany elements like localizations. They are hasMany but these are already loaded with joins! + // @todo Check if there are more cases where the relation is already loaded with joins etc. + // There can be pseudo hasMany elements like localizations. + // They are hasMany but these are already loaded with joins! foreach ($this->with as $member => $withData) { if (isset($this->mapper::HAS_MANY[$member])) { $many = $this->mapper::HAS_MANY[$member]; diff --git a/DataStorage/Database/Mapper/WriteMapper.php b/DataStorage/Database/Mapper/WriteMapper.php index fe87a3018..fbb45bead 100755 --- a/DataStorage/Database/Mapper/WriteMapper.php +++ b/DataStorage/Database/Mapper/WriteMapper.php @@ -26,6 +26,9 @@ use phpOMS\Utils\ArrayUtils; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Lock data for concurrency (e.g. table row lock or heartbeat) + * https://github.com/Karaka-Management/Karaka/issues/152 */ final class WriteMapper extends DataMapperAbstract { diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 03477610e..8698e2eb6 100755 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -18,6 +18,7 @@ use phpOMS\Algorithm\Graph\DependencyResolver; use phpOMS\Contract\SerializableInterface; use phpOMS\DataStorage\Database\BuilderAbstract; use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; +use phpOMS\DataStorage\Database\Query\Grammar\Grammar; /** * Database query builder. @@ -26,9 +27,22 @@ use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @question Consider to delete the builder but create a Select, Insert, ... builder + * Then directly call the compileSelect + compileFrom ... from the toSql + * This way the object generated would be much slimmer since we don't need to initialize empty data for + * Insert etc. We also wouldn't have to call compileComponents since this would happen directly in toSql(). */ class Builder extends BuilderAbstract { + /** + * Grammar. + * + * @var Grammar + * @since 1.0.0 + */ + protected Grammar $grammar; + /** * Log queries. * @@ -62,7 +76,9 @@ class Builder extends BuilderAbstract public array $updates = []; /** - * Stupid work around because value needs to be not null for it to work in Grammar. + * Deletes. + * + * @todo Find fix for stupid work around because value needs to be not null for it to work in Grammar. * * @var array * @since 1.0.0 @@ -354,7 +370,16 @@ class Builder extends BuilderAbstract $this->resolveJoinDependencies(); } - $query = $this->grammar->compileQuery($this); + $components = $this->grammar->compileComponents($this); + $queryString = ''; + + foreach ($components as $component) { + if ($component !== '') { + $queryString .= $component . ' '; + } + } + + $query = \substr($queryString, 0, -1) . ';'; if (self::$log) { \phpOMS\Log\FileLogger::getInstance()->debug($query); @@ -399,7 +424,7 @@ class Builder extends BuilderAbstract $resolved = DependencyResolver::resolve($dependencies); - // cyclomatic dependencies + // cyclic dependencies if ($resolved === null) { return; } @@ -816,76 +841,88 @@ class Builder extends BuilderAbstract */ public function __toString() { - return $this->grammar->compileQuery($this); - } + $components = $this->grammar->compileComponents($this); + $queryString = ''; - /** - * Find query. - * - * @return void - * - * @since 1.0.0 - */ - public function find() : void - { + foreach ($components as $component) { + if ($component !== '') { + $queryString .= $component . ' '; + } + } + + return \substr($queryString, 0, -1) . ';'; } /** * Count results. * - * @param string $table Table to count the result set + * @param string $column Table to count the result set * * @return Builder * * @since 1.0.0 */ - public function count(string $table = '*') : self + public function count(string $column = '*', ?string $as = null) : self { - return $this->select('COUNT(' . $table . ')'); + return $as === null + ? $this->select('COUNT(' . $column . ')') + : $this->selectAs('COUNT(' . $column . ')', $as); } /** * Select minimum. * - * @return void + * @return Builder * * @since 1.0.0 */ - public function min() : void + public function min(string $column = '*', ?string $as = null) : self { + return $as === null + ? $this->select('MIN(' . $column . ')') + : $this->selectAs('MIN(' . $column . ')', $as); } /** * Select maximum. * - * @return void + * @return Builder * * @since 1.0.0 */ - public function max() : void + public function max(string $column = '*', ?string $as = null) : self { + return $as === null + ? $this->select('MAX(' . $column . ')') + : $this->selectAs('MAX(' . $column . ')', $as); } /** * Select sum. * - * @return void + * @return Builder * * @since 1.0.0 */ - public function sum() : void + public function sum(string $column = '*', ?string $as = null) : self { + return $as === null + ? $this->select('SUM(' . $column . ')') + : $this->selectAs('SUM(' . $column . ')', $as); } /** * Select average. * - * @return void + * @return Builder * * @since 1.0.0 */ - public function avg() : void + public function avg(string $column = '*', ?string $as = null) : self { + return $as === null + ? $this->select('AVG(' . $column . ')') + : $this->selectAs('AVG(' . $column . ')', $as); } /** @@ -1059,28 +1096,6 @@ class Builder extends BuilderAbstract return $this; } - /** - * Increment value. - * - * @return void - * - * @since 1.0.0 - */ - public function increment() : void - { - } - - /** - * Decrement value. - * - * @return void - * - * @since 1.0.0 - */ - public function decrement() : void - { - } - /** * Join. * @@ -1282,7 +1297,7 @@ class Builder extends BuilderAbstract * @param string|array $columns Columns to join on * @param null|string|array $operator Comparison operator * @param null|string|array $values Values to compare with - * @param string|array $boolean Concatonator + * @param string|array $boolean Concatenation * @param null|string $table Table this belongs to * * @return Builder @@ -1354,29 +1369,16 @@ class Builder extends BuilderAbstract return $this->on($columns, $operator, $values, 'and'); } - /** - * Merging query. - * - * Merging query in order to remove database query volume - * - * @return Builder - * - * @since 1.0.0 - */ - public function merge() : self - { - return clone($this); - } - /** * {@inheritdoc} */ public function execute() : ?\PDOStatement { $sth = null; + $sql = ''; try { - $sth = $this->connection->con->prepare($this->toSql()); + $sth = $this->connection->con->prepare($sql = $this->toSql()); if ($sth === false) { return null; } @@ -1392,7 +1394,7 @@ class Builder extends BuilderAbstract // @codeCoverageIgnoreStart \phpOMS\Log\FileLogger::getInstance()->error( \phpOMS\Log\FileLogger::MSG_FULL, [ - 'message' => $t->getMessage() . ':' . $this->toSql(), + 'message' => $t->getMessage() . ':' . $sql, 'line' => __LINE__, 'file' => self::class, ] @@ -1442,8 +1444,6 @@ class Builder extends BuilderAbstract { if (\is_string($column)) { return $column; - } elseif ($column instanceof Column) { - return $column->getColumn(); } elseif ($column instanceof SerializableInterface) { return $column->serialize(); } elseif ($column instanceof self) { diff --git a/DataStorage/Database/Query/Column.php b/DataStorage/Database/Query/Column.php deleted file mode 100755 index 1311415c5..000000000 --- a/DataStorage/Database/Query/Column.php +++ /dev/null @@ -1,27 +0,0 @@ -type = QueryType::SELECT; + } + + public function columns(string $as, string $delim, ...$columns) : void + { + $this->delim = $delim; + $this->as = $as; + + $this->select($columns); + } + + /** + * {@inheritdoc} + */ + public function toSql() : string + { + $query = $this->grammar->compileConcat($this, $this->selects); + + if (self::$log) { + \phpOMS\Log\FileLogger::getInstance()->debug($query); + } + + return $query; + } +} \ No newline at end of file diff --git a/DataStorage/Database/Query/Count.php b/DataStorage/Database/Query/Count.php deleted file mode 100755 index 80f2cee39..000000000 --- a/DataStorage/Database/Query/Count.php +++ /dev/null @@ -1,27 +0,0 @@ -expressionizeTableColumn($columns) . ') AS ' . $query->as; + } + /** * Compile select. * @@ -244,14 +256,14 @@ class Grammar extends GrammarAbstract * Compile where. * * @param Builder $query Builder - * @param array $wheres Where elmenets + * @param array $wheres Where elements * @param bool $first Is first element (useful for nesting) * * @return string * * @since 1.0.0 */ - protected function compileWheres(Builder $query, array $wheres, bool $first = true) : string + public function compileWheres(Builder $query, array $wheres, bool $first = true) : string { $expression = ''; @@ -283,58 +295,46 @@ class Grammar extends GrammarAbstract protected function compileWhereElement(array $element, Builder $query, bool $first = true) : string { $expression = ''; + $prefix = ''; if (!$first) { - $expression = ' ' . \strtoupper($element['boolean']) . ' '; + $prefix = ' ' . \strtoupper($element['boolean']) . ' '; } if (\is_string($element['column'])) { $expression .= $this->compileSystem($element['column']); - } elseif ($element['column'] instanceof \Closure) { - $expression .= $element['column'](); - } elseif ($element['column'] instanceof Where) { - $where = \rtrim($this->compileWhereQuery($element['column']), ';'); - $expression .= '(' . (\str_starts_with($where, 'WHERE ') ? \substr($where, 6) : $where) . ')'; } elseif ($element['column'] instanceof Builder) { $expression .= '(' . \rtrim($element['column']->toSql(), ';') . ')'; + } elseif ($element['column'] instanceof \Closure) { + $expression .= $element['column'](); } - if (isset($element['value']) && (!empty($element['value']) || !\is_array($element['value']))) { + // Handle null for IN (...) + // This is not allowed and must be written as (IN (...) OR IS NULL) + $isArray = \is_array($element['value']); + $hasNull = false; + if ($isArray && ($key = \array_search(null, $element['value'], true)) !== false) { + $hasNull = true; + unset($element['value'][$key]); + + if (empty($element['value'])) { + $element['operator'] = '='; + $element['value'] = null; + } + } + + if (isset($element['value']) && (!empty($element['value']) || !$isArray)) { $expression .= ' ' . \strtoupper($element['operator']) . ' ' . $this->compileValue($query, $element['value']); + + if ($hasNull) { + $expression = '(' . $expression . ' OR ' . $this->compileSystem($element['column']) . ' IS NULL)'; + } } elseif ($element['value'] === null && !($element['column'] instanceof Builder)) { $operator = $element['operator'] === '=' ? 'IS' : 'IS NOT'; $expression .= ' ' . $operator . ' ' . $this->compileValue($query, $element['value']); } - return $expression; - } - - /** - * Compile where query. - * - * @param Where $where Where query - * - * @return string - * - * @since 1.0.0 - */ - protected function compileWhereQuery(Where $where) : string - { - return $where->toSql(); - } - - /** - * Compile from query. - * - * @param From $from Where query - * - * @return string - * - * @since 1.0.0 - */ - protected function compileFromQuery(From $from) : string - { - return $from->toSql(); + return $prefix . $expression; } /** @@ -445,18 +445,16 @@ class Grammar extends GrammarAbstract } if (\is_string($element['column'])) { - // handle bug when no table is specified in the where column + // @bug Handle bug when no table is specified in the where column if (\count($query->from) === 1 && \stripos($element['column'], '.') === false) { $element['column'] = $query->from[0] . '.' . $element['column']; } $expression .= $this->compileSystem($element['column']); - } elseif ($element['column'] instanceof \Closure) { - $expression .= $element['column'](); } elseif ($element['column'] instanceof Builder) { $expression .= '(' . $element['column']->toSql() . ')'; - } elseif ($element['column'] instanceof Where) { - $expression .= '(' . \rtrim($this->compileWhereQuery($element['column']), ';') . ')'; + } elseif ($element['column'] instanceof \Closure) { + $expression .= $element['column'](); } // @bug The on part of a join doesn't allow string values because they conflict with column name diff --git a/DataStorage/Database/Query/Grammar/GrammarInterface.php b/DataStorage/Database/Query/Grammar/GrammarInterface.php deleted file mode 100755 index b09613f33..000000000 --- a/DataStorage/Database/Query/Grammar/GrammarInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -compileFrom($query, $query->from) . ' ORDER BY RANDOM() ' . $this->compileLimit($query, $query->limit ?? 1); } + + /** + * Create concat + * + * @param Concat $query Builder + * @param array $columns Columns + * + * @return string + * + * @since 1.0.0 + */ + public function compileConcat(\phpOMS\DataStorage\Database\Query\Concat $query, array $columns) : string + { + $sql = $this->expressionizeTableColumn($columns); + $sql = \str_replace(',', ' ||', $sql); + + return $sql . ' AS ' . $query->as; + } } diff --git a/DataStorage/Database/Query/Into.php b/DataStorage/Database/Query/Into.php deleted file mode 100755 index 9f42cc754..000000000 --- a/DataStorage/Database/Query/Into.php +++ /dev/null @@ -1,27 +0,0 @@ -type = QueryType::SELECT; } + + /** + * {@inheritdoc} + */ + public function toSql() : string + { + $query = $this->grammar->compileWheres($this, $this->wheres); + $query = \str_starts_with($query, 'WHERE ') ? \substr($query, 6) : $query; + + if (self::$log) { + \phpOMS\Log\FileLogger::getInstance()->debug($query); + } + + return $query; + } } diff --git a/DataStorage/Database/Schema/Builder.php b/DataStorage/Database/Schema/Builder.php index 0d6a2bb59..ce3787c55 100755 --- a/DataStorage/Database/Schema/Builder.php +++ b/DataStorage/Database/Schema/Builder.php @@ -16,6 +16,7 @@ namespace phpOMS\DataStorage\Database\Schema; use phpOMS\DataStorage\Database\BuilderAbstract; use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; +use phpOMS\DataStorage\Database\Schema\Grammar\Grammar; /** * Database query builder. @@ -29,6 +30,14 @@ use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; */ class Builder extends BuilderAbstract { + /** + * Grammar. + * + * @var Grammar + * @since 1.0.0 + */ + protected Grammar $grammar; + /** * Table to create. * @@ -260,7 +269,7 @@ class Builder extends BuilderAbstract * @param bool $isNullable Can be null * @param bool $isPrimary Is a primary field * @param bool $isUnique Is a unique field - * @param bool $autoincrement Autoincrements + * @param bool $autoincrement Auto increments * @param string $foreignTable Foreign table (in case of foreign key) * @param string $foreignKey Foreign key * @param array $meta Meta data @@ -335,9 +344,10 @@ class Builder extends BuilderAbstract public function execute() : ?\PDOStatement { $sth = null; + $sql = ''; try { - $sth = $this->connection->con->prepare($this->toSql()); + $sth = $this->connection->con->prepare($sql = $this->toSql()); if ($sth === false) { return null; } @@ -347,14 +357,19 @@ class Builder extends BuilderAbstract if ($this->hasPostQuery) { $sqls = $this->grammar->compilePostQueries($this); - foreach ($sqls as $sql) { - $this->connection->con->exec($sql); + foreach ($sqls as $post) { + $this->connection->con->exec($post); } } } catch (\Throwable $t) { // @codeCoverageIgnoreStart - \var_dump($t->getMessage()); - \var_dump($this->toSql()); + \phpOMS\Log\FileLogger::getInstance()->error( + \phpOMS\Log\FileLogger::MSG_FULL, [ + 'message' => $t->getMessage() . ':' . $sql, + 'line' => __LINE__, + 'file' => self::class, + ] + ); $sth = null; // @codeCoverageIgnoreEnd @@ -368,6 +383,15 @@ class Builder extends BuilderAbstract */ public function toSql() : string { - return $this->grammar->compileQuery($this); + $components = $this->grammar->compileComponents($this); + $queryString = ''; + + foreach ($components as $component) { + if ($component !== '') { + $queryString .= $component . ' '; + } + } + + return \substr($queryString, 0, -1) . ';'; } } diff --git a/DataStorage/Database/Schema/Grammar/Grammar.php b/DataStorage/Database/Schema/Grammar/Grammar.php index eb43c1c2f..79ce26d58 100755 --- a/DataStorage/Database/Schema/Grammar/Grammar.php +++ b/DataStorage/Database/Schema/Grammar/Grammar.php @@ -32,7 +32,7 @@ class Grammar extends GrammarAbstract /** * {@inheritdoc} */ - protected function compileComponents(BuilderAbstract $query) : array + public function compileComponents(BuilderAbstract $query) : array { /** @var SchemaBuilder $query */ diff --git a/DataStorage/Database/Schema/Grammar/GrammarInterface.php b/DataStorage/Database/Schema/Grammar/GrammarInterface.php deleted file mode 100755 index a396f2b4b..000000000 --- a/DataStorage/Database/Schema/Grammar/GrammarInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -error( + FileLogger::getInstance()->warning( FileLogger::MSG_FULL, [ - 'message' => 'Bad application flow.', + 'message' => 'Headers already sent.', 'line' => __LINE__, 'file' => self::class, ] diff --git a/Localization/ISO3166Trait.php b/Localization/ISO3166Trait.php index 39aa6ffd4..3e050a500 100644 --- a/Localization/ISO3166Trait.php +++ b/Localization/ISO3166Trait.php @@ -44,6 +44,479 @@ trait ISO3166Trait return self::getByName($code3); } + /** + * Get country from language. + * + * @param string $language Language 2 code + * + * @return array + * + * @since 1.0.0 + */ + public static function countryFromLanguage(string $language) : array + { + switch (\strtolower($language)) { + case ISO639x1Enum::_PS: + return [ + self::_AFG, + ]; + case ISO639x1Enum::_UZ: + return [ + self::_AFG, self::_UZB, + ]; + case ISO639x1Enum::_TK: + return [ + self::_AFG, self::_TKM, + ]; + case ISO639x1Enum::_SV: + return [ + self::_ALA, self::_FIN, self::_SWE, + ]; + case ISO639x1Enum::_SQ: + return [ + self::_ALB, self::_MNE, + ]; + case ISO639x1Enum::_AR: + return [ + self::_DZA, self::_BHR, self::_TCD, self::_COM, self::_DJI, self::_EGY, self::_ERI, self::_ETH, self::_IRQ, self::_ISR, self::_JOR, self::_KWT, self::_LBN, self::_LBY, self::_MRT, self::_MAR, self::_OMN, self::_PSE, self::_QAT, self::_SAU, self::_SOM, self::_SDN, self::_SYR, self::_TUN, self::_ARE, self::_ESH, self::_YEM, + ]; + case ISO639x1Enum::_EN: + return [ + self::_USA, self::_ASM, self::_AIA, self::_ATA, self::_ATG, self::_AUS, self::_BHS, self::_BRB, self::_BLZ, self::_BMU, self::_BES, self::_BWA, self::_IOT, self::_CMR, self::_CAN, self::_CYM, self::_CXR, self::_CCK, self::_COK, self::_CUW, self::_DMA, self::_ERI, self::_FLK, self::_FJI, self::_GMB, self::_GHA, self::_GIB, self::_GRD, self::_GUM, self::_GGY, self::_GUY, self::_HMD, self::_HKG, self::_IND, self::_IRL, self::_IMN, self::_JAM, self::_JEY, self::_KEN, self::_KIR, self::_LSO, self::_LBR, self::_MWI, self::_MLT, self::_MHL, self::_MUS, self::_FSM, self::_MSR, self::_NAM, self::_NRU, self::_NZL, self::_NGA, self::_NIU, self::_NFK, self::_MNP, self::_PAK, self::_PLW, self::_PNG, self::_PHL, self::_PCN, self::_PRI, self::_RWA, self::_SHN, self::_KNA, self::_LCA, self::_MAF, self::_VCT, self::_WSM, self::_SYC, self::_SLE, self::_SGP, self::_SXM, self::_SLB, self::_SOM, self::_ZAF, self::_SGS, self::_SSD, self::_LKA, self::_SDN, self::_SWZ, self::_TZA, self::_TKL, self::_TON, self::_TTO, self::_TCA, self::_TUV, self::_UGA, self::_GBR, self::_UMI, self::_VUT, self::_VGB, self::_VIR, self::_ZMB, self::_ZWE, + ]; + case ISO639x1Enum::_SM: + return [ + self::_ASM, self::_WSM, + ]; + case ISO639x1Enum::_CA: + return [ + self::_AND, + ]; + case ISO639x1Enum::_PT: + return [ + self::_AGO, self::_BRA, self::_CPV, self::_GNQ, self::_GNB, self::_MAC, self::_MOZ, self::_PRT, self::_STP, self::_TLS, + ]; + case ISO639x1Enum::_RU: + return [ + self::_ATA, self::_ARM, self::_AZE, self::_BLR, self::_KAZ, self::_KGZ, self::_RUS, self::_TJK, self::_TKM, self::_UZB, + ]; + case ISO639x1Enum::_ES: + return [ + self::_ARG, self::_BOL, self::_CHL, self::_COL, self::_CRI, self::_CUB, self::_DOM, self::_ECU, self::_SLV, self::_GNQ, self::_GUM, self::_GTM, self::_HND, self::_MEX, self::_NIC, self::_PAN, self::_PRY, self::_PER, self::_PRI, self::_ESP, self::_USA, self::_URY, self::_VEN, self::_ESH, + ]; + case ISO639x1Enum::_GN: + return [ + self::_ARG, self::_PRY, + ]; + case ISO639x1Enum::_HY: + return [ + self::_ARM, self::_AZE, + ]; + case ISO639x1Enum::_NL: + return [ + self::_ABW, self::_BEL, self::_BES, self::_CUW, self::_NLD, self::_MAF, self::_SXM, self::_SUR, + ]; + case ISO639x1Enum::_DE: + return [ + self::_DEU, self::_AUT, self::_BEL, self::_LIE, self::_LUX, self::_CHE, + ]; + case ISO639x1Enum::_AZ: + return [ + self::_AZE, + ]; + case ISO639x1Enum::_BN: + return [ + self::_BGD, + ]; + case ISO639x1Enum::_BE: + return [ + self::_BLR, + ]; + case ISO639x1Enum::_FR: + return [ + self::_BEL, self::_BEN, self::_BFA, self::_BDI, self::_CMR, self::_CAN, self::_CAF, self::_TCD, self::_COM, self::_COG, self::_COD, self::_CIV, self::_DJI, self::_GNQ, self::_FRA, self::_GUF, self::_PYF, self::_ATF, self::_GAB, self::_GLP, self::_GGY, self::_GIN, self::_HTI, self::_JEY, self::_LBN, self::_LUX, self::_MDG, self::_MLI, self::_MTQ, self::_MRT, self::_MUS, self::_MYT, self::_MCO, self::_NCL, self::_NER, self::_REU, self::_RWA, self::_BLM, self::_MAF, self::_SPM, self::_SEN, self::_SYC, self::_CHE, self::_TGO, self::_VUT, self::_WLF, + ]; + case ISO639x1Enum::_DZ: + return [ + self::_BTN, + ]; + case ISO639x1Enum::_QU: + return [ + self::_BOL, self::_PER, + ]; + case ISO639x1Enum::_AY: + return [ + self::_BOL, self::_PER, + ]; + case ISO639x1Enum::_BS: + return [ + self::_BIH, self::_MNE, self::_XXK, + ]; + case ISO639x1Enum::_HR: + return [ + self::_BIH, self::_HRV, self::_MNE, + ]; + case ISO639x1Enum::_SR: + return [ + self::_BIH, self::_MNE, self::_SRB, + ]; + case ISO639x1Enum::_TN: + return [ + self::_BWA, self::_ZAF, + ]; + case ISO639x1Enum::_NO: + return [ + self::_BVT, self::_NOR, self::_SJM, + ]; + case ISO639x1Enum::_MS: + return [ + self::_BRN, self::_MYS, self::_SGP, + ]; + case ISO639x1Enum::_BG: + return [ + self::_BGR, + ]; + case ISO639x1Enum::_RN: + return [ + self::_BDI, + ]; + case ISO639x1Enum::_KM: + return [ + self::_KHM, + ]; + case ISO639x1Enum::_SG: + return [ + self::_CAF, + ]; + case ISO639x1Enum::_ZH: + return [ + self::_CHN, self::_HKG, self::_MAC, self::_PLW, self::_SGP, self::_TWN, + ]; + case ISO639x1Enum::_LN: + return [ + self::_COG, self::_COD, + ]; + case ISO639x1Enum::_KG: + return [ + self::_COG, self::_COD, + ]; + case ISO639x1Enum::_SW: + return [ + self::_COG, self::_COD, self::_KEN, self::_TZA, self::_UGA, + ]; + case ISO639x1Enum::_PA: + return [ + self::_CUW, + ]; + case ISO639x1Enum::_EL: + return [ + self::_CYP, self::_GRC, + ]; + case ISO639x1Enum::_TR: + return [ + self::_CYP, self::_TUR, self::_XXK, + ]; + case ISO639x1Enum::_CS: + return [ + self::_CZE, + ]; + case ISO639x1Enum::_SK: + return [ + self::_CZE, self::_SVK, + ]; + case ISO639x1Enum::_DA: + return [ + self::_DNK, + ]; + case ISO639x1Enum::_SO: + return [ + self::_DJI, self::_ETH, self::_SOM, + ]; + case ISO639x1Enum::_TI: + return [ + self::_ERI, self::_ETH, + ]; + case ISO639x1Enum::_ET: + return [ + self::_EST, + ]; + case ISO639x1Enum::_AM: + return [ + self::_ETH, + ]; + case ISO639x1Enum::_OM: + return [ + self::_ETH, + ]; + case ISO639x1Enum::_FO: + return [ + self::_FRO, + ]; + case ISO639x1Enum::_FJ: + return [ + self::_FJI, + ]; + case ISO639x1Enum::_HI: + return [ + self::_FJI, self::_IND, + ]; + case ISO639x1Enum::_UR: + return [ + self::_FJI, self::_PAK, + ]; + case ISO639x1Enum::_FI: + return [ + self::_FIN, + ]; + case ISO639x1Enum::_TY: + return [ + self::_PYF, + ]; + case ISO639x1Enum::_KA: + return [ + self::_GEO, + ]; + case ISO639x1Enum::_KL: + return [ + self::_GRL, + ]; + case ISO639x1Enum::_CH: + return [ + self::_GUM, self::_MNP, + ]; + case ISO639x1Enum::_HT: + return [ + self::_HTI, + ]; + case ISO639x1Enum::_IT: + return [ + self::_VAT, self::_ITA, self::_SMR, self::_SOM, self::_CHE, + ]; + case ISO639x1Enum::_LA: + return [ + self::_VAT, + ]; + case ISO639x1Enum::_HU: + return [ + self::_HUN, + ]; + case ISO639x1Enum::_IS: + return [ + self::_ISL, + ]; + case ISO639x1Enum::_ID: + return [ + self::_IDN, + ]; + case ISO639x1Enum::_FA: + return [ + self::_IRN, + ]; + case ISO639x1Enum::_KU: + return [ + self::_IRQ, + ]; + case ISO639x1Enum::_GA: + return [ + self::_IRL, self::_GBR, + ]; + case ISO639x1Enum::_GV: + return [ + self::_IMN, + ]; + case ISO639x1Enum::_HE: + return [ + self::_ISR, + ]; + case ISO639x1Enum::_JA: + return [ + self::_JPN, self::_PLW, + ]; + case ISO639x1Enum::_KK: + return [ + self::_KAZ, + ]; + case ISO639x1Enum::_KO: + return [ + self::_PRK, self::_KOR, + ]; + case ISO639x1Enum::_KY: + return [ + self::_KGZ, + ]; + case ISO639x1Enum::_LO: + return [ + self::_LAO, + ]; + case ISO639x1Enum::_LV: + return [ + self::_LVA, + ]; + case ISO639x1Enum::_ST: + return [ + self::_LSO, self::_ZAF, + ]; + case ISO639x1Enum::_LT: + return [ + self::_LTU, + ]; + case ISO639x1Enum::_LB: + return [ + self::_LUX, + ]; + case ISO639x1Enum::_MK: + return [ + self::_MKD, + ]; + case ISO639x1Enum::_MG: + return [ + self::_MDG, + ]; + case ISO639x1Enum::_NY: + return [ + self::_MWI, + ]; + case ISO639x1Enum::_DV: + return [ + self::_MDV, + ]; + case ISO639x1Enum::_MT: + return [ + self::_MLT, + ]; + case ISO639x1Enum::_MH: + return [ + self::_MHL, + ]; + case ISO639x1Enum::_RO: + return [ + self::_MDA, self::_ROU, + ]; + case ISO639x1Enum::_MN: + return [ + self::_MNG, + ]; + case ISO639x1Enum::_MY: + return [ + self::_MMR, + ]; + case ISO639x1Enum::_AF: + return [ + self::_NAM, self::_ZAF, + ]; + case ISO639x1Enum::_NA: + return [ + self::_NRU, + ]; + case ISO639x1Enum::_NE: + return [ + self::_NPL, + ]; + case ISO639x1Enum::_MI: + return [ + self::_NZL, + ]; + case ISO639x1Enum::_NB: + return [ + self::_NOR, + ]; + case ISO639x1Enum::_NN: + return [ + self::_NOR, + ]; + case ISO639x1Enum::_HO: + return [ + self::_PNG, + ]; + case ISO639x1Enum::_PL: + return [ + self::_POL, + ]; + case ISO639x1Enum::_RW: + return [ + self::_RWA, + ]; + case ISO639x1Enum::_WO: + return [ + self::_SEN, + ]; + case ISO639x1Enum::_TA: + return [ + self::_SGP, self::_LKA, + ]; + case ISO639x1Enum::_SL: + return [ + self::_SVN, + ]; + case ISO639x1Enum::_ZU: + return [ + self::_ZAF, + ]; + case ISO639x1Enum::_XH: + return [ + self::_ZAF, + ]; + case ISO639x1Enum::_TS: + return [ + self::_ZAF, + ]; + case ISO639x1Enum::_SS: + return [ + self::_ZAF, self::_SWZ, + ]; + case ISO639x1Enum::_VE: + return [ + self::_ZAF, + ]; + case ISO639x1Enum::_SI: + return [ + self::_LKA, + ]; + case ISO639x1Enum::_TG: + return [ + self::_TJK, + ]; + case ISO639x1Enum::_TH: + return [ + self::_THA, + ]; + case ISO639x1Enum::_TO: + return [ + self::_TON, + ]; + case ISO639x1Enum::_UK: + return [ + self::_UKR, + ]; + case ISO639x1Enum::_CY: + return [ + self::_GBR, + ]; + case ISO639x1Enum::_GD: + return [ + self::_GBR, + ]; + case ISO639x1Enum::_BI: + return [ + self::_VUT, + ]; + case ISO639x1Enum::_VI: + return [ + self::_VNM, + ]; + case ISO639x1Enum::_SN: + return [ + self::_ZWE, + ]; + case ISO639x1Enum::_ND: + return [ + self::_ZWE, + ]; + default: + return []; + } + } + /** * Get countries in a region * diff --git a/Localization/ISO4217CharEnum.php b/Localization/ISO4217CharEnum.php index 108571a1d..f35a9a2e0 100755 --- a/Localization/ISO4217CharEnum.php +++ b/Localization/ISO4217CharEnum.php @@ -75,6 +75,8 @@ class ISO4217CharEnum extends Enum public const _CLP = 'CLP'; public const _CNY = 'CNY'; + public const _CNH = 'CNH'; + public const _RMB = 'RMB'; public const _COP = 'COP'; @@ -403,4 +405,6 @@ class ISO4217CharEnum extends Enum public const _XUA = 'XUA'; public const _ZMW = 'ZMW'; + + use ISO4217Trait; } diff --git a/Localization/ISO4217DecimalEnum.php b/Localization/ISO4217DecimalEnum.php index a5dc42125..23f758dfd 100755 --- a/Localization/ISO4217DecimalEnum.php +++ b/Localization/ISO4217DecimalEnum.php @@ -93,6 +93,8 @@ class ISO4217DecimalEnum extends Enum public const _CLP = 0; public const _CNY = 2; + public const _CNH = 2; + public const _RMB = 2; public const _COP = 2; diff --git a/Localization/ISO4217Enum.php b/Localization/ISO4217Enum.php index 1ae94b490..458458b1a 100755 --- a/Localization/ISO4217Enum.php +++ b/Localization/ISO4217Enum.php @@ -75,6 +75,8 @@ class ISO4217Enum extends Enum public const _CLP = 'Pesos, Chile'; public const _CNY = 'Yuan Renminbi, China'; + public const _CNH = 'Yuan Renminbi, China'; + public const _RMB = 'Yuan Renminbi, China'; public const _COP = 'Pesos, Colombia'; @@ -403,4 +405,6 @@ class ISO4217Enum extends Enum public const _XUA = 'ADB Unit of Account'; public const _ZMW = 'kwacha, Zambian'; + + use ISO4217Trait; } diff --git a/Localization/ISO4217NumEnum.php b/Localization/ISO4217NumEnum.php index 29bf818ce..f75c56176 100755 --- a/Localization/ISO4217NumEnum.php +++ b/Localization/ISO4217NumEnum.php @@ -93,6 +93,8 @@ class ISO4217NumEnum extends Enum public const _CLP = '152'; public const _CNY = '156'; + public const _CNH = '156'; + public const _RMB = '156'; public const _COP = '170'; @@ -393,4 +395,6 @@ class ISO4217NumEnum extends Enum public const _ZMK = '894'; public const _ZWL = '932'; + + use ISO4217Trait; } diff --git a/Localization/ISO4217SubUnitEnum.php b/Localization/ISO4217SubUnitEnum.php index 06d7d4911..0bcbe52d7 100755 --- a/Localization/ISO4217SubUnitEnum.php +++ b/Localization/ISO4217SubUnitEnum.php @@ -83,6 +83,8 @@ class ISO4217SubUnitEnum extends Enum public const _CLP = 100; public const _CNY = 100; + public const _CNH = 100; + public const _RMB = 100; public const _COP = 100; diff --git a/Localization/ISO4217SymbolEnum.php b/Localization/ISO4217SymbolEnum.php index 7f223b7d1..aeff629e7 100755 --- a/Localization/ISO4217SymbolEnum.php +++ b/Localization/ISO4217SymbolEnum.php @@ -75,6 +75,8 @@ class ISO4217SymbolEnum extends Enum public const _CLP = '$'; public const _CNY = '¥'; + public const _CNH = '¥'; + public const _RMB = '¥'; public const _COP = '$'; @@ -401,4 +403,6 @@ class ISO4217SymbolEnum extends Enum public const _ZMW = 'ZK'; public const _KES = 'KSh'; + + use ISO4217Trait; } diff --git a/Localization/ISO4217Trait.php b/Localization/ISO4217Trait.php new file mode 100644 index 000000000..65cf44fc2 --- /dev/null +++ b/Localization/ISO4217Trait.php @@ -0,0 +1,483 @@ + currency trait. + * + * @package phpOMS\Localization + * @license OMS License 2.0 + * @link https://jingga.app + * @since 1.0.0 + */ +trait ISO4217Trait +{ + /** + * Get currency from country. + * + * @param string $country Country 2 code + * + * @return array + * + * @since 1.0.0 + */ + public static function currencyFromCountry(string $country) : string + { + switch (\strtoupper($country)) { + case ISO3166TwoEnum::_AFG: + return self::_USD; + case ISO3166TwoEnum::_ALA: + return self::_EUR; + case ISO3166TwoEnum::_ALB: + return self::_EUR; + case ISO3166TwoEnum::_DZA: + return self::_DZD; + case ISO3166TwoEnum::_ASM: + return self::_USD; + case ISO3166TwoEnum::_AND: + return self::_EUR; + case ISO3166TwoEnum::_AGO: + return self::_AOA; + case ISO3166TwoEnum::_AIA: + return self::_XCD; + case ISO3166TwoEnum::_ATG: + return self::_XCD; + case ISO3166TwoEnum::_ARG: + return self::_ARS; + case ISO3166TwoEnum::_ARM: + return self::_AMD; + case ISO3166TwoEnum::_ABW: + return self::_AWG; + case ISO3166TwoEnum::_AUS: + return self::_AUD; + case ISO3166TwoEnum::_AUT: + return self::_EUR; + case ISO3166TwoEnum::_AZE: + return self::_AZM; + case ISO3166TwoEnum::_PRT: + return self::_EUR; + case ISO3166TwoEnum::_BHS: + return self::_BSD; + case ISO3166TwoEnum::_BHR: + return self::_BHD; + case ISO3166TwoEnum::_BGD: + return self::_BDT; + case ISO3166TwoEnum::_BRB: + return self::_BBD; + case ISO3166TwoEnum::_BLR: + return self::_BYR; + case ISO3166TwoEnum::_BEL: + return self::_EUR; + case ISO3166TwoEnum::_BLZ: + return self::_BZD; + case ISO3166TwoEnum::_BEN: + return self::_XOF; + case ISO3166TwoEnum::_BMU: + return self::_BMD; + case ISO3166TwoEnum::_BTN: + return self::_BTN; + case ISO3166TwoEnum::_BOL: + return self::_BOB; + case ISO3166TwoEnum::_BES: + return self::_ANG; + case ISO3166TwoEnum::_BIH: + return self::_BAM; + case ISO3166TwoEnum::_BWA: + return self::_BWP; + case ISO3166TwoEnum::_BRA: + return self::_BRL; + case ISO3166TwoEnum::_VGB: + return self::_USD; + case ISO3166TwoEnum::_BRN: + return self::_BND; + case ISO3166TwoEnum::_BGR: + return self::_EUR; + case ISO3166TwoEnum::_BFA: + return self::_XOF; + case ISO3166TwoEnum::_BDI: + return self::_BIF; + case ISO3166TwoEnum::_KHM: + return self::_KHR; + case ISO3166TwoEnum::_CMR: + return self::_XAF; + case ISO3166TwoEnum::_CAN: + return self::_CAD; + case ISO3166TwoEnum::_ESP: + return self::_EUR; + case ISO3166TwoEnum::_CPV: + return self::_CVE; + case ISO3166TwoEnum::_CYM: + return self::_KYD; + case ISO3166TwoEnum::_CAF: + return self::_XAF; + case ISO3166TwoEnum::_TCD: + return self::_XAF; + case ISO3166TwoEnum::_CHL: + return self::_CLP; + case ISO3166TwoEnum::_CHN: + return self::_CNY; + case ISO3166TwoEnum::_COL: + return self::_COP; + case ISO3166TwoEnum::_COM: + return self::_USD; + case ISO3166TwoEnum::_COG: + return self::_XAF; + case ISO3166TwoEnum::_COD: + return self::_CDF; + case ISO3166TwoEnum::_COK: + return self::_NZD; + case ISO3166TwoEnum::_CRI: + return self::_CRC; + case ISO3166TwoEnum::_HRV: + return self::_EUR; + case ISO3166TwoEnum::_CUW: + return self::_USD; + case ISO3166TwoEnum::_CYP: + return self::_EUR; + case ISO3166TwoEnum::_CZE: + return self::_CZK; + case ISO3166TwoEnum::_DNK: + return self::_DKK; + case ISO3166TwoEnum::_DJI: + return self::_DJF; + case ISO3166TwoEnum::_DMA: + return self::_XCD; + case ISO3166TwoEnum::_DOM: + return self::_DOP; + case ISO3166TwoEnum::_TLS: + return self::_USD; + case ISO3166TwoEnum::_ECU: + return self::_USD; + case ISO3166TwoEnum::_EGY: + return self::_EGP; + case ISO3166TwoEnum::_SLV: + return self::_USD; + case ISO3166TwoEnum::_GBR: + return self::_GBP; + case ISO3166TwoEnum::_GNQ: + return self::_XAF; + case ISO3166TwoEnum::_ERI: + return self::_ERN; + case ISO3166TwoEnum::_EST: + return self::_EUR; + case ISO3166TwoEnum::_ETH: + return self::_ETB; + case ISO3166TwoEnum::_FRO: + return self::_DKK; + case ISO3166TwoEnum::_FJI: + return self::_FJD; + case ISO3166TwoEnum::_FIN: + return self::_EUR; + case ISO3166TwoEnum::_FRA: + return self::_EUR; + case ISO3166TwoEnum::_GUF: + return self::_EUR; + case ISO3166TwoEnum::_PYF: + return self::_XPF; + case ISO3166TwoEnum::_GAB: + return self::_XAF; + case ISO3166TwoEnum::_GMB: + return self::_GMD; + case ISO3166TwoEnum::_GEO: + return self::_GEL; + case ISO3166TwoEnum::_DEU: + return self::_EUR; + case ISO3166TwoEnum::_GHA: + return self::_GHS; + case ISO3166TwoEnum::_GIB: + return self::_GIP; + case ISO3166TwoEnum::_GRC: + return self::_EUR; + case ISO3166TwoEnum::_GRL: + return self::_DKK; + case ISO3166TwoEnum::_GRD: + return self::_XCD; + case ISO3166TwoEnum::_GLP: + return self::_EUR; + case ISO3166TwoEnum::_GUM: + return self::_USD; + case ISO3166TwoEnum::_GTM: + return self::_GTQ; + case ISO3166TwoEnum::_GGY: + return self::_GBP; + case ISO3166TwoEnum::_GIN: + return self::_GNF; + case ISO3166TwoEnum::_GNB: + return self::_XOF; + case ISO3166TwoEnum::_GUY: + return self::_GYD; + case ISO3166TwoEnum::_HTI: + return self::_HTG; + case ISO3166TwoEnum::_NLD: + return self::_EUR; + case ISO3166TwoEnum::_HND: + return self::_HNL; + case ISO3166TwoEnum::_HKG: + return self::_HKD; + case ISO3166TwoEnum::_HUN: + return self::_HUF; + case ISO3166TwoEnum::_ISL: + return self::_ISK; + case ISO3166TwoEnum::_IND: + return self::_INR; + case ISO3166TwoEnum::_IDN: + return self::_IDR; + case ISO3166TwoEnum::_IRQ: + return self::_NID; + case ISO3166TwoEnum::_IRL: + return self::_EUR; + case ISO3166TwoEnum::_ISR: + return self::_ILS; + case ISO3166TwoEnum::_ITA: + return self::_EUR; + case ISO3166TwoEnum::_CIV: + return self::_XOF; + case ISO3166TwoEnum::_JAM: + return self::_JMD; + case ISO3166TwoEnum::_JPN: + return self::_JPY; + case ISO3166TwoEnum::_JEY: + return self::_GBP; + case ISO3166TwoEnum::_JOR: + return self::_JOD; + case ISO3166TwoEnum::_KAZ: + return self::_KZT; + case ISO3166TwoEnum::_KEN: + return self::_KES; + case ISO3166TwoEnum::_KIR: + return self::_AUD; + case ISO3166TwoEnum::_KOR: + return self::_KRW; + case ISO3166TwoEnum::_FSM: + return self::_USD; + case ISO3166TwoEnum::_KWT: + return self::_KWD; + case ISO3166TwoEnum::_KGZ: + return self::_KGS; + case ISO3166TwoEnum::_LAO: + return self::_LAK; + case ISO3166TwoEnum::_LVA: + return self::_EUR; + case ISO3166TwoEnum::_LBN: + return self::_LBP; + case ISO3166TwoEnum::_LSO: + return self::_LSL; + case ISO3166TwoEnum::_LBR: + return self::_LRD; + case ISO3166TwoEnum::_LBY: + return self::_LYD; + case ISO3166TwoEnum::_LIE: + return self::_CHF; + case ISO3166TwoEnum::_LTU: + return self::_EUR; + case ISO3166TwoEnum::_LUX: + return self::_EUR; + case ISO3166TwoEnum::_MAC: + return self::_MOP; + case ISO3166TwoEnum::_MKD: + return self::_EUR; + case ISO3166TwoEnum::_MDG: + return self::_MGA; + case ISO3166TwoEnum::_MWI: + return self::_MWK; + case ISO3166TwoEnum::_MYS: + return self::_MYR; + case ISO3166TwoEnum::_MDV: + return self::_MVR; + case ISO3166TwoEnum::_MLI: + return self::_XOF; + case ISO3166TwoEnum::_MLT: + return self::_EUR; + case ISO3166TwoEnum::_MHL: + return self::_USD; + case ISO3166TwoEnum::_MTQ: + return self::_EUR; + case ISO3166TwoEnum::_MRT: + return self::_MRO; + case ISO3166TwoEnum::_MUS: + return self::_MUR; + case ISO3166TwoEnum::_MYT: + return self::_EUR; + case ISO3166TwoEnum::_MEX: + return self::_MXN; + case ISO3166TwoEnum::_MDA: + return self::_MDL; + case ISO3166TwoEnum::_MCO: + return self::_EUR; + case ISO3166TwoEnum::_MNG: + return self::_MNT; + case ISO3166TwoEnum::_MNE: + return self::_EUR; + case ISO3166TwoEnum::_MSR: + return self::_XCD; + case ISO3166TwoEnum::_MAR: + return self::_MAD; + case ISO3166TwoEnum::_MOZ: + return self::_MZM; + case ISO3166TwoEnum::_NAM: + return self::_NAD; + case ISO3166TwoEnum::_NPL: + return self::_NPR; + case ISO3166TwoEnum::_NCL: + return self::_XPF; + case ISO3166TwoEnum::_NZL: + return self::_NZD; + case ISO3166TwoEnum::_NIC: + return self::_NIO; + case ISO3166TwoEnum::_NER: + return self::_XOF; + case ISO3166TwoEnum::_NGA: + return self::_NGN; + case ISO3166TwoEnum::_NFK: + return self::_AUD; + case ISO3166TwoEnum::_MNP: + return self::_USD; + case ISO3166TwoEnum::_NOR: + return self::_NOK; + case ISO3166TwoEnum::_OMN: + return self::_OMR; + case ISO3166TwoEnum::_PAK: + return self::_PKR; + case ISO3166TwoEnum::_PLW: + return self::_USD; + case ISO3166TwoEnum::_PAN: + return self::_PAB; + case ISO3166TwoEnum::_PNG: + return self::_PGK; + case ISO3166TwoEnum::_PRY: + return self::_PYG; + case ISO3166TwoEnum::_PER: + return self::_PEN; + case ISO3166TwoEnum::_PHL: + return self::_PHP; + case ISO3166TwoEnum::_POL: + return self::_PLN; + case ISO3166TwoEnum::_PRI: + return self::_USD; + case ISO3166TwoEnum::_QAT: + return self::_QAR; + case ISO3166TwoEnum::_REU: + return self::_EUR; + case ISO3166TwoEnum::_ROU: + return self::_ROL; + case ISO3166TwoEnum::_RUS: + return self::_RUB; + case ISO3166TwoEnum::_RWA: + return self::_RWF; + case ISO3166TwoEnum::_WSM: + return self::_WST; + case ISO3166TwoEnum::_SMR: + return self::_EUR; + case ISO3166TwoEnum::_STP: + return self::_STD; + case ISO3166TwoEnum::_SAU: + return self::_SAR; + case ISO3166TwoEnum::_SEN: + return self::_XOF; + case ISO3166TwoEnum::_SRB: + return self::_EUR; + case ISO3166TwoEnum::_SYC: + return self::_SCR; + case ISO3166TwoEnum::_SLE: + return self::_SLL; + case ISO3166TwoEnum::_SGP: + return self::_SGD; + case ISO3166TwoEnum::_SVK: + return self::_EUR; + case ISO3166TwoEnum::_SVN: + return self::_EUR; + case ISO3166TwoEnum::_SLB: + return self::_SBD; + case ISO3166TwoEnum::_ZAF: + return self::_ZAR; + case ISO3166TwoEnum::_LKA: + return self::_LKR; + case ISO3166TwoEnum::_BLM: + return self::_EUR; + case ISO3166TwoEnum::_KNA: + return self::_XCD; + case ISO3166TwoEnum::_VIR: + return self::_USD; + case ISO3166TwoEnum::_LCA: + return self::_XCD; + case ISO3166TwoEnum::_SXM: + return self::_USD; + case ISO3166TwoEnum::_VCT: + return self::_XCD; + case ISO3166TwoEnum::_SUR: + return self::_SRG; + case ISO3166TwoEnum::_SWZ: + return self::_SZL; + case ISO3166TwoEnum::_SWE: + return self::_SEK; + case ISO3166TwoEnum::_CHE: + return self::_CHF; + case ISO3166TwoEnum::_TWN: + return self::_TWD; + case ISO3166TwoEnum::_TJK: + return self::_TJS; + case ISO3166TwoEnum::_TZA: + return self::_TZS; + case ISO3166TwoEnum::_THA: + return self::_THB; + case ISO3166TwoEnum::_TGO: + return self::_XOF; + case ISO3166TwoEnum::_TON: + return self::_TOP; + case ISO3166TwoEnum::_TTO: + return self::_TTD; + case ISO3166TwoEnum::_TUN: + return self::_TND; + case ISO3166TwoEnum::_TUR: + return self::_TRY; + case ISO3166TwoEnum::_TKM: + return self::_TMT; + case ISO3166TwoEnum::_TCA: + return self::_USD; + case ISO3166TwoEnum::_TUV: + return self::_AUD; + case ISO3166TwoEnum::_UGA: + return self::_UGX; + case ISO3166TwoEnum::_UKR: + return self::_UAH; + case ISO3166TwoEnum::_ARE: + return self::_AED; + case ISO3166TwoEnum::_USA: + return self::_USD; + case ISO3166TwoEnum::_URY: + return self::_UYU; + case ISO3166TwoEnum::_UZB: + return self::_UZS; + case ISO3166TwoEnum::_VUT: + return self::_VUV; + case ISO3166TwoEnum::_VAT: + return self::_EUR; + case ISO3166TwoEnum::_VEN: + return self::_VEB; + case ISO3166TwoEnum::_VNM: + return self::_VND; + case ISO3166TwoEnum::_WLF: + return self::_XPF; + case ISO3166TwoEnum::_YEM: + return self::_YER; + case ISO3166TwoEnum::_ZMB: + return self::_ZMK; + case ISO3166TwoEnum::_ZWE: + return self::_ZWD; + default: + return ''; + } + } +} diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index 4b6e49737..fd57eced6 100755 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -235,18 +235,19 @@ final class L11nManager /** * Print a percentage value * - * @param Localization $l11n Localization - * @param float $percentage Percentage value to print - * @param null|string $format Format type to use + * @param Localization $l11n Localization + * @param float|FloatInt $percentage Percentage value to print + * @param null|string $format Format type to use * * @return string * * @since 1.0.0 */ - public function getPercentage(Localization $l11n, float $percentage, ?string $format = null) : string + public function getPercentage(Localization $l11n, float | FloatInt $percentage, ?string $format = null) : string { return \number_format( - $percentage, $l11n->getPrecision()[$format ?? 'medium'], + \is_float($percentage) ? $percentage : $percentage->value / (FloatInt::DIVISOR * 100), + $l11n->getPrecision()[$format ?? 'medium'], $l11n->getDecimal(), $l11n->getThousands() ) . '%'; @@ -277,7 +278,7 @@ final class L11nManager $symbol ??= $l11n->currency; if (\is_float($currency)) { - $currency = (int) ($currency * \pow(10, Money::MAX_DECIMALS)); + $currency = (int) ($currency * FloatInt::DIVISOR); } if ($divide > 1 && !empty($symbol)) { diff --git a/Localization/LanguageDetection/Language.php b/Localization/LanguageDetection/Language.php index 0a4662e9f..d9b253831 100755 --- a/Localization/LanguageDetection/Language.php +++ b/Localization/LanguageDetection/Language.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpOMS\Localization\LanguageDetection; /** - * Langauge detection class + * Language detection class * * @package phpOMS\Localization\LanguageDetection * @license https://opensource.org/licenses/mit-license.html MIT diff --git a/Localization/LanguageDetection/LanguageResult.php b/Localization/LanguageDetection/LanguageResult.php index 6495bf822..643b76884 100755 --- a/Localization/LanguageDetection/LanguageResult.php +++ b/Localization/LanguageDetection/LanguageResult.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpOMS\Localization\LanguageDetection; /** - * Langauge match result + * Language match result * * @package phpOMS\Localization\LanguageDetection * @license https://opensource.org/licenses/mit-license.html MIT @@ -43,7 +43,7 @@ class LanguageResult implements \ArrayAccess, \IteratorAggregate, \JsonSerializa /** * Constructor. * - * @param array $result Langauge match results + * @param array $result Language match results * * @since 1.0.0 */ diff --git a/Localization/LanguageDetection/Trainer.php b/Localization/LanguageDetection/Trainer.php index cd6eb9e36..ba480fa39 100755 --- a/Localization/LanguageDetection/Trainer.php +++ b/Localization/LanguageDetection/Trainer.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpOMS\Localization\LanguageDetection; /** - * Langauge training class + * Language training class * * @package phpOMS\Localization\LanguageDetection * @license https://opensource.org/licenses/mit-license.html MIT diff --git a/Localization/RegionEnum.php b/Localization/RegionEnum.php index 64df63c8c..65b1133dc 100644 --- a/Localization/RegionEnum.php +++ b/Localization/RegionEnum.php @@ -32,6 +32,16 @@ class RegionEnum extends Enum public const EURO = 'Euro'; + public const OECD = 'OECD'; + + public const NATO = 'NATO'; + + public const SCHENGEN = 'Schengen'; + + public const P5 = 'P5'; + + public const G8 = 'G8'; + public const NORTH_EUROPE = 'North-Europe'; public const SOUTH_EUROPE = 'South-Europe'; @@ -93,4 +103,6 @@ class RegionEnum extends Enum public const DOMESTIC = 'Domestic'; public const EXPORT = 'Export'; + + public const DACH = 'DACH'; } diff --git a/Math/Functions/Functions.php b/Math/Functions/Functions.php index c69eedda1..153a9e3a7 100755 --- a/Math/Functions/Functions.php +++ b/Math/Functions/Functions.php @@ -196,6 +196,11 @@ final class Functions return $a % $b; } + public static function modFloat(float $a, float $b) : float + { + return $a - ((int) ($a / $b)) * $b; + } + /** * Check if value is odd. * diff --git a/Message/Mail/Imap.php b/Message/Mail/Imap.php index 23b16a035..9d8bbab00 100755 --- a/Message/Mail/Imap.php +++ b/Message/Mail/Imap.php @@ -21,6 +21,9 @@ namespace phpOMS\Message\Mail; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Continue implementation of email sending and receiving + * https://github.com/Karaka-Management/phpOMS/issues/258 */ class Imap implements MailBoxInterface { diff --git a/Message/Mail/Pop3.php b/Message/Mail/Pop3.php index 3ddc28b84..760b734fd 100755 --- a/Message/Mail/Pop3.php +++ b/Message/Mail/Pop3.php @@ -21,6 +21,9 @@ namespace phpOMS\Message\Mail; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Continue implementation of email sending and receiving + * https://github.com/Karaka-Management/phpOMS/issues/258 */ class Pop3 implements MailBoxInterface { diff --git a/Module/ModuleAbstract.php b/Module/ModuleAbstract.php index d1d12e6fd..a32f9092b 100755 --- a/Module/ModuleAbstract.php +++ b/Module/ModuleAbstract.php @@ -30,6 +30,10 @@ use phpOMS\Utils\StringUtils; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @performance The modules use the module name for identification in many places + * where the module id should be used for performance reasons + * https://github.com/Karaka-Management/Karaka/issues/159 */ abstract class ModuleAbstract { @@ -290,6 +294,39 @@ abstract class ModuleAbstract ]; } + /** + * Create standard model background process response. + * + * The response object contains the following data: + * + * * status = Response status + * * title = Response title (e.g. for frontend reporting) + * * message = Response message (e.g. for frontend reporting) + * * response = Response object (e.g. for validation/frontend reporting/form validation) + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $obj Response object + * + * @return void + * + * @since 1.0.0 + */ + public function createStandardBackgroundResponse( + RequestAbstract $request, + ResponseAbstract $response, + mixed $obj + ) : void + { + $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); + $response->data[$request->uri->__toString()] = [ + 'status' => NotificationLevel::INFO, + 'title' => '', + 'message' => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulBackground'), + 'response' => $obj, + ]; + } + /** * Create standard model update response. * diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index 539c012ed..2ee5272d8 100755 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -30,6 +30,14 @@ use phpOMS\Module\Exception\InvalidModuleException; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Implement a strategy for managing optional modules (e.g., comment module within the news module). + * Previously, modifications to the Mapper were made (e.g., comments were removed) when the comment module was installed. + * However, this approach is no longer viable. One potential solution is to introduce a separate Mapper + * that is dynamically replaced if the comment module is installed. + * Instead of replacing the entire file, a differential approach should be adopted, where only the ADDED lines are merged. + * Consideration must be given to uninstallation scenarios, as determining precisely what to remove is currently problematic. + * https://github.com/Karaka-Management/Karaka/issues/155 */ final class ModuleManager { @@ -253,7 +261,7 @@ final class ModuleManager { $name = '\\Modules\\' . $module . '\\Controller\\' . ($ctlName ?? $this->app->appName) . 'Controller'; - return isset($this->running[$name]); + return isset($this->running[$module][$name]); } /** @@ -646,6 +654,41 @@ final class ModuleManager $class::install($this->app, $this->modulePath); } + /** + * Initialize module. + * + * Also registers controller in the dispatcher + * + * @param string $module Module + * @param string $ctlName Controller name (null = current app) + * + * @return void + * + * @since 1.0.0 + */ + private function initModuleController(string $module, ?string $ctlName = null) : void + { + $name = '\\Modules\\' . $module . '\\Controller\\' . ($ctlName ?? $this->app->appName) . 'Controller'; + $ctrl = $this->get($module, $ctlName); + + if ($this->app->dispatcher !== null) { + $this->app->dispatcher->set($ctrl, $name); + } + + // Handle providing->receiving + foreach ($this->running as $mName => $controllers) { + $controller = \reset($controllers); + + foreach ($controller::$providing as $providing) { + $ctrl = \reset($this->running[$providing]); + + if (!\in_array($mName, $ctrl->receiving)) { + $ctrl->receiving[] = $mName; + } + } + } + } + /** * Get module instance. * @@ -666,69 +709,31 @@ final class ModuleManager * @since 1.0.0 */ public function get(string $module, ?string $ctlName = null) : ModuleAbstract - { - $name = '\\Modules\\' . $module . '\\Controller\\' . ($ctlName ?? $this->app->appName) . 'Controller'; - if (!isset($this->running[$name])) { - $this->initModuleController($module, $ctlName); - } - - /* @phpstan-ignore-next-line */ - return $this->running[$name] ?? new NullModule(); - } - - /** - * Initialize module. - * - * Also registers controller in the dispatcher - * - * @param string $module Module - * @param string $ctlName Controller name (null = current app) - * - * @return void - * - * @since 1.0.0 - */ - private function initModuleController(string $module, ?string $ctlName = null) : void - { - $name = '\\Modules\\' . $module . '\\Controller\\' . ($ctlName ?? $this->app->appName) . 'Controller'; - $this->running[$name] = $this->getModuleInstance($module, $ctlName); - - if ($this->app->dispatcher !== null) { - $this->app->dispatcher->set($this->running[$name], $name); - } - } - - /** - * Gets and initializes modules. - * - * @param string $module Module ID - * @param string $ctlName Controller name (null = current app) - * - * @return ModuleAbstract - * - * @since 1.0.0 - */ - public function getModuleInstance(string $module, ?string $ctlName = null) : ModuleAbstract { $class = '\\Modules\\' . $module . '\\Controller\\' . ($ctlName ?? $this->app->appName) . 'Controller'; - - if (!isset($this->running[$class])) { - if (Autoloader::exists($class) - || Autoloader::exists($class = '\\Modules\\' . $module . '\\Controller\\Controller') - ) { - try { - /** @var ModuleAbstract $obj */ - $obj = new $class($this->app); - $this->running[$class] = $obj; - } catch (\Throwable $_) { - $this->running[$class] = new NullModule(); - } - } else { - $this->running[$class] = new NullModule(); - } + if (!isset($this->running[$module])) { + $this->running[$module] = []; } - return $this->running[$class]; + if (isset($this->running[$module][$class])) { + return $this->running[$module][$class]; + } + + if (Autoloader::exists($class) + || Autoloader::exists($class = '\\Modules\\' . $module . '\\Controller\\Controller') + ) { + try { + /** @var ModuleAbstract $obj */ + $obj = new $class($this->app); + $this->running[$module][$class] = $obj; + } catch (\Throwable $_) { + $this->running[$module][$class] = new NullModule(); + } + } else { + $this->running[$module][$class] = new NullModule(); + } + + return $this->running[$module][$class]; } /** diff --git a/Router/WebRouter.php b/Router/WebRouter.php index 06c42c7da..fd70cbd83 100755 --- a/Router/WebRouter.php +++ b/Router/WebRouter.php @@ -23,6 +23,13 @@ use phpOMS\Account\Account; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Change the url format in most modules from query parameter to path + * (e.g. `/module/profile?id=Admin` to `/module/Admin/profile`) + * https://github.com/Karaka-Management/Karaka/issues/153 + * + * @todo Instead of doing only regex matching, combine it with a tree search, this should be faster + * https://github.com/Karaka-Management/phpOMS/issues/276 */ final class WebRouter implements RouterInterface { diff --git a/Socket/Client/Client.php b/Socket/Client/Client.php index 5d9410008..e90eeba7e 100755 --- a/Socket/Client/Client.php +++ b/Socket/Client/Client.php @@ -26,6 +26,9 @@ use phpOMS\Socket\SocketAbstract; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Implement + * https://github.com/Karaka-Management/phpOMS/issues/277 */ class Client extends SocketAbstract { diff --git a/Socket/Server/Server.php b/Socket/Server/Server.php index 026abb1e2..e1225eaa1 100755 --- a/Socket/Server/Server.php +++ b/Socket/Server/Server.php @@ -27,6 +27,9 @@ use phpOMS\Socket\SocketAbstract; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Implement + * https://github.com/Karaka-Management/phpOMS/issues/278 */ class Server extends SocketAbstract { diff --git a/Stdlib/Base/FloatInt.php b/Stdlib/Base/FloatInt.php index 5207d5dc9..cf8049ecd 100755 --- a/Stdlib/Base/FloatInt.php +++ b/Stdlib/Base/FloatInt.php @@ -34,6 +34,8 @@ class FloatInt implements SerializableInterface */ public const MAX_DECIMALS = 4; + public const DIVISOR = 10000; + /** * Thousands separator. * @@ -69,9 +71,9 @@ class FloatInt implements SerializableInterface */ 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; + $this->value = \is_int($value) ? $value : self::toInt((string) $value, $thousands, $decimal); } /** @@ -89,26 +91,19 @@ class FloatInt implements SerializableInterface */ public static function toInt(string $value, string $thousands = ',', string $decimal = '.') : int { - $split = \explode($decimal, $value); + $newValue = $value; + $len = \strlen($value); - if ($split === false) { - throw new \Exception('Internal explode error.'); // @codeCoverageIgnore + $decimalPos = \strrpos($value, $decimal); + if ($decimalPos === false) { + $decimalPos = $len - 1; } - $left = $split[0]; - $left = \str_replace($thousands, '', $left); - $right = ''; + $newValue = \str_pad($newValue, 4 - (- $decimalPos - 1), '0'); + $newValue = \str_replace([$thousands, $decimal], ['', ''], $newValue); + $newValue = \ltrim($newValue, '0'); - 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'); + return (int) $newValue; } /** @@ -147,12 +142,12 @@ class FloatInt implements SerializableInterface public function getNormalizedValue() : float { - return $this->value / \pow(10, self::MAX_DECIMALS); + return $this->value / self::DIVISOR; } public function guessScalarValue() : int|float { - $divider = \pow(10, self::MAX_DECIMALS); + $divider = self::DIVISOR; return $this->value % $divider === 0 ? (int) ($this->value / $divider) @@ -206,17 +201,15 @@ class FloatInt implements SerializableInterface */ public function getFloat(?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); + $left = \substr($value, 0, -self::MAX_DECIMALS); /** @var string $left */ $left = $left === false ? '0' : $left; - $right = \substr($value, -self::MAX_DECIMALS + $isNegative); + $right = \substr($value, -self::MAX_DECIMALS); if ($right === false) { throw new \Exception(); // @codeCoverageIgnore @@ -388,4 +381,29 @@ class FloatInt implements SerializableInterface return $this; } + + public static function identifyNumericFormat(string $str) : ?array + { + $commaPos = \strrpos($str, ','); + $periodPos = \strrpos($str, '.'); + + if ($commaPos !== false && $periodPos !== false) { + return [ + 'thousands' => $commaPos < $periodPos ? ',' : '.', + 'decimal' => $commaPos < $periodPos ? '.' : ',', + ]; + } elseif ($commaPos === false && $periodPos === false) { + return null; + } + + // Back to normal cases + $isComma = $commaPos !== false + ? $commaPos + 3 === \strlen($str) + : $periodPos + 3 !== \strlen($str); + + return [ + 'thousands' => $isComma ? '.' : ',', + 'decimal' => $isComma ? ',' : '.' + ]; + } } diff --git a/Stdlib/Base/Iban.php b/Stdlib/Base/Iban.php index 2754d36ad..bbe49de9e 100755 --- a/Stdlib/Base/Iban.php +++ b/Stdlib/Base/Iban.php @@ -119,7 +119,7 @@ class Iban implements SerializableInterface $country = $this->getCountry(); /** @var string $iban */ - $iban = IbanEnum::getByName('C_' . $country); + $iban = IbanEnum::getByName('_' . $country); $layout = \str_replace(' ', '', $iban); $start = \stripos($layout, $sequence); $end = \strrpos($layout, $sequence); diff --git a/Stdlib/Base/SmartDateTime.php b/Stdlib/Base/SmartDateTime.php index 976c8b8d9..df0803902 100755 --- a/Stdlib/Base/SmartDateTime.php +++ b/Stdlib/Base/SmartDateTime.php @@ -111,15 +111,18 @@ class SmartDateTime extends \DateTime */ public function smartModify(int $y = 0, int $m = 0, int $d = 0, int $calendar = \CAL_GREGORIAN) : self { - $yearChange = (int) \floor(((int) $this->format('m') - 1 + $m) / 12); - $yearNew = (int) $this->format('Y') + $y + $yearChange; + $year = (int) $this->format('Y'); + $month = (int) $this->format('m'); - $monthNew = (int) $this->format('m') + $m; - $monthNew = $monthNew <= 0 - ? 12 + ($monthNew - 1) % 12 + 1 - : ($monthNew - 1) % 12 + 1; + $yearChange = (int) \floor(($month - 1 + $m) / 12); + $yearNew = $year + $y + $yearChange; - $dayMonthOld = \cal_days_in_month($calendar, (int) $this->format('m'), (int) $this->format('Y')); + $monthNew = $month - 1 + $m; + $monthNew = $monthNew < 0 + ? ($month - 1 + $m - 12 * $yearChange) % 12 + 1 + : $monthNew % 12 + 1; + + $dayMonthOld = \cal_days_in_month($calendar, $month, $year); $dayMonthNew = \cal_days_in_month($calendar, $monthNew, $yearNew); $dayOld = (int) $this->format('d'); diff --git a/Utils/Parser/Html/HtmlParser.php b/Utils/Parser/Html/HtmlParser.php index 934ca6efb..7de40702a 100644 --- a/Utils/Parser/Html/HtmlParser.php +++ b/Utils/Parser/Html/HtmlParser.php @@ -55,27 +55,27 @@ final class HtmlParser ); $doc->loadHTMLFile($path); - $content = ''; if (empty($xpath)) { $body = $doc->getElementsByTagName('body'); $node = $body->item(0); - $content = empty($node->textContent) ? '' : $node->textContent; - } else { - $xNode = new \DOMXpath($doc); - $elements = $xNode->query($xpath); + return empty($node->textContent) ? '' : $node->textContent; + } - if ($elements === false) { - return $content; - } + $content = ''; + $xNode = new \DOMXpath($doc); + $elements = $xNode->query($xpath); - foreach ($elements as $element) { - $nodes = $element->childNodes; + if ($elements === false) { + return $content; + } - foreach ($nodes as $node) { - $content .= $node->textContent . "\n"; - } + foreach ($elements as $element) { + $nodes = $element->childNodes; + + foreach ($nodes as $node) { + $content .= $node->textContent . "\n"; } } diff --git a/Utils/Parser/Pdf/PdfParser.php b/Utils/Parser/Pdf/PdfParser.php index 6c20399af..8f6876562 100755 --- a/Utils/Parser/Pdf/PdfParser.php +++ b/Utils/Parser/Pdf/PdfParser.php @@ -144,6 +144,7 @@ final class PdfParser foreach ($files as $file) { if (!StringUtils::endsWith($file, '.jpg') + && !StringUtils::endsWith($file, '.jpeg') && !StringUtils::endsWith($file, '.png') && !StringUtils::endsWith($file, '.gif') ) { diff --git a/Utils/Parser/Xml/XmlParser.php b/Utils/Parser/Xml/XmlParser.php new file mode 100644 index 000000000..c5622d114 --- /dev/null +++ b/Utils/Parser/Xml/XmlParser.php @@ -0,0 +1,83 @@ +preserveWhiteSpace = true; + $doc->formatOutput = true; + + $xml = \file_get_contents($path); + $xml = \preg_replace( + ['~~', '~~'], + ['', ''], + $xml + ); + + $doc->loadXML($path); + + if (empty($xpath)) { + return $doc->loadXML($xml); + } + + $content = ''; + $xNode = new \DOMXpath($doc); + $elements = $xNode->query($xpath); + + if ($elements === false) { + return $content; + } + + foreach ($elements as $element) { + $nodes = $element->childNodes; + + foreach ($nodes as $node) { + $content .= $node->textContent . "\n"; + } + } + + return $content; + } +} diff --git a/Utils/TaskSchedule/Schedule.php b/Utils/TaskSchedule/Schedule.php index 27f116aea..9991020d8 100755 --- a/Utils/TaskSchedule/Schedule.php +++ b/Utils/TaskSchedule/Schedule.php @@ -23,6 +23,9 @@ use phpOMS\Validation\Base\DateTime; * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 + * + * @todo Use `Interval` for scheduler instead of string etc. + * https://github.com/Karaka-Management/phpOMS/issues/257 */ class Schedule extends TaskAbstract { diff --git a/Validation/Finance/Iban.php b/Validation/Finance/Iban.php index 3369770fe..e30f2b803 100755 --- a/Validation/Finance/Iban.php +++ b/Validation/Finance/Iban.php @@ -42,7 +42,7 @@ final class Iban extends ValidatorAbstract return false; // @codeCoverageIgnore } - $enumName = 'C_' . \strtoupper($temp); + $enumName = '_' . \strtoupper($temp); if (!IbanEnum::isValidName($enumName)) { self::$error = IbanErrorType::INVALID_COUNTRY; diff --git a/Validation/Finance/IbanEnum.php b/Validation/Finance/IbanEnum.php index 50e0bdf16..31c7ec98e 100755 --- a/Validation/Finance/IbanEnum.php +++ b/Validation/Finance/IbanEnum.php @@ -26,167 +26,167 @@ use phpOMS\Stdlib\Base\Enum; */ class IbanEnum extends Enum { - public const C_AL = 'ALkk bbbs sssx cccc cccc cccc cccc'; + public const _AL = 'ALkk bbbs sssx cccc cccc cccc cccc'; - public const C_AD = 'ADkk bbbb ssss cccc cccc cccc'; + public const _AD = 'ADkk bbbb ssss cccc cccc cccc'; - public const C_AT = 'ATkk bbbb bccc cccc cccc'; + public const _AT = 'ATkk bbbb bccc cccc cccc'; - public const C_AZ = 'AZkk bbbb cccc cccc cccc cccc cccc '; + public const _AZ = 'AZkk bbbb cccc cccc cccc cccc cccc '; - public const C_BH = 'BHkk bbbb cccc cccc cccc cc'; + public const _BH = 'BHkk bbbb cccc cccc cccc cc'; - public const C_BE = 'BEkk bbbc cccc ccxx'; + public const _BE = 'BEkk bbbc cccc ccxx'; - public const C_BA = 'BAkk bbbs sscc cccc ccxx'; + public const _BA = 'BAkk bbbs sscc cccc ccxx'; - public const C_BR = 'BRkk bbbb bbbb ssss sccc cccc ccct n'; + public const _BR = 'BRkk bbbb bbbb ssss sccc cccc ccct n'; - public const C_BG = 'BGkk bbbb ssss ttcc cccc cc'; + public const _BG = 'BGkk bbbb ssss ttcc cccc cc'; - public const C_CR = 'CRkk bbbc cccc cccc cccc c'; + public const _CR = 'CRkk bbbc cccc cccc cccc c'; - public const C_HR = 'HRkk bbbb bbbc cccc cccc c'; + public const _HR = 'HRkk bbbb bbbc cccc cccc c'; - public const C_CY = 'CYkk bbbs ssss cccc cccc cccc cccc'; + public const _CY = 'CYkk bbbs ssss cccc cccc cccc cccc'; - public const C_CZ = 'CZkk bbbb ssss sscc cccc cccc'; + public const _CZ = 'CZkk bbbb ssss sscc cccc cccc'; - public const C_DK = 'DKkk bbbb cccc cccc cc'; + public const _DK = 'DKkk bbbb cccc cccc cc'; - public const C_DO = 'DOkk bbbb cccc cccc cccc cccc cccc'; + public const _DO = 'DOkk bbbb cccc cccc cccc cccc cccc'; - public const C_TL = 'TLkk bbbc cccc cccc cccc cxx'; + public const _TL = 'TLkk bbbc cccc cccc cccc cxx'; - public const C_EE = 'EEkk bbss cccc cccc cccx'; + public const _EE = 'EEkk bbss cccc cccc cccx'; - public const C_FO = 'FOkk bbbb cccc cccc cx'; + public const _FO = 'FOkk bbbb cccc cccc cx'; - public const C_FI = 'FIkk bbbb bbcc cccc cx'; + public const _FI = 'FIkk bbbb bbcc cccc cx'; - public const C_FR = 'FRkk bbbb bsss sscc cccc cccc cxx'; + public const _FR = 'FRkk bbbb bsss sscc cccc cccc cxx'; - public const C_GE = 'GEkk bbcc cccc cccc cccc cc'; + public const _GE = 'GEkk bbcc cccc cccc cccc cc'; - public const C_DE = 'DEkk bbbb bbbb cccc cccc cc'; + public const _DE = 'DEkk bbbb bbbb cccc cccc cc'; - public const C_GI = 'GIkk bbbb cccc cccc cccc ccc'; + public const _GI = 'GIkk bbbb cccc cccc cccc ccc'; - public const C_GR = 'GRkk bbbs sssc cccc cccc cccc ccc'; + public const _GR = 'GRkk bbbs sssc cccc cccc cccc ccc'; - public const C_GL = 'GLkk bbbb cccc cccc cc'; + public const _GL = 'GLkk bbbb cccc cccc cc'; - public const C_GT = 'GTkk bbbb mmtt cccc cccc cccc cccc'; + public const _GT = 'GTkk bbbb mmtt cccc cccc cccc cccc'; - public const C_HU = 'HUkk bbbs sssx cccc cccc cccc cccx'; + public const _HU = 'HUkk bbbs sssx cccc cccc cccc cccx'; - public const C_IS = 'ISkk bbbb sscc cccc iiii iiii ii'; + public const _IS = 'ISkk bbbb sscc cccc iiii iiii ii'; - public const C_IE = 'IEkk aaaa bbbb bbcc cccc cc'; + public const _IE = 'IEkk aaaa bbbb bbcc cccc cc'; - public const C_IL = 'ILkk bbbn nncc cccc cccc ccc'; + public const _IL = 'ILkk bbbn nncc cccc cccc ccc'; - public const C_IT = 'ITkk xbbb bbss sssc cccc cccc ccc'; + public const _IT = 'ITkk xbbb bbss sssc cccc cccc ccc'; - public const C_JO = 'JOkk bbbb ssss cccc cccc cccc cccc cc'; + public const _JO = 'JOkk bbbb ssss cccc cccc cccc cccc cc'; - public const C_KZ = 'KZkk bbbc cccc cccc cccc'; + public const _KZ = 'KZkk bbbc cccc cccc cccc'; - public const C_XK = 'XKkk bbbb cccc cccc cccc'; + public const _XK = 'XKkk bbbb cccc cccc cccc'; - public const C_KW = 'KWkk bbbb cccc cccc cccc cccc cccc cc'; + public const _KW = 'KWkk bbbb cccc cccc cccc cccc cccc cc'; - public const C_LV = 'LVkk bbbb cccc cccc cccc c'; + public const _LV = 'LVkk bbbb cccc cccc cccc c'; - public const C_LB = 'LBkk bbbb cccc cccc cccc cccc cccc'; + public const _LB = 'LBkk bbbb cccc cccc cccc cccc cccc'; - public const C_LI = 'LIkk bbbb bccc cccc cccc c'; + public const _LI = 'LIkk bbbb bccc cccc cccc c'; - public const C_LT = 'LTkk bbbb bccc cccc cccc'; + public const _LT = 'LTkk bbbb bccc cccc cccc'; - public const C_LU = 'LUkk bbbc cccc cccc cccc'; + public const _LU = 'LUkk bbbc cccc cccc cccc'; - public const C_MK = 'MKkk bbbc cccc cccc cxx'; + public const _MK = 'MKkk bbbc cccc cccc cxx'; - public const C_MT = 'MTkk bbbb ssss sccc cccc cccc cccc ccc'; + public const _MT = 'MTkk bbbb ssss sccc cccc cccc cccc ccc'; - public const C_MR = 'MRkk bbbb bsss sscc cccc cccc cxx'; + public const _MR = 'MRkk bbbb bsss sscc cccc cccc cxx'; - public const C_MU = 'MUkk bbbb bbss cccc cccc cccc 000m mm'; + public const _MU = 'MUkk bbbb bbss cccc cccc cccc 000m mm'; - public const C_MC = 'MCkk bbbb bsss sscc cccc cccc cxx'; + public const _MC = 'MCkk bbbb bsss sscc cccc cccc cxx'; - public const C_MD = 'MDkk bbcc cccc cccc cccc cccc'; + public const _MD = 'MDkk bbcc cccc cccc cccc cccc'; - public const C_ME = 'MEkk bbbc cccc cccc cccc xx'; + public const _ME = 'MEkk bbbc cccc cccc cccc xx'; - public const C_NL = 'NLkk bbbb cccc cccc cc'; + public const _NL = 'NLkk bbbb cccc cccc cc'; - public const C_NO = 'NOkk bbbb cccc ccx'; + public const _NO = 'NOkk bbbb cccc ccx'; - public const C_PK = 'PKkk bbbb cccc cccc cccc cccc'; + public const _PK = 'PKkk bbbb cccc cccc cccc cccc'; - public const C_PS = 'PSkk bbbb xxxx xxxx xccc cccc cccc c'; + public const _PS = 'PSkk bbbb xxxx xxxx xccc cccc cccc c'; - public const C_PL = 'PLkk bbbs sssx cccc cccc cccc cccc'; + public const _PL = 'PLkk bbbs sssx cccc cccc cccc cccc'; - public const C_PT = 'PTkk bbbb ssss cccc cccc cccx x'; + public const _PT = 'PTkk bbbb ssss cccc cccc cccx x'; - public const C_QA = 'QAkk bbbb cccc cccc cccc cccc cccc c'; + public const _QA = 'QAkk bbbb cccc cccc cccc cccc cccc c'; - public const C_RO = 'ROkk bbbb cccc cccc cccc cccc'; + public const _RO = 'ROkk bbbb cccc cccc cccc cccc'; - public const C_SM = 'SMkk xbbb bbss sssc cccc cccc ccc'; + public const _SM = 'SMkk xbbb bbss sssc cccc cccc ccc'; - public const C_SA = 'SAkk bbcc cccc cccc cccc cccc'; + public const _SA = 'SAkk bbcc cccc cccc cccc cccc'; - public const C_RS = 'RSkk bbbc cccc cccc cccc xx'; + public const _RS = 'RSkk bbbc cccc cccc cccc xx'; - public const C_SK = 'SKkk bbbb ssss sscc cccc cccc'; + public const _SK = 'SKkk bbbb ssss sscc cccc cccc'; - public const C_SI = 'SIkk bbss sccc cccc cxx'; + public const _SI = 'SIkk bbss sccc cccc cxx'; - public const C_ES = 'ESkk bbbb ssss xxcc cccc cccc'; + public const _ES = 'ESkk bbbb ssss xxcc cccc cccc'; - public const C_SE = 'SEkk bbbc cccc cccc cccc cccc'; + public const _SE = 'SEkk bbbc cccc cccc cccc cccc'; - public const C_CH = 'CHkk bbbb bccc cccc cccc c'; + public const _CH = 'CHkk bbbb bccc cccc cccc c'; - public const C_TN = 'TNkk bbss sccc cccc cccc cccc'; + public const _TN = 'TNkk bbss sccc cccc cccc cccc'; - public const C_TR = 'TRkk bbbb bxcc cccc cccc cccc cc'; + public const _TR = 'TRkk bbbb bxcc cccc cccc cccc cc'; - public const C_UA = 'UAkk bbbb bbcc cccc cccc cccc cccc c'; + public const _UA = 'UAkk bbbb bbcc cccc cccc cccc cccc c'; - public const C_AE = 'AEkk bbbc cccc cccc cccc ccc'; + public const _AE = 'AEkk bbbc cccc cccc cccc ccc'; - public const C_GB = 'GBkk bbbb ssss sscc cccc cc'; + public const _GB = 'GBkk bbbb ssss sscc cccc cc'; - public const C_VG = 'VGkk bbbb cccc cccc cccc cccc'; + public const _VG = 'VGkk bbbb cccc cccc cccc cccc'; - public const C_SN = 'SNkk annn nnnn nnnn nnnn nnnn nnnn'; + public const _SN = 'SNkk annn nnnn nnnn nnnn nnnn nnnn'; - public const C_MZ = 'MZkk nnnn nnnn nnnn nnnn nnnn n'; + public const _MZ = 'MZkk nnnn nnnn nnnn nnnn nnnn n'; - public const C_ML = 'MLkk annn nnnn nnnn nnnn nnnn nnnn'; + public const _ML = 'MLkk annn nnnn nnnn nnnn nnnn nnnn'; - public const C_MG = 'MGkk nnnn nnnn nnnn nnnn nnnn nnn'; + public const _MG = 'MGkk nnnn nnnn nnnn nnnn nnnn nnn'; - public const C_CI = 'CIkk annn nnnn nnnn nnnn nnnn nnnn'; + public const _CI = 'CIkk annn nnnn nnnn nnnn nnnn nnnn'; - public const C_IR = 'IRkk nnnn nnnn nnnn nnnn nnnn nn'; + public const _IR = 'IRkk nnnn nnnn nnnn nnnn nnnn nn'; - public const C_CV = 'CVkk nnnn nnnn nnnn nnnn nnnn n'; + public const _CV = 'CVkk nnnn nnnn nnnn nnnn nnnn n'; - public const C_CM = 'CMkk nnnn nnnn nnnn nnnn nnnn nnn'; + public const _CM = 'CMkk nnnn nnnn nnnn nnnn nnnn nnn'; - public const C_BI = 'BIkk nnnn nnnn nnnn'; + public const _BI = 'BIkk nnnn nnnn nnnn'; - public const C_BF = 'BFkk nnnn nnnn nnnn nnnn nnnn nnn'; + public const _BF = 'BFkk nnnn nnnn nnnn nnnn nnnn nnn'; - public const C_BJ = 'BJkk annn nnnn nnnn nnnn nnnn nnnn'; + public const _BJ = 'BJkk annn nnnn nnnn nnnn nnnn nnnn'; - public const C_AO = 'AOkk nnnn nnnn nnnn nnnn nnnn n'; + public const _AO = 'AOkk nnnn nnnn nnnn nnnn nnnn n'; - public const C_DZ = 'DZkk nnnn nnnn nnnn nnnn nnnn'; + public const _DZ = 'DZkk nnnn nnnn nnnn nnnn nnnn'; } diff --git a/Views/View.php b/Views/View.php index 9905006ef..15863d165 100755 --- a/Views/View.php +++ b/Views/View.php @@ -325,14 +325,14 @@ class View extends ViewAbstract /** * Print a percentage value * - * @param float $percentage Percentage value to print - * @param null|string $format Format type to use + * @param float|FloatInt $percentage Percentage value to print + * @param null|string $format Format type to use * * @return string * * @since 1.0.0 */ - public function getPercentage(float $percentage, ?string $format = null) : string + public function getPercentage(float | FloatInt $percentage, ?string $format = null) : string { return $this->l11nManager->getPercentage($this->l11n, $percentage, $format); } diff --git a/Views/ViewAbstract.php b/Views/ViewAbstract.php index d39ca6b64..f218c0274 100755 --- a/Views/ViewAbstract.php +++ b/Views/ViewAbstract.php @@ -32,7 +32,7 @@ abstract class ViewAbstract implements RenderableInterface * @var string * @since 1.0.0 */ - protected const BASE_PATH = __DIR__ . '/../..'; + public const BASE_PATH = __DIR__ . '/../..'; /** * Output is buffered @@ -230,7 +230,7 @@ abstract class ViewAbstract implements RenderableInterface } /** - * Arrayify view and it's subviews. + * Arrayify view and it's sub-views. * * @return array * diff --git a/tests/DataStorage/Database/Query/ColumnTest.php b/tests/DataStorage/Database/Query/ColumnTest.php deleted file mode 100755 index 51a14aa20..000000000 --- a/tests/DataStorage/Database/Query/ColumnTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/DataStorage/Database/Query/CountTest.php b/tests/DataStorage/Database/Query/CountTest.php deleted file mode 100755 index d13cfd7a8..000000000 --- a/tests/DataStorage/Database/Query/CountTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/DataStorage/Database/Query/ExpressionTest.php b/tests/DataStorage/Database/Query/ExpressionTest.php deleted file mode 100755 index 0743230fc..000000000 --- a/tests/DataStorage/Database/Query/ExpressionTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/DataStorage/Database/Query/FromTest.php b/tests/DataStorage/Database/Query/FromTest.php deleted file mode 100755 index f1a7111d9..000000000 --- a/tests/DataStorage/Database/Query/FromTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/DataStorage/Database/Query/IntoTest.php b/tests/DataStorage/Database/Query/IntoTest.php deleted file mode 100755 index fd3daafaa..000000000 --- a/tests/DataStorage/Database/Query/IntoTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/DataStorage/Database/Query/SelectTest.php b/tests/DataStorage/Database/Query/SelectTest.php deleted file mode 100755 index 83a46661e..000000000 --- a/tests/DataStorage/Database/Query/SelectTest.php +++ /dev/null @@ -1,32 +0,0 @@ -get())); - } -} diff --git a/tests/Router/WebRouterTest.php b/tests/Router/WebRouterTest.php index 11b55137d..041d1bd03 100755 --- a/tests/Router/WebRouterTest.php +++ b/tests/Router/WebRouterTest.php @@ -53,7 +53,7 @@ final class WebRouterTest extends \PHPUnit\Framework\TestCase { self::assertEmpty( $this->router->route( - (new HttpRequest(new HttpUri('')))->uri->getRoute() + (new HttpRequest())->uri->getRoute() ) ); } diff --git a/tests/Views/ViewTest.php b/tests/Views/ViewTest.php index b0bc13d0e..59a6f6d8a 100755 --- a/tests/Views/ViewTest.php +++ b/tests/Views/ViewTest.php @@ -251,7 +251,7 @@ final class ViewTest extends \PHPUnit\Framework\TestCase */ public function testGetRequest() : void { - $view = new View($this->app->l11nManager, $request = new HttpRequest(new HttpUri('')), $response = new HttpResponse()); + $view = new View($this->app->l11nManager, $request = new HttpRequest(), $response = new HttpResponse()); self::assertEquals($request, $view->request); self::assertEquals($response, $view->response); @@ -264,7 +264,7 @@ final class ViewTest extends \PHPUnit\Framework\TestCase */ public function testGetResponse() : void { - $view = new View($this->app->l11nManager, new HttpRequest(new HttpUri('')), $response = new HttpResponse()); + $view = new View($this->app->l11nManager, new HttpRequest(), $response = new HttpResponse()); self::assertEquals($response, $view->response); } @@ -276,7 +276,7 @@ final class ViewTest extends \PHPUnit\Framework\TestCase */ public function testPrintHtml() : void { - $view = new View($this->app->l11nManager, $request = new HttpRequest(new HttpUri('')), $response = new HttpResponse()); + $view = new View($this->app->l11nManager, $request = new HttpRequest(), $response = new HttpResponse()); self::assertEquals('<a href="test">Test</a>', $view->printHtml('Test')); self::assertEquals('<a href="test">Test</a>', ViewAbstract::html('Test'));