diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 9dfc26bc..f86b6290 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -2,11 +2,7 @@ $finder = PhpCsFixer\Finder::create() ->in([__DIR__]) - ->exclude([ - 'cache', - 'build', - 'vendor', - ]); + ->exclude(['vendor']); return (new PhpCsFixer\Config()) ->setRiskyAllowed(true) @@ -48,9 +44,6 @@ 'no_superfluous_elseif' => false, 'ordered_class_elements' => false, 'php_unit_internal_class' => false, - 'php_unit_test_case_static_method_calls' => [ - 'call_type' => 'this', - ], 'php_unit_test_class_requires_covers' => false, 'phpdoc_add_missing_param_annotation' => false, 'return_assignment' => false, diff --git a/README.md b/README.md index ea5c76c9..255dcbab 100644 --- a/README.md +++ b/README.md @@ -104,9 +104,9 @@ Displays email and 2 password fields (for confirmation). If filled successfully ``` php \Atk4\Login\LoginForm::addTo($app, [ - 'auth'=>$app->auth, - //'successLink'=>['dashboard'], - //'forgotLink'=>['forgot'], + 'auth'=>$app->auth, + //'successLink'=>['dashboard'], + //'forgotLink'=>['forgot'], ]); ``` @@ -124,7 +124,7 @@ To check if user is currently logged in: ``` php if ($app->auth->user->isLoaded()) { - // logged-in + // logged-in } ``` diff --git a/composer.json b/composer.json index a8048863..db8202ef 100644 --- a/composer.json +++ b/composer.json @@ -33,23 +33,26 @@ }, "require-release": { "php": ">=7.4 <8.2", - "atk4/ui": "~3.2.0" + "atk4/ui": "~4.0.0" }, "require-dev": { - "behat/behat": "^3.9", - "behat/mink": "^1.9", "behat/mink-extension": "^2.3.1", "behat/mink-selenium2-driver": "^1.5", "ergebnis/composer-normalize": "^2.13", "friendsofphp/php-cs-fixer": "^3.0", - "instaclick/php-webdriver": "^1.4.7", "johnkary/phpunit-speedtrap": "^3.3", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0", - "phpunit/phpunit": "^9.5.5", - "symfony/console": "^4.4.30 || ^5.3.7", - "symfony/css-selector": "^4.4.24 || ^5.2.9" + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^9.5.5" + }, + "conflict": { + "behat/behat": "<3.9", + "behat/mink": "<1.9", + "instaclick/php-webdriver": "<1.4.13", + "symfony/console": "<4.4.30 || >=5 <5.3.7", + "symfony/css-selector": "<4.4.24 || >=5 <5.2.9" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/demos/_includes/App.php b/demos/_includes/App.php index bf28772a..bc8bd49a 100644 --- a/demos/_includes/App.php +++ b/demos/_includes/App.php @@ -8,9 +8,6 @@ use Atk4\Login\Auth; use Atk4\Ui\Layout; -/** - * Example implementation of your Authenticated application. - */ class App extends \Atk4\Ui\App { /** @var Auth */ @@ -24,7 +21,7 @@ protected function init(): void $this->initLayout([Layout\Admin::class]); - // Construct menu + // construct menu $this->layout->menuLeft->addItem(['Dashboard', 'icon' => 'info'], ['index']); $this->layout->menuLeft->addItem(['Setup demo database', 'icon' => 'cogs'], ['admin-setup']); @@ -51,7 +48,7 @@ public function initAuth(bool $check = true): void { $this->auth = new Auth($this, ['check' => $check, 'pageDashboard' => 'index']); - // Cannot setmodel at this stage :( + // cannot set model at this stage :( $m = new \Atk4\Login\Model\User($this->db); $this->auth->setModel($m); } diff --git a/demos/_includes/MigratorConsole.php b/demos/_includes/MigratorConsole.php index b21a67e8..c0ceb54e 100644 --- a/demos/_includes/MigratorConsole.php +++ b/demos/_includes/MigratorConsole.php @@ -8,13 +8,10 @@ use Atk4\Core\DynamicMethodTrait; use Atk4\Core\Factory; use Atk4\Core\HookTrait; +use Atk4\Data\Model; use Atk4\Data\Schema\Migrator; use Atk4\Ui\Console; -/** - * Makes sure your database is adjusted for one or several models, - * that you specify. - */ class MigratorConsole extends Console { use AppScopeTrait; @@ -33,9 +30,9 @@ class MigratorConsole extends Console /** * Provided with array of models, perform migration for each of them. * - * @param array $models + * @param array $models */ - public function migrateModels($models): void + public function migrateModels(array $models): void { // run inside callback $this->set(function ($console) use ($models) { @@ -45,7 +42,7 @@ public function migrateModels($models): void foreach ($models as $model) { if (!is_object($model)) { - $model = Factory::factory((array) $model); + $model = Factory::factory($model); $model->setPersistence($console->getApp()->db); } diff --git a/demos/admin-setup.php b/demos/admin-setup.php index 52b9333f..ac6f316d 100644 --- a/demos/admin-setup.php +++ b/demos/admin-setup.php @@ -100,7 +100,7 @@ $c->notice('Data imported'); }); -$c1->migrateModels([Role::class, User::class, AccessRule::class, Client::class]); +$c1->migrateModels([[Role::class], [User::class], [AccessRule::class], [Client::class]]); // button to execute migration $b = Button::addTo($v, ['Run migration', 'icon' => 'check']); diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 1000cdd6..03f9f173 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,29 +1,18 @@ +includes: + - phar://phpstan.phar/conf/bleedingEdge.neon + parameters: level: 6 paths: - ./ excludePaths: - - cache/ - - build/ - vendor/ - # TODO review once we drop PHP 7.x support - treatPhpDocTypesAsCertain: false - - # some extra rules - checkAlwaysTrueCheckTypeFunctionCall: true - checkAlwaysTrueInstanceof: true - checkAlwaysTrueStrictComparison: true - checkExplicitMixedMissingReturn: true - checkFunctionNameCase: true - # TODO checkMissingClosureNativeReturnTypehintRule: true - reportMaybesInMethodSignatures: true - reportStaticMethodSignatures: true - checkTooWideReturnTypesInProtectedAndPublicMethods: true - checkMissingIterableValueType: false # TODO - ignoreErrors: - #- '~^Unsafe usage of new static\(\)\.$~' + - '~^(Property .+ has|Method .+\(\) (has parameter \$.+ with|return type has)) no value type specified in iterable type .+\.~' + + # relax strict rules + - '~^Only booleans are allowed in .+, .+ given( on the (left|right) side)?\.~' # TODO these rules are generated, this ignores should be fixed in the code - @@ -58,3 +47,7 @@ parameters: message: '~^Call to an undefined method Atk4\\Ui\\Form\\Control::addAction\(\)\.$~' count: 1 path: src/UserAdmin.php + - + message: '~^Call to an undefined method Atk4\\Ui\\View::hide\(\)\.$~' + count: 1 + path: src/UserAdmin.php diff --git a/src/Acl.php b/src/Acl.php index 1d621707..cf89d598 100644 --- a/src/Acl.php +++ b/src/Acl.php @@ -6,6 +6,8 @@ use Atk4\Data\Exception; use Atk4\Data\Model; +use Atk4\Login\Model\AccessRule; +use Atk4\Login\Model\User; /** * Access Control Layer. Create one and pass it to your Auth controller. @@ -23,11 +25,11 @@ class Acl /** * Returns AccessRules model for logged in user and in model scope. * - * @return \Atk4\Login\Model\AccessRule + * @return AccessRule */ public function getRules(Model $model) { - /** @var \Atk4\Login\Model\User */ + /** @var User */ $user = $this->auth->user; if (!$user->isLoaded()) { @@ -80,9 +82,7 @@ public function applyRestrictions(Model $m): void } // add conditions on model - /* - * this will work in future when we will have json encoded condition structure stored in here - * for now let's comment this out + /* this will work in future when we will have json encoded condition structure stored in here if ($rule['conditions']) { $this->applyConditions($m, $rule['conditions']); } diff --git a/src/Auth.php b/src/Auth.php index ab9ac137..7eb93517 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -16,16 +16,14 @@ use Atk4\Data\Model; use Atk4\Data\Persistence; use Atk4\Login\Cache\Session; +use Atk4\Login\Form as LoginForm; use Atk4\Login\Layout\Narrow; use Atk4\Login\Model\User; use Atk4\Ui\App; -use Atk4\Ui\Layout\Admin; +use Atk4\Ui\Form; +use Atk4\Ui\Layout; use Atk4\Ui\VirtualPage; -/** - * Authentication controller. Add this to your application somewhere - * and it will work wonders. - */ class Auth { use AppScopeTrait; @@ -82,7 +80,7 @@ class Auth * * @var array */ - public $formLoginSeed = [Form\Login::class]; + public $formLoginSeed = [LoginForm\Login::class]; /** @var array Seed that would create VirtualPage for adding Preference page content */ public $preferencePage = [VirtualPage::class]; @@ -271,11 +269,11 @@ public function check(): void public function addUserMenu(): void { // add admin menu - if ($this->hasUserMenu && $this->getApp()->layout instanceof Admin) { + if ($this->hasUserMenu && $this->getApp()->layout instanceof Layout\Admin) { $menu = $this->getApp()->layout->menuRight->addMenu($this->user->getTitle()); if ($this->hasPreferences) { - $userPage = VirtualPage::assertInstanceOf($this->getApp()->add($this->preferencePage)); + $userPage = VirtualPage::addToWithCl($this->getApp(), $this->preferencePage); $this->setPreferencePage($userPage); $menu->addItem(['Preferences', 'icon' => 'user'], $userPage->getUrl()); @@ -290,7 +288,7 @@ public function addUserMenu(): void */ public function setPreferencePage(VirtualPage $page): void { - $f = \Atk4\Ui\Form::addTo($page); + $f = Form::addTo($page); $f->addHeader(['User Preferences', 'subHeader' => $this->user->getTitle(), 'icon' => 'user']); $f->setModel($this->user); $f->onSubmit(function ($f) { @@ -314,15 +312,11 @@ public function displayLoginForm(array $seed = []): void $app->initLayout([Narrow::class]); $app->title .= ' - Login Required'; $app->layout->template->set('title', $app->title); - $app->add(array_merge( - $this->formLoginSeed, - [ - 'auth' => $this, - 'linkSuccess' => [$this->pageAfterLogin], - 'linkForgot' => false, - ], - $seed - )); + $app->add(Factory::factory($this->formLoginSeed, array_merge([ + 'auth' => $this, + 'linkSuccess' => [$this->pageAfterLogin], + 'linkForgot' => false, + ], $seed))); $app->run(); $app->callExit(); } diff --git a/src/Cache/Session.php b/src/Cache/Session.php index 6e2ccfdc..febfeba3 100644 --- a/src/Cache/Session.php +++ b/src/Cache/Session.php @@ -10,9 +10,6 @@ use Atk4\Ui\App; use Atk4\Ui\SessionTrait; -/** - * Session cache for authentication controller. - */ class Session // implements CacheInterface { use AppScopeTrait; diff --git a/src/Feature/PasswordManagementTrait.php b/src/Feature/PasswordManagementTrait.php index 15562814..21c4014d 100644 --- a/src/Feature/PasswordManagementTrait.php +++ b/src/Feature/PasswordManagementTrait.php @@ -214,8 +214,7 @@ private function calculatePasswordStrength(string $pw): int if ($length > 2) { // consecutive letters and numbers foreach (['/[a-z]{2,}/', '/[A-Z]{2,}/', '/[0-9]{2,}/'] as $re) { - preg_match_all($re, $pw, $matches, \PREG_SET_ORDER); - if (!empty($matches)) { + if (preg_match_all($re, $pw, $matches, \PREG_SET_ORDER)) { foreach ($matches as $match) { $score -= (strlen($match[0]) - 1) * 2; } @@ -262,17 +261,17 @@ private function findSequence(array $charLocs, string $src): array $charDistance = ord($charNext) - ord($charHere); if ($distance === 1 && $charDistance === 1) { // We find a pair of sequential chars! - if (empty($sequence)) { + if ($sequence === []) { $sequence = [$charHere, $charNext]; } else { $sequence[] = $charNext; } - } elseif (!empty($sequence)) { + } elseif ($sequence !== []) { $sequences[] = $sequence; $sequence = []; } } - if (!empty($sequence)) { + if ($sequence !== []) { $sequences[] = $sequence; } diff --git a/src/Feature/SetupAccessRuleModelTrait.php b/src/Feature/SetupAccessRuleModelTrait.php index 4d998beb..b9f5360f 100644 --- a/src/Feature/SetupAccessRuleModelTrait.php +++ b/src/Feature/SetupAccessRuleModelTrait.php @@ -24,7 +24,6 @@ protected function init() // And this new class should be separated to let's say AccessRule/Model class so we can // also have AccessRule/Interface or AccessRule/View or AccessRule/Page class in future // with different config properties - } }); */ diff --git a/src/Form/Control/Actions.php b/src/Form/Control/Actions.php index a85b671a..c0d086a5 100644 --- a/src/Form/Control/Actions.php +++ b/src/Form/Control/Actions.php @@ -6,18 +6,14 @@ use Atk4\Data\Model; -/** - * Form field to choose one or multiple model actions. - */ class Actions extends GenericDropdown { public function setModel(Model $model, array $fields = null): void { - // set function for dropdown row rendering $this->renderRowFunction = function ($action) { return [ 'value' => $action->shortName, - 'title' => $action->caption ?: $action->shortName, + 'title' => $action->caption ?? $action->shortName, 'icon' => ($action->ui['icon'] ?? null), ]; }; @@ -25,9 +21,6 @@ public function setModel(Model $model, array $fields = null): void parent::setModel($model); } - /** - * Renders view. - */ protected function renderView(): void { $model = $this->getModel(); diff --git a/src/Form/Control/Fields.php b/src/Form/Control/Fields.php index 55e9d0ef..212b8fcb 100644 --- a/src/Form/Control/Fields.php +++ b/src/Form/Control/Fields.php @@ -4,17 +4,14 @@ namespace Atk4\Login\Form\Control; +use Atk4\Data\Field; use Atk4\Data\Model; -/** - * Form field to choose one or multiple model fields. - */ class Fields extends GenericDropdown { public function setModel(Model $model, array $fields = null): void { - // set function for dropdown row rendering - $this->renderRowFunction = function ($field) { + $this->renderRowFunction = function (Field $field) { return [ 'value' => $field->shortName, 'title' => $field->getCaption(), @@ -25,9 +22,6 @@ public function setModel(Model $model, array $fields = null): void parent::setModel($model); } - /** - * Renders view. - */ protected function renderView(): void { $model = $this->getModel(); diff --git a/src/Form/Control/GenericDropdown.php b/src/Form/Control/GenericDropdown.php index 0e32b522..0b183823 100644 --- a/src/Form/Control/GenericDropdown.php +++ b/src/Form/Control/GenericDropdown.php @@ -6,12 +6,12 @@ use Atk4\Data\Model; use Atk4\Ui\Exception; -use Atk4\Ui\Form\Control\Dropdown; +use Atk4\Ui\Form; /** * Form field to choose one or multiple entities. */ -abstract class GenericDropdown extends Dropdown +abstract class GenericDropdown extends Form\Control\Dropdown { /** @var bool Dropdown with multiselect */ public $isMultiple = true; diff --git a/src/Form/Login.php b/src/Form/Login.php index ae29a90b..6952462c 100644 --- a/src/Form/Login.php +++ b/src/Form/Login.php @@ -6,7 +6,6 @@ use Atk4\Login\Auth; use Atk4\Ui\Form; -use Atk4\Ui\Form\Control; use Atk4\Ui\View; /** @@ -30,14 +29,12 @@ protected function init(): void { parent::init(); - $form = $this; + $this->buttonSave->set('Sign in'); + $this->buttonSave->addClass('large fluid'); + $this->buttonSave->iconRight = 'right arrow'; - $form->buttonSave->set('Sign in'); - $form->buttonSave->addClass('large fluid'); - $form->buttonSave->iconRight = 'right arrow'; - - $form->addControl($this->auth->fieldLogin, [], ['required' => true]); - $p = $form->addControl($this->auth->fieldPassword, [Control\Password::class], ['required' => true]); + $this->addControl($this->auth->fieldLogin, [], ['required' => true]); + $p = $this->addControl($this->auth->fieldPassword, [Form\Control\Password::class], ['required' => true]); if ($this->linkForgot) { $p->addAction(['icon' => 'question']) @@ -46,7 +43,7 @@ protected function init(): void } if ($this->cookieWarning) { - View::addTo($form, ['element' => 'p']) + View::addTo($this, ['element' => 'p']) ->addStyle('font-style', 'italic') ->set($this->cookieWarning); } diff --git a/src/Form/Register.php b/src/Form/Register.php index 1417af39..b2c6ba07 100644 --- a/src/Form/Register.php +++ b/src/Form/Register.php @@ -20,27 +20,24 @@ protected function init(): void { parent::init(); - $form = $this; - - $form->buttonSave->set('Register'); - $form->buttonSave->addClass('large fluid'); - $form->buttonSave->iconRight = 'right arrow'; + $this->buttonSave->set('Register'); + $this->buttonSave->addClass('large fluid'); + $this->buttonSave->iconRight = 'right arrow'; } public function setModel(Model $user, array $fields = null): void { parent::setModel($user, []); - $form = $this; - $form->addControl('name', [], ['required' => true]); - $form->addControl('email', [], ['required' => true]); - $form->addControl('password', [], ['type' => 'string', 'required' => true]) + $this->addControl('name', [], ['required' => true]); + $this->addControl('email', [], ['required' => true]); + $this->addControl('password', [], ['type' => 'string', 'required' => true]) ->setInputAttr('autocomplete', 'new-password'); - $form->addControl('password2', [], ['type' => 'string', 'neverPersist' => true, 'required' => true, 'caption' => 'Repeat Password']) + $this->addControl('password2', [], ['type' => 'string', 'neverPersist' => true, 'required' => true, 'caption' => 'Repeat Password']) ->setInputAttr('autocomplete', 'new-password'); // on form submit save new user in persistence - $form->onSubmit(function ($form) { + $this->onSubmit(function ($form) { // Look if user already exist? $model = $this->model->getModel(); $entity = $model->tryLoadBy($this->auth->fieldLogin, $form->model->get($this->auth->fieldLogin)); diff --git a/src/Layout/Narrow.php b/src/Layout/Narrow.php index 1b743748..6b2d34c1 100644 --- a/src/Layout/Narrow.php +++ b/src/Layout/Narrow.php @@ -4,11 +4,12 @@ namespace Atk4\Login\Layout; +use Atk4\Ui\Layout; + /** * Narrow App layout for login form page. */ -class Narrow extends \Atk4\Ui\Layout +class Narrow extends Layout { - /** @var string default template */ public $defaultTemplate = __DIR__ . '/../../template/layout/narrow.html'; } diff --git a/src/Model/AccessRule.php b/src/Model/AccessRule.php index 631a65a2..2bbaed3c 100644 --- a/src/Model/AccessRule.php +++ b/src/Model/AccessRule.php @@ -8,7 +8,7 @@ use Atk4\Login\Feature\SetupAccessRuleModelTrait; /** - * White-list access control rules. + * Whitelist access control rules. */ class AccessRule extends Model { diff --git a/src/Model/User.php b/src/Model/User.php index 63f46e7a..912b8d56 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -11,9 +11,6 @@ use Atk4\Login\Feature\SetupUserModelTrait; use Atk4\Login\Feature\SignupTrait; -/** - * Example user data model. - */ class User extends Model { use PasswordManagementTrait; diff --git a/src/RoleAdmin.php b/src/RoleAdmin.php index cac3ca0b..16020d2c 100644 --- a/src/RoleAdmin.php +++ b/src/RoleAdmin.php @@ -6,15 +6,13 @@ use Atk4\Core\DebugTrait; use Atk4\Data\Model; -use Atk4\Login\Model\AccessRule; use Atk4\Ui\Crud; use Atk4\Ui\Header; -use Atk4\Ui\Table\Column\ActionButtons; +use Atk4\Ui\Table; use Atk4\Ui\View; /** - * View for Role administration. - * Includes Role association with AccessRule. + * View for Role administration. Includes Role association with AccessRule. */ class RoleAdmin extends Crud { @@ -28,7 +26,7 @@ public function setModel(Model $role, array $fields = null): void parent::setModel($role); // Add new table column used for actions - $column = $this->table->addColumn(null, [ActionButtons::class, 'caption' => '']); + $column = $this->table->addColumn(null, [Table\Column\ActionButtons::class, 'caption' => '']); $column->addModal(['icon' => 'cogs'], 'Role Permissions', function (View $v, $id) use ($role) { $role = $role->load($id); diff --git a/src/UserAdmin.php b/src/UserAdmin.php index 2b5b6a90..7b8b586c 100644 --- a/src/UserAdmin.php +++ b/src/UserAdmin.php @@ -10,12 +10,11 @@ use Atk4\Ui\Crud; use Atk4\Ui\Form; use Atk4\Ui\JsToast; -use Atk4\Ui\Table\Column\ActionButtons; +use Atk4\Ui\Table; use Atk4\Ui\View; /** - * View for User administration. - * Includes User association with Role. + * View for User administration. Includes User association with Role. */ class UserAdmin extends View { @@ -43,10 +42,10 @@ public function setModel(Model $user): void $this->crud->setModel($user); // Add new table column used for actions - $column = $this->crud->table->addColumn(null, [ActionButtons::class, 'caption' => '']); + $column = $this->crud->table->addColumn(null, [Table\Column\ActionButtons::class, 'caption' => '']); // Pop-up for resetting password. Will display button for generating random password - $column->addModal(['icon' => 'key'], 'Change Password', function ($v, $id) { + $column->addModal(['icon' => 'key'], 'Change Password', function (View $v, $id) { $userEntity = $this->model->load($id); $form = Form::addTo($v); @@ -73,7 +72,7 @@ public function setModel(Model $user): void }); /* - $column->addModal(['icon' => 'eye'], 'Details', function ($v, $id, $userEntity) { + $column->addModal(['icon' => 'eye'], 'Details', function (View $v, $id, $userEntity) { $userEntity = $this->model->load($id); $c = Columns::addTo($v); diff --git a/tests/AclTest.php b/tests/AclTest.php index 4df5a8eb..0a957a7f 100644 --- a/tests/AclTest.php +++ b/tests/AclTest.php @@ -37,7 +37,7 @@ protected function createAuthAndLogin(string $user): Auth $auth->setModel($this->createUserModel()); $auth->tryLogin($user, $user === 'admin' ? 'admin' : 'user'); - $this->assertTrue($auth->isLoggedIn()); + static::assertTrue($auth->isLoggedIn()); $auth->setAcl(new Acl(), $this->db); @@ -52,7 +52,7 @@ protected function invokeAndAssertAclException(\Closure $fx): void } catch (\Exception $e) { } - $this->assertInstanceOf(\Atk4\Core\Exception::class, $e); // TODO should be specific ACL exception + static::assertInstanceOf(\Atk4\Core\Exception::class, $e); // TODO should be specific ACL exception } public function testAclBasic(): void @@ -63,28 +63,28 @@ public function testAclBasic(): void // "user" user can edit client.vat_number field $clientEntity = (new AclTestClient($this->db))->load(1); - $this->assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); + static::assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); $clientEntity->save([$clientEntity->fieldName()->vat_number => 'new']); - $this->assertSame($clientEntity->vat_number, 'new'); + static::assertSame($clientEntity->vat_number, 'new'); // but not client.balance field - $this->assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); + static::assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); $clientEntity = (new AclTestClient($this->db))->load(1); // // TODO ACL currently work on UI level only, reject edit on data model layer // $this->invokeAndAssertAclException(function () use ($clientEntity) { // $clientEntity->save([$clientEntity->fieldName()->balance => 100]); // }); -// $this->assertSame($clientEntity->balance, 1234.56); +// static::assertSame($clientEntity->balance, 1234.56); // must also match parent classes $clientEntity = (new class($this->db) extends AclTestClient {})->load(1); - $this->assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); - $this->assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); + static::assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); + static::assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); // and interfaces $clientEntity = (new AclTestClient2($this->db))->load(1); - $this->assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); - $this->assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); + static::assertTrue($clientEntity->getField($clientEntity->fieldName()->vat_number)->isEditable()); + static::assertFalse($clientEntity->getField($clientEntity->fieldName()->balance)->isEditable()); } } diff --git a/tests/AuthTest.php b/tests/AuthTest.php index b47b7a2f..5bc2b33f 100644 --- a/tests/AuthTest.php +++ b/tests/AuthTest.php @@ -13,23 +13,23 @@ public function testDb(): void $this->setupDefaultDb(); $u = $this->createUserModel(); - $this->assertSame(2, count($u->export())); + static::assertCount(2, $u->export()); $r = $this->createRoleModel(); - $this->assertSame(2, count($r->export())); + static::assertCount(2, $r->export()); $a = $this->createAccessRuleModel(); - $this->assertSame(3, count($a->export())); + static::assertCount(3, $a->export()); // password field should not be visible in UI by default - $this->assertFalse($u->getField('password')->isVisible()); + static::assertFalse($u->getField('password')->isVisible()); // test traversal - $this->assertSame(2, count((clone $u)->load(2)->ref('AccessRules')->export())); - $this->assertSame(2, (clone $u)->load(2)->ref('role_id')->getId()); - $this->assertSame(2, count((clone $r)->load(2)->ref('AccessRules')->export())); - $this->assertSame(1, count((clone $r)->load(2)->ref('Users')->export())); - $this->assertSame(2, (clone $a)->load(2)->ref('role_id')->getId()); + static::assertCount(2, (clone $u)->load(2)->ref('AccessRules')->export()); + static::assertSame(2, (clone $u)->load(2)->ref('role_id')->getId()); + static::assertCount(2, (clone $r)->load(2)->ref('AccessRules')->export()); + static::assertCount(1, (clone $r)->load(2)->ref('Users')->export()); + static::assertSame(2, (clone $a)->load(2)->ref('role_id')->getId()); } public function _testAuth(bool $cacheEnabled): void @@ -48,46 +48,46 @@ public function _testAuth(bool $cacheEnabled): void // test Auth without automatic check to avoid UI involvement (login form, user menu etc) $auth = $createAuthFx(); - $this->assertFalse($auth->isLoggedIn()); + static::assertFalse($auth->isLoggedIn()); // wrong login $ok = $auth->tryLogin('admin', 'wrong'); - $this->assertFalse($ok); - $this->assertFalse($auth->isLoggedIn()); + static::assertFalse($ok); + static::assertFalse($auth->isLoggedIn()); // correct login $ok = $auth->tryLogin('admin', 'admin'); - $this->assertTrue($ok); - $this->assertTrue($auth->isLoggedIn()); + static::assertTrue($ok); + static::assertTrue($auth->isLoggedIn()); // logout $auth->logout(); - $this->assertFalse($auth->isLoggedIn()); + static::assertFalse($auth->isLoggedIn()); // now login again, try to change some property, save and check if it's changed in actual DB $auth = $createAuthFx(); $auth->tryLogin('user', 'user'); - $this->assertTrue($auth->isLoggedIn()); - $this->assertSame('user', $auth->user->get($auth->fieldLogin)); + static::assertTrue($auth->isLoggedIn()); + static::assertSame('user', $auth->user->get($auth->fieldLogin)); $auth->user->set('name', 'Test User'); - $this->assertSame('Test User', $auth->user->get('name')); + static::assertSame('Test User', $auth->user->get('name')); $auth->user->save(); - $this->assertSame('Test User', $auth->user->get('name')); + static::assertSame('Test User', $auth->user->get('name')); $auth = $createAuthFx(); $auth->tryLogin('user', 'user'); - $this->assertTrue($auth->isLoggedIn()); - $this->assertSame('user', $auth->user->get($auth->fieldLogin)); - $this->assertSame('Test User', $auth->user->get('name')); + static::assertTrue($auth->isLoggedIn()); + static::assertSame('user', $auth->user->get($auth->fieldLogin)); + static::assertSame('Test User', $auth->user->get('name')); // now create new Auth object, set model and see if it will pick up // last logged user from cache if ($cacheEnabled) { $auth = $createAuthFx(); - $this->assertTrue($auth->isLoggedIn()); - $this->assertSame('user', $auth->user->get($auth->fieldLogin)); - $this->assertSame('Test User', $auth->user->get('name')); + static::assertTrue($auth->isLoggedIn()); + static::assertSame('user', $auth->user->get($auth->fieldLogin)); + static::assertSame('Test User', $auth->user->get('name')); $createAuthWithShortExpireTimeFx = function () use ($createAuthFx) { return $createAuthFx([ @@ -99,12 +99,12 @@ public function _testAuth(bool $cacheEnabled): void $auth->tryLogin('admin', 'admin'); // saves in cache and set timer $auth = $createAuthWithShortExpireTimeFx(); - $this->assertTrue($auth->isLoggedIn()); + static::assertTrue($auth->isLoggedIn()); // now sleep more than expireTime (cache should expire) and try again usleep(60_000); $auth = $createAuthWithShortExpireTimeFx(); - $this->assertFalse($auth->isLoggedIn()); + static::assertFalse($auth->isLoggedIn()); } } @@ -125,12 +125,12 @@ public function testAuthCustomLoginAndPasswordFieldName(): void $auth = new Auth($this->createAppForSession(), ['check' => false]); $auth->setModel($this->createUserModel(), 'name', null); $auth->tryLogin('admin', 'admin'); // there is no "name" = 'admin' - $this->assertFalse($auth->isLoggedIn()); + static::assertFalse($auth->isLoggedIn()); $auth = new Auth($this->createAppForSession(), ['check' => false]); $auth->setModel($this->createUserModel(), 'name', null); $auth->tryLogin('Administrator', 'admin'); - $this->assertTrue($auth->isLoggedIn()); + static::assertTrue($auth->isLoggedIn()); $auth = new Auth($this->createAppForSession(), ['check' => false]); $auth->setModel($this->createUserModel(), null, 'name'); diff --git a/tests/Feature/PasswordManagementTest.php b/tests/Feature/PasswordManagementTest.php index cfe4892a..84a49852 100644 --- a/tests/Feature/PasswordManagementTest.php +++ b/tests/Feature/PasswordManagementTest.php @@ -19,7 +19,7 @@ public function testGenerateRandomPassword(): void use PasswordManagementTrait; }; $model = new $class(new Persistence\Array_()); - $this->assertIsString($model->generateRandomPassword(4)); + static::assertIsString($model->generateRandomPassword(4)); } public function testBasic(): void @@ -27,46 +27,46 @@ public function testBasic(): void $this->setupDefaultDb(); $model = $this->createUserModel(); - $this->assertTrue($model->hasUserAction('generateRandomPassword')); - $this->assertTrue($model->hasUserAction('resetPassword')); - $this->assertTrue($model->hasUserAction('checkPasswordStrength')); + static::assertTrue($model->hasUserAction('generateRandomPassword')); + static::assertTrue($model->hasUserAction('resetPassword')); + static::assertTrue($model->hasUserAction('checkPasswordStrength')); // simply generate password and return it - $this->assertIsString($model->createEntity()->executeUserAction('generateRandomPassword', 8)); + static::assertIsString($model->createEntity()->executeUserAction('generateRandomPassword', 8)); // generate new password and set model record password field and save it and email if possible $entity = $model->load(1); // replace callback so we can catch it $entity->getUserAction('sendEmail')->callback = function () { $args = func_get_args(); - $this->assertInstanceOf(User::class, $args[0]); - $this->assertStringContainsString('reset', $args[1]); - $this->assertIsString($args[2]); + static::assertInstanceOf(User::class, $args[0]); + static::assertStringContainsString('reset', $args[1]); + static::assertIsString($args[2]); }; - $this->assertIsString($pass = $entity->executeUserAction('resetPassword', 8)); - $this->assertTrue(PasswordField::assertInstanceOf($entity->getField('password'))->verifyPassword($entity, $pass)); + static::assertIsString($pass = $entity->executeUserAction('resetPassword', 8)); + static::assertTrue(PasswordField::assertInstanceOf($entity->getField('password'))->verifyPassword($entity, $pass)); $entity->reload(); - $this->assertTrue(PasswordField::assertInstanceOf($entity->getField('password'))->verifyPassword($entity, $pass)); + static::assertTrue(PasswordField::assertInstanceOf($entity->getField('password'))->verifyPassword($entity, $pass)); // check password strength - $this->assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['strength' => 3])); // bad - $this->assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312#~%dsQWRDGFfdfh', ['strength' => 3])); // good + static::assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['strength' => 3])); // bad + static::assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312#~%dsQWRDGFfdfh', ['strength' => 3])); // good // check password length - $this->assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['len' => 8])); // bad - $this->assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312#~%dsQWRDGFfdfh', ['len' => 8])); // good + static::assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['len' => 8])); // bad + static::assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312#~%dsQWRDGFfdfh', ['len' => 8])); // good // check password symbols - $this->assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['symbols' => 4])); // bad - $this->assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312##$$%%^^@@fdsfs', ['symbols' => 4])); // good + static::assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['symbols' => 4])); // bad + static::assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312##$$%%^^@@fdsfs', ['symbols' => 4])); // good // check password numbers - $this->assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['numbers' => 4])); // bad - $this->assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312634dgf#@$', ['numbers' => 4])); // good + static::assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['numbers' => 4])); // bad + static::assertNull($entity->executeUserAction('checkPasswordStrength', 'Qwerty312634dgf#@$', ['numbers' => 4])); // good // check password upper letters - $this->assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['upper' => 4])); // bad - $this->assertNull($entity->executeUserAction('checkPasswordStrength', 'QwERTYqAZ324', ['upper' => 4])); // good + static::assertIsString($entity->executeUserAction('checkPasswordStrength', 'qwerty', ['upper' => 4])); // bad + static::assertNull($entity->executeUserAction('checkPasswordStrength', 'QwERTYqAZ324', ['upper' => 4])); // good } } diff --git a/tests/Feature/SendEmailActionTest.php b/tests/Feature/SendEmailActionTest.php index b695e5c1..816f0b54 100644 --- a/tests/Feature/SendEmailActionTest.php +++ b/tests/Feature/SendEmailActionTest.php @@ -14,22 +14,18 @@ public function testBasic(): void $this->setupDefaultDb(); $m = $this->createUserModel(); - $this->assertTrue($m->hasUserAction('sendEmail')); + static::assertTrue($m->hasUserAction('sendEmail')); $entity = $m->load(1); // replace callback so we can catch it $entity->getUserAction('sendEmail')->callback = function () { $args = func_get_args(); - $this->assertInstanceOf(User::class, $args[0]); - $this->assertSame('Email subject', $args[1]); - $this->assertSame('Email body', $args[2]); + static::assertInstanceOf(User::class, $args[0]); + static::assertSame('Email subject', $args[1]); + static::assertSame('Email body', $args[2]); }; - $entity->executeUserAction( - 'sendEmail', - 'Email subject', - 'Email body' - ); + $entity->executeUserAction('sendEmail', 'Email subject', 'Email body'); } } diff --git a/tests/Feature/SignupTest.php b/tests/Feature/SignupTest.php index 7aab28cb..e3dc41e7 100644 --- a/tests/Feature/SignupTest.php +++ b/tests/Feature/SignupTest.php @@ -14,18 +14,15 @@ public function testBasic(): void $this->setupDefaultDb(); $m = $this->createUserModel(); - $this->assertTrue($m->hasUserAction('registerNewUser')); + static::assertTrue($m->hasUserAction('registerNewUser')); // as result it makes model loaded (as entity) with new user record - $m->createEntity()->executeUserAction( - 'registerNewUser', - [ - 'name' => 'New user', - 'email' => 'test', - 'password' => PasswordField::assertInstanceOf($m->getField('password'))->hashPassword('testpass'), - ] - ); + $m->createEntity()->executeUserAction('registerNewUser', [ + 'name' => 'New user', + 'email' => 'test', + 'password' => PasswordField::assertInstanceOf($m->getField('password'))->hashPassword('testpass'), + ]); - $this->assertSame(1, count((new $m($m->getPersistence()))->addCondition('email', 'test')->export())); + static::assertCount(1, (new $m($m->getPersistence()))->addCondition('email', 'test')->export()); } } diff --git a/tests/Feature/UniqueFieldValueTest.php b/tests/Feature/UniqueFieldValueTest.php index 8f53ceef..180cff2e 100644 --- a/tests/Feature/UniqueFieldValueTest.php +++ b/tests/Feature/UniqueFieldValueTest.php @@ -30,6 +30,7 @@ protected function createTestModel(): Model protected function init(): void { parent::init(); + $this->addField('name'); $this->setUnique('name'); } @@ -43,7 +44,7 @@ public function testBasic(): void $entity = $m->createEntity(); $entity->save(['name' => 'Test2']); - $this->assertSame(2, count($m->export())); + static::assertCount(2, $m->export()); $this->expectException(ValidationException::class);