diff --git a/Account/Account.php b/Account/Account.php index 49ce50933..28f61d8b0 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -206,6 +206,26 @@ class Account implements \JsonSerializable, ArrayableInterface $this->groups[] = $group; } + /** + * User has group. + * + * @param int $group Group id + * + * @return void + * + * @since 1.0.0 + */ + public function hasGroup(int $id) : bool + { + foreach ($this->groups as $group) { + if ($group->getId() === $id) { + return true; + } + } + + return false; + } + /** * Get email. * diff --git a/Application/ApplicationInfo.php b/Application/ApplicationInfo.php index 49cbca504..e89913f6c 100644 --- a/Application/ApplicationInfo.php +++ b/Application/ApplicationInfo.php @@ -222,4 +222,16 @@ final class ApplicationInfo { return $this->info['version'] ?? ''; } + + /** + * Get info data. + * + * @return array + * + * @since 1.0.0 + */ + public function getProviding() : array + { + return $this->info['providing'] ?? []; + } } diff --git a/Application/ApplicationManager.php b/Application/ApplicationManager.php index f8e26140a..4f0e0528f 100644 --- a/Application/ApplicationManager.php +++ b/Application/ApplicationManager.php @@ -16,7 +16,6 @@ declare(strict_types=1); namespace phpOMS\Application; -use phpOMS\Module\ModuleManager; use phpOMS\System\File\Local\Directory; use phpOMS\System\File\PathException; @@ -32,14 +31,6 @@ use phpOMS\System\File\PathException; */ final class ApplicationManager { - /** - * Module manager - * - * @var ModuleManager - * @since 1.0.0 - */ - private ModuleManager $moduleManager; - /** * Applications * @@ -51,13 +42,10 @@ final class ApplicationManager /** * Constructor. * - * @param ModuleManager $moduleManager Module manager - * * @since. 1.0.0 */ - public function __construct(ModuleManager $moduleManager) + public function __construct() { - $this->moduleManager = $moduleManager; } /** @@ -106,7 +94,6 @@ final class ApplicationManager $this->installFiles($source, $destination); $this->installTheme($destination, $theme); - $this->installFromModules($app); $files = Directory::list($destination, '*', true); foreach ($files as $file) { @@ -173,21 +160,4 @@ final class ApplicationManager ); } } - - /** - * Install routes and hooks from modules for application - * - * @param ApplicationInfo $info Application info - * - * @return void - * - * @since 1.0.0 - */ - public function installFromModules(ApplicationInfo $info) : void - { - $installed = $this->moduleManager->getInstalledModules(); - foreach ($installed as $module => $moduleInfo) { - $this->moduleManager->reInit($module, $info); - } - } } diff --git a/Config/SettingsInterface.php b/Config/SettingsInterface.php index fd92451f7..331510f74 100644 --- a/Config/SettingsInterface.php +++ b/Config/SettingsInterface.php @@ -33,6 +33,7 @@ interface SettingsInterface extends OptionsInterface * * @param null|int|int[]|string|string[] $ids Ids * @param null|string|string[] $names Setting name + * @param null|int $app Application * @param null|string $module Module name * @param null|int $group Group id * @param null|int $account Account id @@ -44,6 +45,7 @@ interface SettingsInterface extends OptionsInterface public function get( mixed $ids = null, string | array $names = null, + int $app = null, string $module = null, int $group = null, int $account = null diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 91df708ad..2c7a3d9fc 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -121,14 +121,6 @@ class DataMapperAbstract implements DataMapperInterface */ protected static string $createdAt = ''; - /** - * Language - * - * @var string - * @since 1.0.0 - */ - protected static string $languageField = ''; - /** * Columns. * @@ -246,6 +238,14 @@ class DataMapperAbstract implements DataMapperInterface */ protected static array $lastQueryData = []; + /** + * Fields to sort by. + * + * @var array[] + * @since 1.0.0 + */ + protected static array $sortFields = []; + /** * Constructor. * @@ -342,6 +342,34 @@ class DataMapperAbstract implements DataMapperInterface 'ignore' => $models === null, // don't load this model ]; + // @todo: ignore seems to be a bug, models === null is true VERY often because i usually omit the models definition. Why is it still working, or is it? + + /** @var string */ + return static::class; + } + + /** + * Create a conditional value + * + * @param string $by Name of the variable to sort by + * @param string $order ASC or DESC + * @param string[] $models Models to apply the sort on + * + * @return string + * + * @since 1.0.0 + */ + public static function sortBy( + string $by, + string $order = 'DESC', + ?array $models = [], + ) : string + { + self::$sortFields[$by] = [ + 'order' => $order, + 'models' => $models === [] ? null : $models, + ]; + /** @var string */ return static::class; } @@ -364,6 +392,7 @@ class DataMapperAbstract implements DataMapperInterface self::$parentMapper = null; self::$withFields = []; + self::$sortFields = []; self::$relations = RelationType::ALL; } @@ -750,6 +779,31 @@ class DataMapperAbstract implements DataMapperInterface return true; } + /** + * Delete relation + * + * This is only possible for hasMany objects which are stored in a relation table + * + * @param string $member Member name of the relation + * @param mixed $id1 Id of the primary object + * @param mixed $id2 Id of the secondary object + * + * @return bool + * + * @since 1.0.0 + */ + public static function delteRelation(string $member, mixed $id1, mixed $id2) : bool + { + if (!isset(static::$hasMany[$member]) || !isset(static::$hasMany[$member]['external'])) { + return false; + } + + self::removeInitialized(static::class, $id1); + self::deleteRelationTable($member, \is_array($id2) ? $id2 : [$id2], $id1); + + return true; + } + /** * Create has many * @@ -1329,7 +1383,7 @@ class DataMapperAbstract implements DataMapperInterface * Delete relation table entry * * @param string $propertyName Property name to initialize - * @param array $objsIds Object ids to insert + * @param array $objsIds Object ids to delete * @param mixed $objId Model to reference * * @return void @@ -2585,7 +2639,6 @@ class DataMapperAbstract implements DataMapperInterface * @param mixed $pivot Pivot * @param string $column Sort column/pivot column * @param int $limit Result limit - * @param string $order Order of the elements * @param int $relations Load relations * @param int $depth Relation depth * @param Builder $query Query @@ -2598,16 +2651,13 @@ class DataMapperAbstract implements DataMapperInterface mixed $pivot, string $column = null, int $limit = 50, - string $order = 'ASC', int $relations = RelationType::ALL, int $depth = 3, Builder $query = null ) : array { $query ??= self::getQuery(depth: $depth); - $query->where(static::$table . '_d' . $depth . '.' . ($column !== null ? self::getColumnByMember($column) : static::$primaryField), '>', $pivot) - ->orderBy(static::$table . '_d' . $depth . '.' . ($column !== null ? self::getColumnByMember($column) : static::$primaryField), $order) - ->limit($limit); + $query->where(static::$table . '_d' . $depth . '.' . ($column !== null ? self::getColumnByMember($column) : static::$primaryField), '>', $pivot); return self::getAllByQuery($query, $relations, $depth); } @@ -2618,7 +2668,6 @@ class DataMapperAbstract implements DataMapperInterface * @param mixed $pivot Pivot * @param string $column Sort column/pivot column * @param int $limit Result limit - * @param string $order Order of the elements * @param int $relations Load relations * @param int $depth Relation depth * @param Builder $query Query @@ -2635,7 +2684,6 @@ class DataMapperAbstract implements DataMapperInterface mixed $pivot, string $column = null, int $limit = 50, - string $order = 'ASC', int $relations = RelationType::ALL, int $depth = 3, Builder $query = null @@ -2643,7 +2691,6 @@ class DataMapperAbstract implements DataMapperInterface { $query ??= self::getQuery(depth: $depth); $query->where(static::$table . '_d' . $depth . '.' . ($column !== null ? self::getColumnByMember($column) : static::$primaryField), '<', $pivot) - ->orderBy(static::$table . '_d' . $depth . '.' . ($column !== null ? self::getColumnByMember($column) : static::$primaryField), $order) ->limit($limit); return self::getAllByQuery($query, $relations, $depth); @@ -3205,69 +3252,73 @@ class DataMapperAbstract implements DataMapperInterface foreach (static::$hasMany as $member => $value) { if ($value['writeonly'] ?? false === true + || self::$relations !== RelationType::ALL || (isset(self::$withFields[$member]['ignore']) && self::$withFields[$member]['ignore']) // should not be loaded ) { continue; } - if (!isset($cachedTables[$value['table']])) { - $query = new Builder(self::$db); + if (isset($cachedTables[$value['table']])) { + $result[$member] = $cachedTables[$value['table']]; - if (self::$relations === RelationType::ALL) { - $src = $value['external'] ?? $value['mapper']::$primaryField; + continue; + } - // @todo: what if a specific column name is defined instead of primaryField for the join? Fix, it should be stored in 'column' - $query->select($value['table'] . '.' . $src) - ->from($value['table']) - ->where($value['table'] . '.' . $value['self'], '=', $primaryKey); + $query = new Builder(self::$db); + $src = $value['external'] ?? $value['mapper']::$primaryField; - if ($value['mapper']::getTable() !== $value['table']) { - $query->leftJoin($value['mapper']::getTable()) - ->on($value['table'] . '.' . $src, '=', $value['mapper']::getTable() . '.' . $value['mapper']::getPrimaryField()); - } + // @todo: what if a specific column name is defined instead of primaryField for the join? Fix, it should be stored in 'column' + $query->select($value['table'] . '.' . $src) + ->from($value['table']) + ->where($value['table'] . '.' . $value['self'], '=', $primaryKey); - // @todo: here the relation table should probably join the the model table for better ::with() handling + if ($value['mapper']::getTable() !== $value['table']) { + $query->leftJoin($value['mapper']::getTable()) + ->on($value['table'] . '.' . $src, '=', $value['mapper']::getTable() . '.' . $value['mapper']::getPrimaryField()); + } - if (isset(self::$withFields[$member]) && self::$withFields[$member]['orderBy'] !== null) { - $query->orderBy($value['mapper']::getTable() . '.' . $value['mapper']::getColumnByMember(self::$withFields[$member]['orderBy']), self::$withFields[$member]['sortOrder']); - } + $modelName = $value['mapper']::getModelName(); - if (isset(self::$withFields[$member]) && self::$withFields[$member]['limit'] !== null) { - $query->limit(self::$withFields[$member]['limit']); - } + // @todo: here the relation table should probably join the the model table for better ::with() handling - $modelName = $value['mapper']::getModelName(); - foreach (self::$withFields as $condKey => $condValue) { - if (($column = $value['mapper']::getColumnByMember($condKey)) === null - || ($condValue['models'] !== null && !\in_array($modelName, $condValue['models'])) - || ($value['conditional'] ?? false) === false - || $condValue['ignore'] - ) { - continue; - } + if (isset(self::$sortFields[$member]) + && ($column = $value['mapper']::getColumnByMember($member)) !== null + && (self::$sortFields[$member]['models'] === null || \in_array($modelName, self::$sortFields[$member]['models'])) + ) { + $query->orderBy($value['mapper']::getTable() . '.' . $column, self::$sortFields[$member]['order']); + } elseif (isset($value['sort'])) { + $query->orderBy($value['mapper']::getTable() . '.' . $value['mapper']::getColumnByMember($value['sort']['orderBy']), $value['sort']['sortOrder']); + } - if ($condValue['value'] !== null) { - $query->andWhere($value['mapper']::getTable() . '.' . $column, $condValue['comparison'], $condValue['value']); - } + if (isset(self::$withFields[$member]) && self::$withFields[$member]['limit'] !== null) { + $query->limit(self::$withFields[$member]['limit']); + } - if ($condValue['orderBy'] !== null) { - $query->orderBy($value['mapper']::getTable() . '.' . $column . '.' . $value['mapper']::getColumnByMember($condValue['orderBy']), $condValue['sortOrder']); - } + // @todo: like the foreach loop below, I probably also need to loop all sortFields to check if ther is a sortField defined which is part of the hasMany definition?! - if ($condValue['limit'] !== null) { - $query->limit($condValue['limit']); - } - } + foreach (self::$withFields as $condKey => $condValue) { + if (($column = $value['mapper']::getColumnByMember($condKey)) === null + || ($condValue['models'] !== null && !\in_array($modelName, $condValue['models'])) + || ($value['conditional'] ?? false) === false + || $condValue['ignore'] + ) { + continue; } - $sth = self::$db->con->prepare($query->toSql()); - if ($sth !== false) { - $sth->execute(); - $cachedTables[$value['table']] = $sth->fetchAll(\PDO::FETCH_COLUMN); + if ($condValue['value'] !== null) { + $query->andWhere($value['mapper']::getTable() . '.' . $column, $condValue['comparison'], $condValue['value']); + } + + if ($condValue['limit'] !== null) { + $query->limit($condValue['limit']); } } - $result[$member] = $cachedTables[$value['table']]; + $sth = self::$db->con->prepare($query->toSql()); + if ($sth !== false) { + $sth->execute(); + $result[$member] = $cachedTables[$value['table']] = $sth->fetchAll(\PDO::FETCH_COLUMN); + } } // @todo: this returns IDs it should return the database data here in order to reduce the requests. @@ -3306,8 +3357,19 @@ class DataMapperAbstract implements DataMapperInterface $query->fromAs(static::$table, static::$table . '_d' . $depth); } - // handle conditional + // handle sort, the column name order is very important. Therefore it cannot be done in the foreach loop above! $modelName = self::getModelName(); + foreach (self::$sortFields as $member => $sort) { + if (($column = self::getColumnByMember($member)) === null + || ($sort['models'] !== null && !\in_array($modelName, $sort['models'])) + ) { + continue; + } + + $query->orderBy(static::$table . '_d' . $depth . '.' . $column, $sort['order']); + } + + // handle conditional foreach (self::$withFields as $condKey => $condValue) { if (($column = self::getColumnByMember($condKey)) === null || ($condValue['models'] !== null && !\in_array($modelName, $condValue['models'])) @@ -3382,7 +3444,7 @@ class DataMapperAbstract implements DataMapperInterface // get HasManyQuery (but only for elements which have a 'column' defined) if ($depth > 1 && self::$relations === RelationType::ALL) { foreach (static::$hasMany as $key => $rel) { - // @todo: impl. conditiona/with handling, sort, limit, filter or is this not required here? + // @todo: impl. conditional/with handling, sort, limit, filter or is this not required here? if (isset($rel['external']) || !isset($rel['column']) // @todo: conflict with getHasMany()???!?!?!?! || (isset(self::$withFields[$key]) && self::$withFields[$key]['ignore']) ) { diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 9c6b58914..b1c6e5b98 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -724,7 +724,7 @@ class Builder extends BuilderAbstract } /** - * Order by oldest. + * Order by. * * @param string|array $columns Columns * @param string|string[] $order Orders @@ -736,19 +736,13 @@ class Builder extends BuilderAbstract public function orderBy(string | array $columns, string | array $order = 'DESC') : self { if (\is_string($columns)) { - if (!\is_string($order)) { - throw new \InvalidArgumentException(); - } + $columns = [$columns]; + } - if (!isset($this->orders[$order])) { - $this->orders[$order] = []; - } + foreach ($columns as $key => $column) { + $tOrder = \is_string($order) ? $order : $order[$key]; - $this->orders[$order][] = $columns; - } else { - foreach ($columns as $key => $column) { - $this->orders[\is_string($order) ? $order : $order[$key]][] = $column; - } + $this->orders[$column] = $tOrder; } return $this; diff --git a/DataStorage/Database/Query/Grammar/Grammar.php b/DataStorage/Database/Query/Grammar/Grammar.php index 05638e286..d177c3801 100644 --- a/DataStorage/Database/Query/Grammar/Grammar.php +++ b/DataStorage/Database/Query/Grammar/Grammar.php @@ -535,23 +535,19 @@ class Grammar extends GrammarAbstract */ protected function compileOrders(Builder $query, array $orders) : string { - $expression = ''; + $expression = ''; + $lastOrderType = ''; - foreach ($orders as $key => $order) { - foreach ($order as $column) { - $expression .= $this->compileSystem($column) . ', '; - } - - $expression = \rtrim($expression, ', '); - $expression .= ' ' . $key . ', '; + foreach ($orders as $column => $order) { + $expression .= $this->compileSystem($column) . ' ' . $order . ', '; } + $expression = \rtrim($expression, ', '); + if ($expression === '') { return ''; } - $expression = \rtrim($expression, ', '); - return 'ORDER BY ' . $expression; } diff --git a/Event/EventManager.php b/Event/EventManager.php index 29a3231b1..60fdb1f67 100644 --- a/Event/EventManager.php +++ b/Event/EventManager.php @@ -120,6 +120,18 @@ final class EventManager implements \Countable return true; } + /** + * Clear all events + * + * @return void + * @since 1.0.0 + */ + public function clear() : bool + { + $this->groups = []; + $this->callbacks = []; + } + /** * Attach new event * diff --git a/Module/ModuleAbstract.php b/Module/ModuleAbstract.php index 2af6239cd..3c84cdbaf 100644 --- a/Module/ModuleAbstract.php +++ b/Module/ModuleAbstract.php @@ -263,15 +263,17 @@ abstract class ModuleAbstract $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj); $id = $mapper::create($obj); - $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', [ - $account, - null, $obj, - StringUtils::intHash($mapper), $trigger, - static::MODULE_NAME, - (string) $id, - '', - $ip, - ]); + $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', + [ + $account, + null, $obj, + StringUtils::intHash($mapper), $trigger, + static::MODULE_NAME, + (string) $id, + '', + $ip, + ] + ); } /** @@ -294,15 +296,17 @@ abstract class ModuleAbstract foreach ($objs as $obj) { $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj); $id = $mapper::create($obj); - $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', [ - $account, - null, $obj, - StringUtils::intHash($mapper), $trigger, - static::MODULE_NAME, - (string) $id, - '', - $ip, - ]); + $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', + [ + $account, + null, $obj, + StringUtils::intHash($mapper), $trigger, + static::MODULE_NAME, + (string) $id, + '', + $ip, + ] + ); } } @@ -331,15 +335,17 @@ abstract class ModuleAbstract $mapper(); } - $this->app->eventManager->triggerSimilar('POST:Module:' . static::MODULE_NAME . '-' . $trigger . '-update', '', [ - $account, - $old, $new, - StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger, - static::MODULE_NAME, - (string) $id, - '', - $ip, - ]); + $this->app->eventManager->triggerSimilar('POST:Module:' . static::MODULE_NAME . '-' . $trigger . '-update', '', + [ + $account, + $old, $new, + StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger, + static::MODULE_NAME, + (string) $id, + '', + $ip, + ] + ); } /** @@ -361,15 +367,17 @@ abstract class ModuleAbstract $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj); $id = $mapper::delete($obj); - $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', [ - $account, - $obj, null, - StringUtils::intHash($mapper), $trigger, - static::MODULE_NAME, - (string) $id, - '', - $ip, - ]); + $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', + [ + $account, + $obj, null, + StringUtils::intHash($mapper), $trigger, + static::MODULE_NAME, + (string) $id, + '', + $ip, + ] + ); } /** @@ -389,18 +397,54 @@ abstract class ModuleAbstract */ protected function createModelRelation(int $account, mixed $rel1, mixed $rel2, string $mapper, string $field, string $trigger, string $ip) : void { - $trigger = static::MODULE_NAME . '-' . $trigger . '-relation'; + $trigger = static::MODULE_NAME . '-' . $trigger . '-relation-create'; $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $rel1); $mapper::createRelation($field, $rel1, $rel2); - $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', [ - $account, - $rel1, $rel2, - StringUtils::intHash($mapper), $trigger, - static::MODULE_NAME, - '0', - '', - $ip, - ]); + $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', + [ + $account, + $rel1, $rel2, + StringUtils::intHash($mapper), $trigger, + static::MODULE_NAME, + '0', + '', + $ip, + ] + ); + } + + /** + * Create a model relation + * + * @param int $account Account id + * @param mixed $rel1 Object relation1 + * @param mixed $rel2 Object relation2 + * @param string $mapper Object mapper + * @param string $field Relation field + * @param string $trigger Trigger for the event manager + * @param string $ip Ip + * + * @return void + * + * @since 1.0.0 + */ + protected function deleteModelRelation(int $account, mixed $rel1, mixed $rel2, string $mapper, string $field, string $trigger, string $ip) : void + { + $trigger = static::MODULE_NAME . '-' . $trigger . '-relation-delete'; + + $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $rel1); + $mapper::deleteRelation($field, $rel1, $rel2); + $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', + [ + $account, + $rel1, $rel2, + StringUtils::intHash($mapper), $trigger, + static::MODULE_NAME, + '0', + '', + $ip, + ] + ); } } diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index e2c6c3adc..011d6e1ce 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -61,14 +61,6 @@ final class ModuleManager */ private ApplicationAbstract $app; - /** - * Application manager. - * - * @var ApplicationManager - * @since 1.0.0 - */ - private ApplicationManager $appManager; - /** * Installed modules. * @@ -511,18 +503,15 @@ final class ModuleManager $providing = $info->getProviding(); foreach ($providing as $key => $version) { if (isset($installed[$key])) { - $this->installProviding($module, $key); + $this->installProviding('/Modules/' . $module, $key); } } /* Install receiving and applications */ foreach ($this->installed as $key => $value) { - $this->installProviding($key, $module); + $this->installProviding('/Modules/' . $key, $module); } - $this->appManager = new ApplicationManager($this); - $this->installApplications($module); - return true; } catch (\Throwable $t) { return false; // @codeCoverageIgnore @@ -630,7 +619,7 @@ final class ModuleManager * * Installing additional functionality for another module * - * @param string $from From module + * @param string $from From path * @param string $for For module * * @return void @@ -639,45 +628,16 @@ final class ModuleManager */ public function installProviding(string $from, string $for) : void { - if (!\is_file($this->modulePath . $from . '/Admin/Install/' . $for . '.php')) { + if (!\is_file(__DIR__ . '/../..' . $from . '/Admin/Install/' . $for . '.php')) { return; } - $class = '\\Modules\\' . $from . '\\Admin\\Install\\' . $for; + $from = \str_replace('/', '\\', $from); + + $class = $from . '\\Admin\\Install\\' . $for; $class::install($this->modulePath, $this->app); } - /** - * Install applications. - * - * Installing additional functionality for another module - * - * @param string $from From module - * - * @return void - * - * @since 1.0.0 - */ - public function installApplications(string $from) : void - { - if (!\is_dir($this->modulePath . $from . '/Admin/Install/Application')) { - return; - } - - $dirs = \scandir($this->modulePath . $from . '/Admin/Install/Application'); - if ($dirs === false) { - return; - } - - foreach ($dirs as $dir) { - if ($dir === '.' || $dir === '..') { - continue; - } - - $this->appManager->install($dir, __DIR__ . '/../../Web/' . \basename($dir)); - } - } - /** * Get module instance. * diff --git a/Module/StatusAbstract.php b/Module/StatusAbstract.php index f1b5ca40b..e2d3d3052 100644 --- a/Module/StatusAbstract.php +++ b/Module/StatusAbstract.php @@ -228,7 +228,7 @@ abstract class StatusAbstract { $query = new Builder($dbPool->get('update')); $query->update('module') - ->sets('module.module_active', 1) + ->sets('module.module_active', ModuleStatus::ACTIVE) ->where('module.module_id', '=', $info->getInternalName()) ->execute(); } @@ -416,7 +416,7 @@ abstract class StatusAbstract { $query = new Builder($dbPool->get('update')); $query->update('module') - ->sets('module.module_active', 0) + ->sets('module.module_active', ModuleStatus::INACTIVE) ->where('module.module_id', '=', $info->getInternalName()) ->execute(); } diff --git a/Router/RouterInterface.php b/Router/RouterInterface.php index 66be2862a..5fb263f27 100644 --- a/Router/RouterInterface.php +++ b/Router/RouterInterface.php @@ -34,4 +34,12 @@ interface RouterInterface * @since 1.0.0 */ public function importFromFile(string $path) : bool; + + /** + * Clear routes + * + * @return void + * @since 1.0.0 + */ + public function clear() : void; } diff --git a/Router/SocketRouter.php b/Router/SocketRouter.php index 994c395cf..fc2647ddc 100644 --- a/Router/SocketRouter.php +++ b/Router/SocketRouter.php @@ -69,6 +69,17 @@ final class SocketRouter implements RouterInterface return true; } + /** + * Clear routes + * + * @return void + * @since 1.0.0 + */ + public function clear() : void + { + $this->routes = []; + } + /** * Add route. * diff --git a/Router/WebRouter.php b/Router/WebRouter.php index 5a8f7ac45..3ae53954b 100644 --- a/Router/WebRouter.php +++ b/Router/WebRouter.php @@ -71,6 +71,17 @@ final class WebRouter implements RouterInterface return true; } + /** + * Clear routes + * + * @return void + * @since 1.0.0 + */ + public function clear() : void + { + $this->routes = []; + } + /** * Add route. * @@ -144,25 +155,35 @@ final class WebRouter implements RouterInterface ) { // if csrf is required but not set if (isset($d['csrf']) && $d['csrf'] && $csrf === null) { - return $app !== null ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) : $this->route('/e403', $csrf, $verb); + return $app !== null + ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) + : $this->route('/e403', $csrf, $verb); } // if permission check is invalid if ((isset($d['permission']) && $account === null) || (isset($d['permission']) && !$account?->hasPermission( - $d['permission']['type'] ?? 0, $d['permission']['unit'] ?? $orgId, $app, $d['permission']['module'] ?? null, $d['permission']['state'] ?? null + $d['permission']['type'] ?? 0, + $d['permission']['unit'] ?? $orgId, + $app, + $d['permission']['module'] ?? null, + $d['permission']['state'] ?? null ) ) ) { - return $app !== null ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) : $this->route('/e403', $csrf, $verb); + return $app !== null + ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) + : $this->route('/e403', $csrf, $verb); } // if validation check is invalid if (isset($d['validation'])) { - foreach ($d['validation'] as $name => $pattern) { - if (!isset($data[$name]) || \preg_match($pattern, $data[$name]) !== 1) { - return $app !== null ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) : $this->route('/e403', $csrf, $verb); + foreach ($d['validation'] as $name => $validation) { + if (!isset($data[$name]) || \preg_match($validation, $data[$name]) !== 1) { + return $app !== null + ? $this->route('/' . \strtolower($app) . '/e403', $csrf, $verb) + : $this->route('/e403', $csrf, $verb); } } } diff --git a/tests/Application/ApplicationManagerTest.php b/tests/Application/ApplicationManagerTest.php index b211df695..b048971db 100644 --- a/tests/Application/ApplicationManagerTest.php +++ b/tests/Application/ApplicationManagerTest.php @@ -69,7 +69,7 @@ class ApplicationManagerTest extends \PHPUnit\Framework\TestCase $app->moduleManager = new ModuleManager($app, __DIR__ . '/../../../Modules/'); - $this->appManager = new ApplicationManager($app->moduleManager); + $this->appManager = new ApplicationManager(); } /** diff --git a/tests/Router/WebRouterTest.php b/tests/Router/WebRouterTest.php index 93e4e6417..272aabf3f 100644 --- a/tests/Router/WebRouterTest.php +++ b/tests/Router/WebRouterTest.php @@ -349,7 +349,7 @@ class WebRouterTest extends \PHPUnit\Framework\TestCase RouteVerb::GET | RouteVerb::SET, false, [], - '/^.*?(something)=(\d*).*?$/' + '/^.*?(something)=(?\d*).*?$/' ); self::assertEquals( @@ -358,6 +358,7 @@ class WebRouterTest extends \PHPUnit\Framework\TestCase 'data' => [ '/backends/admin?something=123&sd=asdf', 'something', + 'name' => '123', '123', ], ]],