From b96a3e8c7724c3be8e7c005928dfd1bb893c4d40 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Tue, 22 Apr 2025 23:07:49 +0300 Subject: [PATCH 1/9] Version 2.0.x support of Laravel Doctrine ORM ^3.1 and Laravel 12 - Support of Laravel 12 - Support of Laravel Doctrine ORM ^3.1 - Migrated to attributes instead of annotations - PHPUnit setup workbench for laravel imulation - GitHub actions setup php tests on github - PHPCS, PHPStan upgrade coding standards - Updated README.md --- .github/workflows/ci.yml | 39 --- .github/workflows/coding-standards.yml | 20 ++ .github/workflows/continuous-integration.yml | 61 +++++ .github/workflows/static-analysis.yml | 36 +++ .gitignore | 15 +- README.md | 56 ++-- composer.json | 146 +++++++---- docs/configurations.rst | 61 +++++ docs/core-concepts.rst | 8 - docs/index.rst | 4 +- docs/install.rst | 35 +++ docs/installation.rst | 27 -- docs/introduction.rst | 2 +- phpcs.xml.dist | 18 ++ phpstan.neon | 4 + phpunit.xml | 16 +- src/AclServiceProvider.php | 107 +++----- src/Contracts/BelongsToOrganisation.php | 7 +- src/Contracts/BelongsToOrganisations.php | 10 +- src/Contracts/HasPermissions.php | 17 +- src/Contracts/HasRoles.php | 10 +- src/Contracts/Organisation.php | 7 +- src/Contracts/Permission.php | 7 +- src/Contracts/Role.php | 7 +- src/Mappings/BelongsToOrganisation.php | 36 +-- src/Mappings/BelongsToOrganisations.php | 38 +-- src/Mappings/Builders/Builder.php | 11 +- src/Mappings/Builders/JsonArrayBuilder.php | 22 +- src/Mappings/Builders/ManyToManyBuilder.php | 34 +-- src/Mappings/Builders/ManyToOneBuilder.php | 30 +-- src/Mappings/ConfigAnnotation.php | 15 -- src/Mappings/ConfigAttribute.php | 12 + src/Mappings/HasPermissions.php | 37 ++- src/Mappings/HasRoles.php | 38 +-- .../RegisterMappedEventSubscribers.php | 24 +- src/Mappings/RelationAnnotation.php | 42 --- src/Mappings/RelationAttribute.php | 20 ++ .../BelongsToOrganisationSubscriber.php | 30 +-- .../BelongsToOrganisationsSubscriber.php | 30 +-- .../Subscribers/HasPermissionsSubscriber.php | 30 +-- .../Subscribers/HasRolesSubscriber.php | 30 +-- .../Subscribers/MappedEventSubscriber.php | 107 ++------ src/Organisations/BelongsToOrganisation.php | 53 ++-- src/Permissions/ConfigPermissionDriver.php | 20 +- src/Permissions/DoctrinePermissionDriver.php | 64 ++--- src/Permissions/HasPermissions.php | 56 ++-- src/{ => Permissions}/Manager.php | 19 +- src/Permissions/Permission.php | 48 ++-- src/Permissions/PermissionDriver.php | 7 +- src/Permissions/PermissionManager.php | 55 ++-- src/Roles/HasRoles.php | 57 ++--- testbench.yaml | 16 ++ tests/Integration/AclServiceProviderTest.php | 48 ++++ .../ConfigPermissionDriverTest.php | 44 ++++ .../DoctrinePermissionPersistenceTest.php | 103 ++++++++ tests/LaravelSetupTest.php | 24 ++ .../BelongsToOrganisationTest.php | 224 ++++------------ .../ConfigPermissionDriverTest.php | 24 +- .../DoctrinePermissionDriverTest.php | 126 ++++----- tests/Permissions/HasPermissionsTest.php | 240 +++++------------ tests/Permissions/PermissionManagerTest.php | 75 +++--- tests/Roles/HasRolesTest.php | 234 ++++------------- tests/TestCase.php | 30 +++ workbench/app/Entities/Organisation.php | 39 +++ workbench/app/Entities/Role.php | 57 +++++ workbench/app/Entities/User.php | 95 +++++++ .../app/Entities/UserJsonPermissions.php | 53 ++++ workbench/app/Entities/UserSingleOrg.php | 93 +++++++ .../Providers/WorkbenchServiceProvider.php | 24 ++ workbench/bootstrap/app.php | 19 ++ workbench/bootstrap/cache/.gitkeep | 0 workbench/bootstrap/cache/packages.php | 78 ++++++ workbench/bootstrap/cache/services.php | 242 ++++++++++++++++++ workbench/bootstrap/providers.php | 12 + workbench/config/acl.php | 40 +++ workbench/config/auth.php | 117 +++++++++ workbench/config/database.php | 175 +++++++++++++ workbench/config/doctrine.php | 215 ++++++++++++++++ workbench/config/migrations.php | 67 +++++ workbench/config/session.php | 217 ++++++++++++++++ workbench/config/view.php | 36 +++ workbench/database/README.md | 79 ++++++ workbench/database/factories/.gitkeep | 0 .../factories/OrganisationFactory.php | 10 + .../database/factories/PermissionFactory.php | 32 +++ workbench/database/factories/RoleFactory.php | 27 ++ workbench/database/factories/UserFactory.php | 24 ++ .../factories/UserJsonPermissions.php | 16 ++ .../factories/UserSingleOrgFactory.php | 16 ++ workbench/database/migrations/.gitkeep | 0 workbench/database/seeders/DatabaseSeeder.php | 23 ++ workbench/resources/views/.gitkeep | 0 workbench/routes/console.php | 8 + workbench/routes/web.php | 7 + workbench/storage/framework/views/.gitkeep | 0 95 files changed, 3219 insertions(+), 1475 deletions(-) delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/coding-standards.yml create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .github/workflows/static-analysis.yml create mode 100644 docs/configurations.rst create mode 100644 docs/install.rst delete mode 100644 docs/installation.rst create mode 100644 phpcs.xml.dist create mode 100644 phpstan.neon delete mode 100644 src/Mappings/ConfigAnnotation.php create mode 100644 src/Mappings/ConfigAttribute.php rename src/{ => Mappings}/RegisterMappedEventSubscribers.php (66%) delete mode 100644 src/Mappings/RelationAnnotation.php create mode 100644 src/Mappings/RelationAttribute.php rename src/{ => Permissions}/Manager.php (68%) create mode 100644 testbench.yaml create mode 100644 tests/Integration/AclServiceProviderTest.php create mode 100644 tests/Integration/ConfigPermissionDriverTest.php create mode 100644 tests/Integration/DoctrinePermissionPersistenceTest.php create mode 100644 tests/LaravelSetupTest.php create mode 100644 tests/TestCase.php create mode 100644 workbench/app/Entities/Organisation.php create mode 100644 workbench/app/Entities/Role.php create mode 100644 workbench/app/Entities/User.php create mode 100644 workbench/app/Entities/UserJsonPermissions.php create mode 100644 workbench/app/Entities/UserSingleOrg.php create mode 100644 workbench/app/Providers/WorkbenchServiceProvider.php create mode 100644 workbench/bootstrap/app.php create mode 100644 workbench/bootstrap/cache/.gitkeep create mode 100755 workbench/bootstrap/cache/packages.php create mode 100755 workbench/bootstrap/cache/services.php create mode 100644 workbench/bootstrap/providers.php create mode 100644 workbench/config/acl.php create mode 100644 workbench/config/auth.php create mode 100644 workbench/config/database.php create mode 100644 workbench/config/doctrine.php create mode 100644 workbench/config/migrations.php create mode 100644 workbench/config/session.php create mode 100644 workbench/config/view.php create mode 100644 workbench/database/README.md create mode 100644 workbench/database/factories/.gitkeep create mode 100644 workbench/database/factories/OrganisationFactory.php create mode 100644 workbench/database/factories/PermissionFactory.php create mode 100644 workbench/database/factories/RoleFactory.php create mode 100644 workbench/database/factories/UserFactory.php create mode 100644 workbench/database/factories/UserJsonPermissions.php create mode 100644 workbench/database/factories/UserSingleOrgFactory.php create mode 100644 workbench/database/migrations/.gitkeep create mode 100644 workbench/database/seeders/DatabaseSeeder.php create mode 100644 workbench/resources/views/.gitkeep create mode 100644 workbench/routes/console.php create mode 100644 workbench/routes/web.php create mode 100644 workbench/storage/framework/views/.gitkeep diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 3708651..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: CI -on: - push: - pull_request: - schedule: - - cron: '0 0 * * *' -jobs: - tests: - runs-on: 'ubuntu-latest' - name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - strategy: - matrix: - php: ['8.0', '8.1', '8.2'] - laravel: ['8', '9', '10'] - exclude: - - php: '8.2' - laravel: '8' - - php: '8.0' - laravel: '10' - steps: - - uses: actions/checkout@v3 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - ini-values: error_reporting=E_ALL - tools: phpunit, git - - - name: Install Composer dependencies - run: rm -f composer.lock - - - name: Install dependencies for Laravel ${{ matrix.laravel}} - run: composer require --no-progress --no-scripts --no-plugins illuminate/config ^${{ matrix.laravel }} illuminate/contracts ^${{ matrix.laravel }} illuminate/console ^${{ matrix.laravel }} -v - - - name: Update dependencies - run: composer update --no-interaction - - - name: PHPUnit - run: vendor/bin/phpunit diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml new file mode 100644 index 0000000..ff96e40 --- /dev/null +++ b/.github/workflows/coding-standards.yml @@ -0,0 +1,20 @@ +name: "Coding Standards" + +on: + pull_request: + branches: + - "*.x" + - "main" + push: + branches: + - "*.x" + - "main" + +jobs: + coding-standards: + name: "Coding Standards" + uses: "doctrine/.github/.github/workflows/coding-standards.yml@5.2.0" + with: + php-version: '8.2' + composer-options: '--prefer-dist --ignore-platform-req=php' + diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000..b5d5786 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,61 @@ +name: "Continuous Integration" + +on: + pull_request: + branches: + - "*.x" + - "main" + push: + branches: + - "*.x" + - "main" + +jobs: + phpunit: + name: "PHPUnit" + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php-version: + - "8.2" + - "8.3" + - "8.4" + dependencies: + - "highest" + - "lowest" + optional-dependencies: + - true + - false + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 2 + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + coverage: "pcov" + ini-values: "zend.assertions=1" + extensions: "pdo_mysql" + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v1" + with: + dependency-versions: "${{ matrix.dependencies }}" + composer-options: "--prefer-dist" + + - name: "Show Composer packages" + run: "composer show" + + - name: "Run PHPUnit" + run: "vendor/bin/phpunit --coverage-clover=coverage.xml" + + - name: "Upload coverage" + uses: "codecov/codecov-action@v5" + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000..1f0c400 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,36 @@ +name: "Static Analysis" + +on: + pull_request: + push: + +jobs: + static-analysis-phpstan: + name: "Static Analysis with PHPStan" + runs-on: "ubuntu-22.04" + + strategy: + matrix: + php-version: + - "8.2" + - "8.3" + - "8.4" + + steps: + - name: "Checkout code" + uses: "actions/checkout@v3" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "pdo_sqlite" + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependencies }}" + + - name: "Run a static analysis with phpstan/phpstan" + run: "vendor/bin/phpstan analyse src --level 1" diff --git a/.gitignore b/.gitignore index 6832801..493e917 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,21 @@ +/coverage /vendor composer.phar composer.lock .DS_Store -.php_cs.cache +.phpcs-cache +.phpunit.cache +.phpunit.result.cache + .idea +.vscode + +/tests/Stubs/storage/framework/views/* +!/tests/Stubs/storage/framework/views/.gitkeep +/tests/Stubs/storage/doctrine.generated.php laravel-doctrine-orm.iml +/workbench/bootstrap/cache/* +!/workbench/bootstrap/cache/.gitkeep +/workbench/storage/logs/* +/workbench/vendor \ No newline at end of file diff --git a/README.md b/README.md index b096e4f..1dc015b 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,44 @@ -# Laravel Doctrine ACL +

+ + +

- +Laravel Doctrine ACL +==================== -[![GitHub release](https://img.shields.io/github/release/laravel-doctrine/acl.svg?style=flat-square)](https://packagist.org/packages/laravel-doctrine/acl) -[![Github actions](https://github.com/laravel-doctrine/acl/workflows/CI/badge.svg?branch=1.x)](https://github.com/laravel-doctrine/acl/actions?query=workflow%3ACI+branch%3A1.x) -[![Packagist](https://img.shields.io/packagist/dm/laravel-doctrine/acl.svg?style=flat-square)](https://packagist.org/packages/laravel-doctrine/acl) -[![Packagist](https://img.shields.io/packagist/dt/laravel-doctrine/acl.svg?style=flat-square)](https://packagist.org/packages/laravel-doctrine/acl) +Laravel Doctrine ACL is a package that provides RBAC (Role-Based Access Control) functionality for Laravel applications using Doctrine. It allows you to manage roles, permissions, and organisations, and seamlessly integrates with Laravel's Authorization system. -*ACL functionality for Laravel powered by Doctrine* +[![Build Status](https://github.com/ScholarshipOwl/laravel-doctrine-acl/actions/workflows/php.yml/badge.svg)](https://github.com/ScholarshipOwl/laravel-doctrine-acl/actions) +[![Code Coverage](https://codecov.io/gh/laravel-doctrine/acl/graph/badge.svg?token=3CpQzDXOWX)](https://codecov.io/gh/laravel-doctrine/acl) +[![PHPStan](https://img.shields.io/badge/PHPStan-level%201-brightgreen.svg)](https://img.shields.io/badge/PHPStan-level%201-brightgreen.svg) +[![Documentation](https://readthedocs.org/projects/laravel-doctrine-acl-official/badge/?version=latest)](https://laravel-doctrine-acl-official.readthedocs.io/en/latest/) +[![Packagist Downloads](https://img.shields.io/packagist/dd/laravel-doctrine/acl)](https://packagist.org/packages/laravel-doctrine/acl) -* Roles -* Permissions -* Organisations -* Seamless integration with Laravel's Authorization system +Installation +------------ -## Versions +Via composer: -Version | Supported Laravel Versions -:---------|:---------- -~1.1.0 | 6.x -~1.2.0 | 7.x -~1.3.0 | 8.x -^1.4.0 | 6.x, 7.x, 8.x, 9.x, 10.x +```bash +composer require laravel-doctrine/acl +``` + +The ServiceProvider and Facades are autodiscovered. + +Publish the configuration: + +```bash +php artisan vendor:publish --tag="config" --provider="LaravelDoctrine\ACL\AclServiceProvider" +``` + +Documentation +------------- + +Full documentation at https://laravel-doctrine-acl.readthedocs.io/en/latest/index.html +or in the docs directory. + +Versions +-------- + +* Version 2 supports DBAL ^4.0, ORM ^3.0, and PHP 8.2. +* Version 1 supports Laravel 6 - 11, DBAL ^2.0, ORM ^2.0, and PHP ^5.5 - ^8.0. diff --git a/composer.json b/composer.json index fb4ca3e..09c2449 100644 --- a/composer.json +++ b/composer.json @@ -1,55 +1,97 @@ { - "name": "laravel-doctrine/acl", - "type": "library", - "description": "Doctrine ACL for Doctrine 2 and Laravel", - "license": "MIT", - "keywords": [ - "doctrine", - "laravel", - "orm", - "data mapper", - "database", - "acl", - "abilities", - "policies", - "permissions", - "roles", - "organisations" - ], - "authors": [ - { - "name": "Patrick Brouwers", - "email": "patrick@maatwebsite.nl" + "name": "laravel-doctrine/acl", + "type": "library", + "description": "Doctrine ACL for Doctrine 2 and Laravel", + "license": "MIT", + "keywords": [ + "doctrine", + "laravel", + "orm", + "data mapper", + "database", + "acl", + "abilities", + "policies", + "permissions", + "roles", + "organisations" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@maatwebsite.nl" + }, + { + "name": "Pavlo Zhytomyrskyi", + "email": "pavelz@scholarshipowl.com" + } + ], + "require": { + "php": "^8.2", + "illuminate/auth": "^11.0|^12.0", + "illuminate/config": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "laravel-doctrine/orm": "^3.1" + }, + "require-dev": { + "mockery/mockery": "^1.3.1", + "phpunit/phpunit": "^11.5", + "laravel/framework": "^11.0|^12.0", + "orchestra/testbench": "^10.2", + "laravel-doctrine/migrations": "^3.4", + "doctrine/coding-standard": "^12.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-deprecation-rules": "^2.0" + }, + "autoload": { + "psr-4": { + "LaravelDoctrine\\ACL\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests", + "Workbench\\App\\": "workbench/app/", + "Workbench\\Database\\Factories\\": "workbench/database/factories/", + "Workbench\\Database\\Seeders\\": "workbench/database/seeders/" + } + }, + "extra": { + "laravel": { + "providers": [ + "LaravelDoctrine\\ACL\\AclServiceProvider" + ] + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "scripts": { + "test": [ + "vendor/bin/parallel-lint src tests", + "vendor/bin/phpcs", + "vendor/bin/phpunit", + "vendor/bin/phpstan analyze src --level 1" + ], + "coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage", + "post-autoload-dump": [ + "@clear", + "@prepare" + ], + "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi", + "prepare": "@php vendor/bin/testbench package:discover --ansi", + "build": "@php vendor/bin/testbench workbench:build --ansi", + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@build", + "@php vendor/bin/testbench serve --ansi" + ], + "lint": [ + "@php vendor/bin/phpstan analyse --verbose --ansi" + ] } - ], - "require": { - "php": "^7.2.5|^8.0", - "illuminate/auth": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/config": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", - "laravel-doctrine/orm": "^1|^2.0", - "doctrine/annotations": "^1.10|^2.0" - }, - "require-dev": { - "mockery/mockery": "^1.3.1", - "phpunit/phpunit": "^8.5" - }, - "autoload": { - "psr-4": { - "LaravelDoctrine\\ACL\\": "src/" - } - }, - "autoload-dev": { - "classmap": [ - "tests" - ] - }, - "extra": { - "laravel": { - "providers": [ - "LaravelDoctrine\\ACL\\AclServiceProvider" - ] - } - } } diff --git a/docs/configurations.rst b/docs/configurations.rst new file mode 100644 index 0000000..87f44d5 --- /dev/null +++ b/docs/configurations.rst @@ -0,0 +1,61 @@ +=========== +Config File +=========== + +This document describes the options available in the `config/acl.php` configuration file for the Laravel Doctrine ACL package. + +Permissions +=========== + +.. code-block:: php + + 'permissions' => [ + 'driver' => 'config', + 'entity' => LaravelDoctrine\ACL\Permissions\Permission::class, + 'list' => [], + ], + +- **driver**: The permissions driver to use. Supported drivers: + + - `config`: Permissions are defined statically in the `list` array below. + - `doctrine`: Permissions are managed as Doctrine entities in the database. + +- **list**: (Only for `config` driver) An array of permission names to be recognized by the system. Example: `['edit.posts', 'delete.posts']` + + .. code-block:: php + + 'list' => [ + 'edit.posts', + 'delete.posts', + ], + +- **entity**: (Only for `doctrine` driver) The fully qualified class name of your Permission entity. Defaults to `LaravelDoctrine\ACL\Permissions\Permission`. + +Roles +===== + +.. code-block:: php + + 'roles' => [ + 'entity' => App\Entities\Role::class, + ], + +- **entity**: The fully qualified class name of your Role entity. By default, this is `App\Entities\Role`. You may customize this to point to your own Role entity class implementing `LaravelDoctrine\ACL\Contracts\Role`. + + +Organisations +============= + +.. code-block:: php + + 'organisations' => [ + 'entity' => App\Entities\Organisation::class, + ], + +- **entity**: The fully qualified class name of your Organisation entity. By default, this is `App\Entities\Organisation`. You may customize this to point to your own Organisation entity class implementing `LaravelDoctrine\ACL\Contracts\Organisation`. + + +.. role:: raw-html(raw) + :format: html + +.. include:: footer.rst diff --git a/docs/core-concepts.rst b/docs/core-concepts.rst index 2166764..22d565d 100644 --- a/docs/core-concepts.rst +++ b/docs/core-concepts.rst @@ -45,14 +45,6 @@ Read more about `organisations `_. * Set ``acl.organisations.entity`` in your config. * Users can belong to one or multiple organisations (implement ``BelongsToOrganisation`` or ``BelongsToOrganisations``). - -Advanced Configuration -====================== - -* Override default entities in the config (``acl.roles.entity``, ``acl.permissions.entity``, etc.). -* Choose permission storage driver (``acl.permissions.driver``: ``config`` or ``doctrine``). -* Use custom permission logic by implementing the relevant contracts. - .. role:: raw-html(raw) :format: html diff --git a/docs/index.rst b/docs/index.rst index 1b299e6..5a1f72b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,9 @@ For older versions use 1.x :caption: Table of Contents introduction - installation + install + configurations + usage core-concepts permissions diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 0000000..9b59670 --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,35 @@ +======= +Install +======= + +Installation of this module uses composer. For composer documentation, please +refer to `getcomposer.org `_ :: + +.. code-block:: bash + + composer require laravel-doctrine/acl + +To publish the config use: + +.. code-block:: bash + + php artisan vendor:publish --tag="config" --provider="LaravelDoctrine\ACL\AclServiceProvider" + +Thanks to Laravel auto package discovery, the ServiceProvider is +automatically registered. However they can still be manually registered if +required (see below). + +Manual Registration +=================== + +After updating composer, add the ServiceProvider to the providers +array in ``bootstrap/providers.php`` + +.. code-block:: php + + LaravelDoctrine\ACL\AclServiceProvider::class, + +.. role:: raw-html(raw) + :format: html + +.. include:: footer.rst diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index f313c43..0000000 --- a/docs/installation.rst +++ /dev/null @@ -1,27 +0,0 @@ -============ -Installation -============ - -Install via Composer: - -.. code-block:: bash - - composer require laravel-doctrine/acl - -Package should be automatically registered but in case no add it to `bootstrap/providers.php`: - -.. code-block:: php - - LaravelDoctrine\ACL\AclServiceProvider::class, - -Publish the configuration: - -.. code-block:: bash - - php artisan vendor:publish --tag="config" --provider="LaravelDoctrine\ACL\AclServiceProvider" - - -.. role:: raw-html(raw) - :format: html - -.. include:: footer.rst diff --git a/docs/introduction.rst b/docs/introduction.rst index ad441f4..c936f38 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -6,8 +6,8 @@ Laravel Doctrine ACL brings robust, flexible Access Control List (ACL) support t Laravel using Doctrine ORM. It enables you to manage permissions, roles, and organisations in a way that integrates seamlessly with Laravel’s native authorization system. -* Users can belong to organisations. * Users and roles can have permissions. +* Users can belong to organisations. * Flexible permission storage (config or database). diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..c0e526a --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,18 @@ + + + + + + + + + + + + + src + tests + + + + \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..d0d0224 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 0 + paths: + - src \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 0b5c4a4..0aedd31 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,17 +1,17 @@ - +> ./tests/ + + + ./src + + diff --git a/src/AclServiceProvider.php b/src/AclServiceProvider.php index 8d1aa9b..245a91e 100644 --- a/src/AclServiceProvider.php +++ b/src/AclServiceProvider.php @@ -1,107 +1,78 @@ isLumen()) { - $this->publishes([ - $this->getConfigPath() => config_path('acl.php'), - ], 'config'); - } - - $this->app->make(DoctrineManager::class)->onResolve(function () { - $this->definePermissions( - app(Gate::class), - app(PermissionManager::class) - ); - }); - } - /** * Register the service provider. - * @return void */ - public function register() + public function register(): void { $this->mergeConfig(); - if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { - AnnotationRegistry::registerUniqueLoader('class_exists'); - } - $manager = $this->app->make(DoctrineManager::class); - $manager->extendAll(RegisterMappedEventSubscribers::class); - - $this->registerPaths($manager); + $this->registerPaths(); + $this->registerGatePermissions(); + $this->registerDoctrineMappings(); } - /** - * @param Gate $gate - * @param PermissionManager $manager - */ - protected function definePermissions(Gate $gate, PermissionManager $manager) + protected function registerDoctrineMappings(): void { - foreach ($manager->getPermissionsWithDotNotation() as $permission) { - $gate->define($permission, function (HasPermissions $user) use ($permission) { - return $user->hasPermissionTo($permission); - }); - } + $manager = $this->app->make(DoctrineManager::class); + $manager->extendAll(RegisterMappedEventSubscribers::class); } - /** - * Merge config. - */ - protected function mergeConfig() + protected function registerPaths(): void { - $this->mergeConfigFrom( - $this->getConfigPath(), 'acl' - ); + $manager = $this->app->make(DoctrineManager::class); + $permissionManager = $this->app->make(PermissionManager::class); - if ($this->isLumen()) { - $this->app->configure('acl'); + if (! $permissionManager->useDefaultPermissionEntity()) { + return; } + + $manager->addPaths([ + __DIR__ . DIRECTORY_SEPARATOR . 'Permissions', + ]); } - /** - * @return string - */ - protected function getConfigPath() + protected function registerGatePermissions(): void { - return __DIR__ . '/../config/acl.php'; + $this->app->afterResolving(Gate::class, function (Gate $gate): void { + $manager = $this->app->make(PermissionManager::class); + + foreach ($manager->getPermissionsWithDotNotation() as $permission) { + $gate->define($permission, static function (HasPermissions $user) use ($permission) { + return $user->hasPermissionTo($permission); + }); + } + }); } /** - * @return bool + * Merge config. */ - protected function isLumen() + protected function mergeConfig(): void { - return Str::contains($this->app->version(), 'Lumen'); + $this->mergeConfigFrom( + $this->getConfigPath(), + 'acl', + ); } - /** - * @param $manager - */ - private function registerPaths($manager) + protected function getConfigPath(): string { - $permissionManager = $this->app->make(PermissionManager::class); - - if ($permissionManager->useDefaultPermissionEntity()) { - $manager->addPaths([ - __DIR__ . DIRECTORY_SEPARATOR . 'Permissions', - ]); - } + return __DIR__ . '/../config/acl.php'; } } diff --git a/src/Contracts/BelongsToOrganisation.php b/src/Contracts/BelongsToOrganisation.php index f3e3bc0..2be978b 100644 --- a/src/Contracts/BelongsToOrganisation.php +++ b/src/Contracts/BelongsToOrganisation.php @@ -1,11 +1,10 @@ targetEntity = $targetEntity; + $this->cascade = $cascade; + $this->fetch = $fetch; + $this->orphanRemoval = $orphanRemoval; + $this->indexBy = $indexBy; + } - /** - * @param Repository $config - * - * @return mixed - */ - public function getTargetEntity(Repository $config) + public function getTargetEntity(Repository $config): string|null { return $this->targetEntity ?: $config->get('acl.organisations.entity', 'Organisation'); } diff --git a/src/Mappings/BelongsToOrganisations.php b/src/Mappings/BelongsToOrganisations.php index 20e114e..0463ba9 100644 --- a/src/Mappings/BelongsToOrganisations.php +++ b/src/Mappings/BelongsToOrganisations.php @@ -1,27 +1,33 @@ targetEntity = $targetEntity; + $this->mappedBy = $mappedBy; + $this->cascade = $cascade; + $this->fetch = $fetch; + $this->orphanRemoval = $orphanRemoval; + $this->indexBy = $indexBy; + } - /** - * @param Repository $config - * - * @return mixed - */ - public function getTargetEntity(Repository $config) + public function getTargetEntity(Repository $config): string|null { return $this->targetEntity ?: $config->get('acl.organisations.entity', 'Organisation'); } diff --git a/src/Mappings/Builders/Builder.php b/src/Mappings/Builders/Builder.php index 14cc339..2baf593 100644 --- a/src/Mappings/Builders/Builder.php +++ b/src/Mappings/Builders/Builder.php @@ -1,17 +1,14 @@ $property->getName(), - 'type' => Type::JSON_ARRAY, - ] + 'type' => Types::JSON, + ], ); $builder->build(); diff --git a/src/Mappings/Builders/ManyToManyBuilder.php b/src/Mappings/Builders/ManyToManyBuilder.php index 8b134c7..bc0c223 100644 --- a/src/Mappings/Builders/ManyToManyBuilder.php +++ b/src/Mappings/Builders/ManyToManyBuilder.php @@ -1,51 +1,39 @@ config = $config; } - /** - * @param ClassMetadata $metadata - * @param ReflectionProperty $property - * @param ConfigAnnotation $annotation - */ - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAnnotation $annotation) + public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void { $builder = new ManyToManyAssociationBuilder( new ClassMetadataBuilder($metadata), [ 'fieldName' => $property->getName(), - 'targetEntity' => $annotation->getTargetEntity($this->config), + 'targetEntity' => $attribute->getTargetEntity($this->config), ], - ClassMetadata::MANY_TO_MANY + ClassMetadata::MANY_TO_MANY, ); - if (isset($annotation->inversedBy) && $annotation->inversedBy) { - $builder->inversedBy($annotation->inversedBy); + if (isset($attribute->inversedBy) && $attribute->inversedBy) { + $builder->inversedBy($attribute->inversedBy); } - if (isset($annotation->mappedBy) && $annotation->mappedBy) { - $builder->mappedBy($annotation->mappedBy); + if (isset($attribute->mappedBy) && $attribute->mappedBy) { + $builder->mappedBy($attribute->mappedBy); } $builder->build(); diff --git a/src/Mappings/Builders/ManyToOneBuilder.php b/src/Mappings/Builders/ManyToOneBuilder.php index 1154be2..c802e40 100644 --- a/src/Mappings/Builders/ManyToOneBuilder.php +++ b/src/Mappings/Builders/ManyToOneBuilder.php @@ -1,47 +1,35 @@ config = $config; } - /** - * @param ClassMetadata $metadata - * @param ReflectionProperty $property - * @param ConfigAnnotation $annotation - */ - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAnnotation $annotation) + public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void { $builder = new AssociationBuilder( new ClassMetadataBuilder($metadata), [ 'fieldName' => $property->getName(), - 'targetEntity' => $annotation->getTargetEntity($this->config), + 'targetEntity' => $attribute->getTargetEntity($this->config), ], - ClassMetadata::MANY_TO_ONE + ClassMetadata::MANY_TO_ONE, ); - if (isset($annotation->inversedBy) && $annotation->inversedBy) { - $builder->inversedBy($annotation->inversedBy); + if (isset($attribute->inversedBy) && $attribute->inversedBy) { + $builder->inversedBy($attribute->inversedBy); } $builder->build(); diff --git a/src/Mappings/ConfigAnnotation.php b/src/Mappings/ConfigAnnotation.php deleted file mode 100644 index 2c08c30..0000000 --- a/src/Mappings/ConfigAnnotation.php +++ /dev/null @@ -1,15 +0,0 @@ -targetEntity = $targetEntity; + $this->mappedBy = $mappedBy; + $this->cascade = $cascade; + $this->fetch = $fetch; + $this->orphanRemoval = $orphanRemoval; + $this->indexBy = $indexBy; + } + + public function getTargetEntity(Repository $config): string|null { // Config driver has no target entity if ($config->get('acl.permissions.driver', 'config') === 'config') { - return false; + return null; } return $this->targetEntity ?: $config->get('acl.permissions.entity', 'Permission'); diff --git a/src/Mappings/HasRoles.php b/src/Mappings/HasRoles.php index 1120cd8..2ab5018 100644 --- a/src/Mappings/HasRoles.php +++ b/src/Mappings/HasRoles.php @@ -1,27 +1,33 @@ targetEntity = $targetEntity; + $this->mappedBy = $mappedBy; + $this->cascade = $cascade; + $this->fetch = $fetch; + $this->orphanRemoval = $orphanRemoval; + $this->indexBy = $indexBy; + } - /** - * @param Repository $config - * - * @return mixed - */ - public function getTargetEntity(Repository $config) + public function getTargetEntity(Repository $config): string|null { return $this->targetEntity ?: $config->get('acl.roles.entity', 'Role'); } diff --git a/src/RegisterMappedEventSubscribers.php b/src/Mappings/RegisterMappedEventSubscribers.php similarity index 66% rename from src/RegisterMappedEventSubscribers.php rename to src/Mappings/RegisterMappedEventSubscribers.php index 5c76dc2..a5521c9 100644 --- a/src/RegisterMappedEventSubscribers.php +++ b/src/Mappings/RegisterMappedEventSubscribers.php @@ -1,6 +1,8 @@ subscribers as $subscriber) { $eventManager->addEventSubscriber( - new $subscriber( - $configuration->getMetadataDriverImpl()->getReader(), - app('config') - ) + new $subscriber(app('config')), ); } } diff --git a/src/Mappings/RelationAnnotation.php b/src/Mappings/RelationAnnotation.php deleted file mode 100644 index 6482399..0000000 --- a/src/Mappings/RelationAnnotation.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ - public $cascade; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch = 'LAZY'; - - /** - * @var bool - */ - public $orphanRemoval = false; - - /** - * @var string - */ - public $indexBy; -} diff --git a/src/Mappings/RelationAttribute.php b/src/Mappings/RelationAttribute.php new file mode 100644 index 0000000..cb58812 --- /dev/null +++ b/src/Mappings/RelationAttribute.php @@ -0,0 +1,20 @@ +getInstance($metadata) instanceof BelongsToOrganisationContract; + return BelongsToOrganisation::class; } - /** - * @return string - */ - public function getAnnotationClass() + protected function shouldBeMapped(ClassMetadata $metadata): bool { - return BelongsToOrganisation::class; + return $this->getInstance($metadata) instanceof BelongsToOrganisationContract; } - /** - * @param ConfigAnnotation $annotation - * - * @return string - */ - protected function getBuilder(ConfigAnnotation $annotation) + protected function getBuilder(ConfigAttribute $attribute): Builder { - return ManyToOneBuilder::class; + return new ManyToOneBuilder($this->config); } } diff --git a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php index aec2857..f40094c 100644 --- a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php +++ b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php @@ -1,40 +1,30 @@ getInstance($metadata) instanceof BelongsToOrganisationsContract; + return BelongsToOrganisations::class; } - /** - * @return string - */ - public function getAnnotationClass() + protected function shouldBeMapped(ClassMetadata $metadata): bool { - return BelongsToOrganisations::class; + return $this->getInstance($metadata) instanceof BelongsToOrganisationsContract; } - /** - * @param ConfigAnnotation $annotation - * - * @return string - */ - protected function getBuilder(ConfigAnnotation $annotation) + protected function getBuilder(ConfigAttribute $attribute): Builder { - return ManyToManyBuilder::class; + return new ManyToManyBuilder($this->config); } } diff --git a/src/Mappings/Subscribers/HasPermissionsSubscriber.php b/src/Mappings/Subscribers/HasPermissionsSubscriber.php index 5248105..ba987af 100644 --- a/src/Mappings/Subscribers/HasPermissionsSubscriber.php +++ b/src/Mappings/Subscribers/HasPermissionsSubscriber.php @@ -1,47 +1,37 @@ getInstance($metadata) instanceof HasPermissionsContract; } - /** - * @return string - */ - public function getAnnotationClass() + public function getAttributeClass(): string { return HasPermissions::class; } - /** - * @param ConfigAnnotation $annotation - * - * @return string - */ - protected function getBuilder(ConfigAnnotation $annotation) + protected function getBuilder(ConfigAttribute $attribute): Builder { // If there's a target entity, create pivot table - if ($annotation->getTargetEntity($this->config)) { - return ManyToManyBuilder::class; + if ($attribute->getTargetEntity($this->config)) { + return new ManyToManyBuilder($this->config); } // Else save the permissions inside the table as json - return JsonArrayBuilder::class; + return new JsonArrayBuilder($this->config); } } diff --git a/src/Mappings/Subscribers/HasRolesSubscriber.php b/src/Mappings/Subscribers/HasRolesSubscriber.php index f57da3a..4debd13 100644 --- a/src/Mappings/Subscribers/HasRolesSubscriber.php +++ b/src/Mappings/Subscribers/HasRolesSubscriber.php @@ -1,40 +1,30 @@ getInstance($metadata) instanceof HasRolesContract; + return HasRoles::class; } - /** - * @return string - */ - public function getAnnotationClass() + protected function shouldBeMapped(ClassMetadata $metadata): bool { - return HasRoles::class; + return $this->getInstance($metadata) instanceof HasRolesContract; } - /** - * @param ConfigAnnotation $annotation - * - * @return string - */ - protected function getBuilder(ConfigAnnotation $annotation) + protected function getBuilder(ConfigAttribute $attribute): Builder { - return ManyToManyBuilder::class; + return new ManyToManyBuilder($this->config); } } diff --git a/src/Mappings/Subscribers/MappedEventSubscriber.php b/src/Mappings/Subscribers/MappedEventSubscriber.php index 40ea1d1..0ab732b 100644 --- a/src/Mappings/Subscribers/MappedEventSubscriber.php +++ b/src/Mappings/Subscribers/MappedEventSubscriber.php @@ -1,130 +1,69 @@ */ + abstract public function getAttributeClass(): string; + + abstract protected function shouldBeMapped(ClassMetadata $metadata): bool; - /** - * @var Repository - */ - protected $config; + abstract protected function getBuilder(ConfigAttribute $attribute): Builder; - /** - * @param Reader|null $reader - * @param Repository $config - */ - public function __construct(?Reader $reader, Repository $config) + public function __construct(protected Repository $config) { - $this->reader = $reader; - $this->config = $config; } - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() + /** @return array */ + public function getSubscribedEvents(): array { return [ Events::loadClassMetadata, ]; } - /** - * @param LoadClassMetadataEventArgs $eventArgs - */ - public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void { $metadata = $eventArgs->getClassMetadata(); - if (! $this->reader) { + if (! $this->isInstantiable($metadata) || ! $this->shouldBeMapped($metadata)) { return; } - if ($this->isInstantiable($metadata) && $this->shouldBeMapped($metadata)) { - foreach ($metadata->getReflectionClass()->getProperties() as $property) { - if ($annotation = $this->findMapping($property)) { - $builder = $this->getBuilder($annotation); - $builder = new $builder($this->config); - $builder->build($metadata, $property, $annotation); - } + foreach ($metadata->getReflectionClass()->getProperties() as $property) { + foreach ($property->getAttributes($this->getAttributeClass()) as $refAttr) { + $attribute = $refAttr->newInstance(); + $builder = $this->getBuilder($attribute); + $builder->build($metadata, $property, $attribute); } } } - /** - * @param ClassMetadata $metadata - * - * @return bool - */ - abstract protected function shouldBeMapped(ClassMetadata $metadata); - - /** - * @return string - */ - abstract public function getAnnotationClass(); - - /** - * @param $property - * - * @return ConfigAnnotation - */ - protected function findMapping(ReflectionProperty $property) - { - return $this->reader->getPropertyAnnotation($property, $this->getAnnotationClass()); - } - - /** - * @param ClassMetadata $metadata - * - * @return object - */ - protected function getInstance(ClassMetadata $metadata) + protected function getInstance(ClassMetadata $metadata): object { $reflection = new ReflectionClass($metadata->getName()); - $instance = $reflection->newInstanceWithoutConstructor(); - return $instance; + return $reflection->newInstanceWithoutConstructor(); } - /** - * @param ConfigAnnotation $annotation - * - * @return string - */ - abstract protected function getBuilder(ConfigAnnotation $annotation); - - /** - * A MappedSuperClass or Abstract class cannot be instantiated. - * - * @param ClassMetadata $metadata - * - * @return bool - */ - protected function isInstantiable(ClassMetadata $metadata) + protected function isInstantiable(ClassMetadata $metadata): bool { if ($metadata->isMappedSuperclass) { return false; } - if (!$metadata->getReflectionClass() || $metadata->getReflectionClass()->isAbstract()) { - return false; - } - - return true; + return $metadata->getReflectionClass() && ! $metadata->getReflectionClass()->isAbstract(); } } diff --git a/src/Organisations/BelongsToOrganisation.php b/src/Organisations/BelongsToOrganisation.php index b19566e..1f61307 100644 --- a/src/Organisations/BelongsToOrganisation.php +++ b/src/Organisations/BelongsToOrganisation.php @@ -1,62 +1,57 @@ belongsToOrganisation($o); - if ($hasOrganisation && !$requireAll) { + if ($hasOrganisation && ! $requireAll) { return true; - } elseif (!$hasOrganisation && $requireAll) { + } + + if (! $hasOrganisation && $requireAll) { return false; } } return $requireAll; - } else { - if ($this instanceof BelongsToOrganisationContract) { - if (!is_null($this->getOrganisation()) && $this->getOrganisationName($org) === $this->getOrganisation()->getName()) { - return true; - } + } + + if ($this instanceof BelongsToOrganisationContract) { + if ($this->getOrganisation() && $this->getOrganisationName($org) === $this->getOrganisation()->getName()) { + return true; } - if ($this instanceof BelongsToOrganisationsContract) { - foreach ($this->getOrganisations() as $o) { - if ($this->getOrganisationName($org) === $o->getName()) { - return true; - } + } + + if ($this instanceof BelongsToOrganisationsContract) { + foreach ($this->getOrganisations() as $o) { + if ($this->getOrganisationName($org) === $o->getName()) { + return true; } } - - return false; } + + return false; } - /** - * @param OrganisationContract|string $org - * - * @return string - */ - protected function getOrganisationName($org) + protected function getOrganisationName(OrganisationContract|string $org): string { return $org instanceof OrganisationContract ? $org->getName() : $org; } diff --git a/src/Permissions/ConfigPermissionDriver.php b/src/Permissions/ConfigPermissionDriver.php index c0c0fdf..7f97090 100644 --- a/src/Permissions/ConfigPermissionDriver.php +++ b/src/Permissions/ConfigPermissionDriver.php @@ -1,5 +1,7 @@ repository = $repository; } - /** - * @return Collection - */ - public function getAllPermissions() + public function getAllPermissions(): Collection { return new Collection( - $this->repository->get('acl.permissions.list', []) + $this->repository->get('acl.permissions.list', []), ); } } diff --git a/src/Permissions/DoctrinePermissionDriver.php b/src/Permissions/DoctrinePermissionDriver.php index b663691..4672e4e 100644 --- a/src/Permissions/DoctrinePermissionDriver.php +++ b/src/Permissions/DoctrinePermissionDriver.php @@ -1,101 +1,79 @@ registry = $registry; - $this->config = $config; } - /** - * @return Collection - */ - public function getAllPermissions() + public function getAllPermissions(): Collection { if ($this->getRepository()) { try { $permissions = $this->getRepository()->findAll(); - } catch (TableNotFoundException $e) { + } catch (TableNotFoundException) { $permissions = []; } return new Collection( - $this->mapToArrayOfNames($permissions) + $this->mapToArrayOfNames($permissions), ); } - return new Collection; + return new Collection(); } /** - * @param $permissions + * @param array $permissions * - * @return array + * @return array */ - protected function mapToArrayOfNames($permissions) + protected function mapToArrayOfNames(array $permissions): array { - $permissions = array_map(function (Permission $permission) { + $permissions = array_map(static function (Permission $permission) { return $permission->getName(); }, $permissions); return $permissions; } - /** - * @return string - */ - protected function getEntityName() + protected function getEntityName(): string|null { return $this->config->get('acl.permissions.entity'); } - /** - * @return EntityManagerInterface|null - */ - protected function getEntityManager() + protected function getEntityManager(): EntityManagerInterface|null { return $this->registry->getManagerForClass( - $this->getEntityName() + $this->getEntityName(), ); } - /** - * @return EntityRepository - */ - protected function getRepository() + protected function getRepository(): EntityRepository|null { if ($this->getEntityManager()) { $metadata = $this->getEntityManager()->getClassMetadata($this->getEntityName()); return new EntityRepository( $this->getEntityManager(), - $metadata + $metadata, ); } + + return null; } } diff --git a/src/Permissions/HasPermissions.php b/src/Permissions/HasPermissions.php index d46ffce..e904c6c 100644 --- a/src/Permissions/HasPermissions.php +++ b/src/Permissions/HasPermissions.php @@ -1,61 +1,59 @@ hasPermissionTo($n); - if ($hasPermission && !$requireAll) { + if ($hasPermission && ! $requireAll) { return true; - } elseif (!$hasPermission && $requireAll) { + } + + if (! $hasPermission && $requireAll) { return false; } } return $requireAll; - } else { - if ($this instanceof HasPermissionsContract) { - foreach ($this->getPermissions() as $permission) { - if ($this->getPermissionName($permission) === $this->getPermissionName($name)) { - return true; - } + } + + if ($this instanceof HasPermissionsContract) { + foreach ($this->getPermissions() as $permission) { + if ($this->getPermissionName($permission) === $this->getPermissionName($name)) { + return true; } } + } - if ($this instanceof HasRolesHasRoles) { - foreach ($this->getRoles() as $role) { - if ($role instanceof HasPermissionsContract) { - if ($role->hasPermissionTo($name)) { - return true; - } - } + if ($this instanceof HasRolesHasRoles) { + foreach ($this->getRoles() as $role) { + if (! ($role instanceof HasPermissionsContract)) { + continue; } - } - return false; + if ($role->hasPermissionTo($name)) { + return true; + } + } } + + return false; } - /** - * @param PermissionContract|string $permission - * - * @return string - */ - protected function getPermissionName($permission) + protected function getPermissionName(PermissionContract|string $permission): string { return $permission instanceof PermissionContract ? $permission->getName() : $permission; } diff --git a/src/Manager.php b/src/Permissions/Manager.php similarity index 68% rename from src/Manager.php rename to src/Permissions/Manager.php index 95bbbdf..5620452 100644 --- a/src/Manager.php +++ b/src/Permissions/Manager.php @@ -1,23 +1,26 @@ $settings * * @throws DriverNotFound - * @return mixed */ - protected function createDriver($driver, array $settings = [], $resolve = true) + protected function createDriver(string $driver, array $settings = [], bool $resolve = true): mixed { $class = $this->getNamespace() . '\\' . Str::studly($driver) . $this->getClassSuffix(); @@ -26,10 +29,12 @@ protected function createDriver($driver, array $settings = [], $resolve = true) // drivers using their own customized driver creator Closure to create it. if (isset($this->customCreators[$driver])) { return $this->callCustomCreator($driver); - } elseif (class_exists($class)) { + } + + if (class_exists($class)) { return $this->container->make($class); } - throw new DriverNotFound("Driver [$driver] not supported."); + throw new DriverNotFound(sprintf('Driver [%s] not supported.', $driver)); } } diff --git a/src/Permissions/Permission.php b/src/Permissions/Permission.php index f1f4b9f..2809724 100644 --- a/src/Permissions/Permission.php +++ b/src/Permissions/Permission.php @@ -1,56 +1,42 @@ name = $name; } - /** - * @return mixed - */ - public function getId() + public function getId(): int { return $this->id; } - /** - * @return string - */ - public function getName() + public function getName(): string { return $this->name; } - /** - * @param mixed $name - */ - public function setName($name) + public function setName(string $name): self { $this->name = $name; + + return $this; } } diff --git a/src/Permissions/PermissionDriver.php b/src/Permissions/PermissionDriver.php index 3cd60db..5389f9c 100644 --- a/src/Permissions/PermissionDriver.php +++ b/src/Permissions/PermissionDriver.php @@ -1,13 +1,12 @@ */ + public function getPermissionsWithDotNotation(): array { $permissions = $this->driver()->getAllPermissions(); $list = $this->convertToDotArray( - $permissions->toArray() + $permissions->toArray(), ); return Arr::flatten($list); } /** - * @param array|string $permissions - * @param string $prepend + * @param array|string $permissions * - * @return array + * @return array */ - protected function convertToDotArray($permissions, $prepend = '') + protected function convertToDotArray(array|string $permissions, string $prepend = ''): array { $list = []; if (is_array($permissions)) { foreach ($permissions as $key => $permission) { - $list[] = $this->convertToDotArray($permission, (!is_numeric($key)) ? $prepend . $key . '.' : $prepend); + $list[] = $this->convertToDotArray($permission, ! is_numeric($key) ? $prepend . $key . '.' : $prepend); } } else { $list[] = $prepend . $permissions; @@ -47,48 +47,35 @@ protected function convertToDotArray($permissions, $prepend = '') /** * Get the default driver name. - * @return string */ - public function getDefaultDriver() + public function getDefaultDriver(): string { return $this->container->make('config')->get('acl.permissions.driver', 'config'); } - /** - * @return string - */ - public function getNamespace() + public function getNamespace(): string { return __NAMESPACE__; } - /** - * @return string - */ - public function getClassSuffix() + public function getClassSuffix(): string { return 'PermissionDriver'; } - /** - * @return bool - */ - public function useDefaultPermissionEntity() + public function useDefaultPermissionEntity(): bool { - if (!$this->needsDoctrine()) { + if (! $this->needsDoctrine()) { return false; } $entityFqn = $this->container->make('config')->get('acl.permissions.entity', ''); - $entityFqn = ltrim($entityFqn, "\\"); + $entityFqn = ltrim($entityFqn, '\\'); return $entityFqn === Permission::class; } - /** - * @return bool - */ - public function needsDoctrine() + public function needsDoctrine(): bool { return $this->getDefaultDriver() === 'doctrine'; } diff --git a/src/Roles/HasRoles.php b/src/Roles/HasRoles.php index b1e1101..e6e3e5b 100644 --- a/src/Roles/HasRoles.php +++ b/src/Roles/HasRoles.php @@ -1,73 +1,70 @@ hasRole($r); - if ($hasRole && !$requireAll) { + if ($hasRole && ! $requireAll) { return true; - } elseif (!$hasRole && $requireAll) { + } + + if (! $hasRole && $requireAll) { return false; } } return $requireAll; - } else { - foreach ($this->getRoles() as $ownedRole) { - if ($ownedRole === $role) { - return true; - } + } + + foreach ($this->getRoles() as $ownedRole) { + if ($ownedRole === $role) { + return true; } } return false; } - /** - * @param string|array $name - * @param bool $requireAll - * @return bool - */ - public function hasRoleByName($name, $requireAll = false) + public function hasRoleByName(string|array $name, bool $requireAll = false): bool { if (is_array($name)) { foreach ($name as $n) { $hasRole = $this->hasRoleByName($n); - if ($hasRole && !$requireAll) { + if ($hasRole && ! $requireAll) { return true; - } elseif (!$hasRole && $requireAll) { + } + + if (! $hasRole && $requireAll) { return false; } } return $requireAll; - } else { - foreach ($this->getRoles() as $ownedRole) { - if ($ownedRole->getName() === $name) { - return true; - } + } + + foreach ($this->getRoles() as $ownedRole) { + if ($ownedRole->getName() === $name) { + return true; } } return false; } - /** - * @return ArrayCollection|Role[] - */ - abstract public function getRoles(); + /** @return Collection|Role[] */ + abstract public function getRoles(): Collection|array; } diff --git a/testbench.yaml b/testbench.yaml new file mode 100644 index 0000000..2fedee6 --- /dev/null +++ b/testbench.yaml @@ -0,0 +1,16 @@ +laravel: ./workbench +workbench: + start: '/' + install: true + health: false + discovers: + web: false + api: false + commands: false + components: false + views: false + build: + - asset-publish + - create-sqlite-db + - db-wipe + sync: [] diff --git a/tests/Integration/AclServiceProviderTest.php b/tests/Integration/AclServiceProviderTest.php new file mode 100644 index 0000000..5d8722b --- /dev/null +++ b/tests/Integration/AclServiceProviderTest.php @@ -0,0 +1,48 @@ +createMock(PermissionManager::class); + $manager->method('getPermissionsWithDotNotation')->willReturn(['foo.bar', 'baz.qux']); + $this->app->instance(PermissionManager::class, $manager); + + // Get the Gate + $gate = $this->app->make(Gate::class); + + // Assert: Gate has the permissions defined + $this->assertTrue($gate->has('foo.bar')); + $this->assertTrue($gate->has('baz.qux')); + + $user = entity(User::class)->create(); + $user->setPermissions(['foo.bar']); + $this->actingAs($user); + + $this->assertTrue($gate->allows('foo.bar')); + $this->assertFalse($gate->allows('baz.quxdkdkd')); + } + + public function testNoPermissionsDefinedWhenManagerReturnsEmpty(): void + { + // $manager = $this->createMock(PermissionManager::class); + // $manager->method('getPermissionsWithDotNotation')->willReturn([]); + // $this->app->instance(PermissionManager::class, $manager); + + $gate = $this->app->make(Gate::class); + + $this->assertFalse($gate->has('any.permission')); + } +} diff --git a/tests/Integration/ConfigPermissionDriverTest.php b/tests/Integration/ConfigPermissionDriverTest.php new file mode 100644 index 0000000..62463c7 --- /dev/null +++ b/tests/Integration/ConfigPermissionDriverTest.php @@ -0,0 +1,44 @@ +set('acl.permissions.driver', 'config'); + } + + public function testPermissionsAreLoadedFromConfig(): void + { + $em = $this->app->make(EntityManager::class); + + $user = entity(UserJsonPermissions::class)->create(); + $user->setPermissions(['role.attach']); + + $em->persist($user); + $em->flush(); + + $this->actingAs($user); + + $gate = $this->app->make(Gate::class); + + $this->assertTrue($gate->allows('role.attach')); + $this->assertFalse($gate->allows('no_permission')); + } +} diff --git a/tests/Integration/DoctrinePermissionPersistenceTest.php b/tests/Integration/DoctrinePermissionPersistenceTest.php new file mode 100644 index 0000000..bc18e77 --- /dev/null +++ b/tests/Integration/DoctrinePermissionPersistenceTest.php @@ -0,0 +1,103 @@ +getRepository(User::class); + + // Create user, role, organisation, and permission + $user = entity(User::class)->create(); + $role = new Role('test-role'); + $organisation = new Organisation('test-org'); + $permission = new Permission('persisted.permission'); + $permission->setName('persisted.permission'); // Just for test coverage + $role->getPermissions()->add($permission); + $user->getRoles()->add($role); + $user->getOrganisations()->add($organisation); + $user->getPermissions()->add($permission); + + // Persist all entities + $em->persist($permission); + $em->persist($role); + $em->persist($organisation); + $em->persist($user); + $em->flush(); + $em->clear(); + + $reloaded = $repo->findOneBy(['email' => $user->email]); + assert($reloaded instanceof User); + $this->assertNotNull($reloaded); + $this->assertInstanceOf(User::class, $reloaded); + + // Permissions + $permissions = $reloaded->getPermissions(); + $this->assertInstanceOf(Collection::class, $permissions); + $this->assertTrue($permissions->exists(static fn ($key, $perm) => $perm->getName() === 'persisted.permission')); + + $reloadedPermission = $permissions->filter(static fn ($perm) => $perm->getName() === 'persisted.permission')->first(); + assert($reloadedPermission instanceof Permission); + $this->assertNotNull($reloadedPermission); + $this->assertInstanceOf(Permission::class, $reloadedPermission); + $this->assertIsNumeric($reloadedPermission->getId()); + + // Roles + $roles = $reloaded->getRoles(); + $this->assertInstanceOf(Collection::class, $roles); + $this->assertTrue($roles->exists(static fn ($key, $role) => $role->getName() === 'test-role')); + $reloadedRole = $roles->filter(static fn ($role) => $role->getName() === 'test-role')->first(); + $this->assertNotNull($reloadedRole); + $this->assertTrue($reloadedRole->getPermissions()->exists(static fn ($key, $perm) => $perm->getName() === 'persisted.permission')); + + // Organisations + $organisations = $reloaded->getOrganisations(); + $this->assertInstanceOf(Collection::class, $organisations); + $this->assertTrue($organisations->exists(static fn ($key, $org) => $org->getName() === 'test-org')); + } + + public function testUserSingleOrgPermissionsArrayPersistence(): void + { + $em = app(EntityManagerInterface::class); + assert($em instanceof EntityManagerInterface); + $repo = $em->getRepository(UserSingleOrg::class); + + // Create user and permission + $user = entity(UserSingleOrg::class)->create(); + $user->setPermissions(['array.permission']); + + // Persist entities + $em->persist($user); + $em->flush(); + $em->clear(); + + $reloaded = $repo->findOneBy(['email' => $user->email]); + assert($reloaded instanceof UserSingleOrg); + $this->assertNotNull($reloaded); + $this->assertInstanceOf(UserSingleOrg::class, $reloaded); + + // Permissions should be loaded as an array + $permissions = $reloaded->getPermissions(); + $this->assertIsArray($permissions); + $this->assertNotEmpty($permissions); + $this->assertEquals(['array.permission'], $permissions); + } +} diff --git a/tests/LaravelSetupTest.php b/tests/LaravelSetupTest.php new file mode 100644 index 0000000..69ca6ec --- /dev/null +++ b/tests/LaravelSetupTest.php @@ -0,0 +1,24 @@ +assertNotNull($this->app); + $this->assertInstanceOf(Application::class, $this->app); + $this->assertEquals('testing', $this->app->environment()); + + $user = entity(User::class)->create(); + + $this->actingAs($user); + } +} diff --git a/tests/Organisations/BelongsToOrganisationTest.php b/tests/Organisations/BelongsToOrganisationTest.php index 12b8dca..da9719d 100644 --- a/tests/Organisations/BelongsToOrganisationTest.php +++ b/tests/Organisations/BelongsToOrganisationTest.php @@ -1,207 +1,73 @@ user = new UserMock3; - $this->userSingle = new UserMock4; - $this->orgMock1 = new OrgMock('org1'); - $this->orgMock2 = new OrgMock('org2'); - $this->orgMock3 = new OrgMock('org3'); + parent::setUp(); + + $this->user = entity(User::class)->create(); + $this->userSingle = entity(UserSingleOrg::class)->create(); + $this->orgMock1 = entity(Organisation::class)->create(['name' => 'org1']); + $this->orgMock2 = entity(Organisation::class)->create(['name' => 'org2']); + $this->orgMock3 = entity(Organisation::class)->create(['name' => 'org3']); } - public function test_doesnt_have_organisation_when_no_organisations_assigned_single(): void + public function testBelongsToOrganisationVariousCases(): void { + // No organisations assigned (single org user) $this->assertFalse($this->userSingle->belongsToOrganisation($this->orgMock1)); - } - public function test_doesnt_have_organisation_when_no_organisations_assigned(): void - { - $this->assertFalse($this->user->belongsToOrganisation($this->orgMock1)); - } + // Assign an organisation to userSingle and check positive/negative cases + $this->userSingle->setOrganisation($this->orgMock1); + $this->assertTrue($this->userSingle->belongsToOrganisation($this->orgMock1)); + $this->assertTrue($this->userSingle->belongsToOrganisation('org1')); + $this->assertFalse($this->userSingle->belongsToOrganisation($this->orgMock2)); + $this->assertFalse($this->userSingle->belongsToOrganisation('org2')); - public function test_doesnt_have_role_by_name_when_no_roles_assigned(): void - { + // No organisations assigned (multi org user) + $this->assertFalse($this->user->belongsToOrganisation($this->orgMock1)); $this->assertFalse($this->user->belongsToOrganisation('org1')); - } - public function test_doesnt_have_organisation_when_when_other_orgiansation_assigned(): void - { - $this->user->setOrganisations([ - new OrgMock('org4'), - ]); + // Other organisation assigned + $this->user->setOrganisations([entity(Organisation::class)->create(['name' => 'org4'])]); $this->assertFalse($this->user->belongsToOrganisation($this->orgMock1)); - } - public function test_doesnt_have_any_organisations_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1 - ]); + // Organisation assigned, check any/all/none by object and name + $this->user->setOrganisations([$this->orgMock1]); $this->assertFalse($this->user->belongsToOrganisation([$this->orgMock2, $this->orgMock3])); - } - - public function test_doesnt_have_any_organisation_by_name_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1 - ]); $this->assertFalse($this->user->belongsToOrganisation(['org2', 'org3'])); - } + $this->assertTrue($this->user->belongsToOrganisation($this->orgMock1)); + $this->assertTrue($this->user->belongsToOrganisation('org1')); - public function test_doesnt_have_all_organisations_when_organisations_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2 - ]); + // Two organisations assigned + $this->user->setOrganisations([$this->orgMock1, $this->orgMock2]); $this->assertFalse($this->user->belongsToOrganisation([$this->orgMock1, $this->orgMock2, $this->orgMock3], true)); - } - - public function test_doesnt_have_all_organisations_by_name_when_organisations_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2 - ]); $this->assertFalse($this->user->belongsToOrganisation(['org1', 'org2', 'org3'], true)); - } - - public function test_has_organisation_when_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - ]); - $this->assertTrue($this->user->belongsToOrganisation($this->orgMock1)); - } - public function test_has_organisation_by_name_when_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - ]); - $this->assertTrue($this->user->belongsToOrganisation('org1')); - } - - public function test_has_any_organisation_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2, - $this->orgMock3 - ]); + // Three organisations assigned + $this->user->setOrganisations([$this->orgMock1, $this->orgMock2, $this->orgMock3]); $this->assertTrue($this->user->belongsToOrganisation([$this->orgMock1, $this->orgMock2])); - } - - public function test_has_all_organisations_when_organisations_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2, - $this->orgMock3 - ]); $this->assertTrue($this->user->belongsToOrganisation([$this->orgMock1, $this->orgMock2, $this->orgMock3], true)); - } - - public function test_has_any_organisation_by_name_when_organisation_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2, - $this->orgMock3 - ]); $this->assertTrue($this->user->belongsToOrganisation(['org1', 'org4'])); - } - - public function test_has_all_organisations_by_name_when_organisations_assigned(): void - { - $this->user->setOrganisations([ - $this->orgMock1, - $this->orgMock2, - $this->orgMock3 - ]); $this->assertTrue($this->user->belongsToOrganisation(['org1', 'org2', 'org3'], true)); } } - -class UserMock3 implements \LaravelDoctrine\ACL\Contracts\BelongsToOrganisations -{ - use \LaravelDoctrine\ACL\Organisations\BelongsToOrganisation; - - protected $organisations = []; - - public function getOrganisations() - { - return $this->organisations; - } - - public function setOrganisations($orgs): void - { - $this->organisations = $orgs; - } -} - -class UserMock4 implements \LaravelDoctrine\ACL\Contracts\BelongsToOrganisation -{ - use \LaravelDoctrine\ACL\Organisations\BelongsToOrganisation; - - protected $organisation; - - public function getOrganisation() - { - return $this->organisation; - } - - public function setOrganisation($org) - { - $this->organisation = $org; - } -} - -class OrgMock implements \LaravelDoctrine\ACL\Contracts\Organisation -{ - /** - * @var string - */ - protected $name; - - /** - * @param $name - */ - public function __construct($name) - { - $this->name = $name; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } -} diff --git a/tests/Permissions/ConfigPermissionDriverTest.php b/tests/Permissions/ConfigPermissionDriverTest.php index 258cd32..bfd5346 100644 --- a/tests/Permissions/ConfigPermissionDriverTest.php +++ b/tests/Permissions/ConfigPermissionDriverTest.php @@ -1,29 +1,31 @@ config = m::mock(Repository::class); $this->driver = new ConfigPermissionDriver($this->config); } - public function test_can_get_all_permissions(): void + public function testCanGetAllPermissions(): void { $this->config->shouldReceive('get')->with('acl.permissions.list', [])->once()->andReturn(['mocked']); diff --git a/tests/Permissions/DoctrinePermissionDriverTest.php b/tests/Permissions/DoctrinePermissionDriverTest.php index e0b59f6..3c44917 100644 --- a/tests/Permissions/DoctrinePermissionDriverTest.php +++ b/tests/Permissions/DoctrinePermissionDriverTest.php @@ -1,100 +1,102 @@ config = m::mock(Repository::class); - $this->registry = m::mock(ManagerRegistry::class); - $this->em = m::mock(EntityManagerInterface::class); - $this->driver = new DoctrinePermissionDriver($this->registry, $this->config); + $this->config = m::mock(Repository::class); + $this->registry = m::mock(ManagerRegistry::class); + $this->em = m::mock(EntityManagerInterface::class); + $this->unitOfWork = m::mock(UnitOfWork::class); + $this->entityPersister = m::mock(EntityPersister::class); + $this->driver = new DoctrinePermissionDriver($this->registry, $this->config); + } + + protected function tearDown(): void + { + m::close(); + } + + public function testNoEntityManagerFound(): void + { + $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); + + $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn(null); + + $collection = $this->driver->getAllPermissions(); + $this->assertInstanceOf(Collection::class, $collection); + $this->assertTrue($collection->isEmpty()); } - public function test_can_get_all_permissions(): void + public function testCanGetAllPermissions(): void { - $this->config->shouldReceive('get')->with('acl.permissions.entity')->once()->andReturn(Permission::class); + $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); - $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->once()->andReturn($this->em); + $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn($this->em); - $this->em->shouldReceive('getUnitOfWork')->once()->andReturn($this->em); - $this->em->shouldReceive('getEntityPersister')->with(Permission::class)->once()->andReturn($this->em); - $this->em->shouldReceive('loadAll')->once()->andReturn([ + $this->em->shouldReceive('getUnitOfWork')->andReturn($this->unitOfWork); + $this->unitOfWork->shouldReceive('getEntityPersister')->with(Permission::class)->andReturn($this->entityPersister); + $this->entityPersister->shouldReceive('loadAll')->andReturn([ new Permission('mocked'), ]); $meta = new ClassMetadata(Permission::class); - $meta->table = [ - 'name' => 'permissions', - ]; - $this->em->shouldReceive('getClassMetadata')->once()->andReturn($meta); + $meta->table = ['name' => 'permissions']; + $this->em->shouldReceive('getClassMetadata')->andReturn($meta); $permissions = $this->driver->getAllPermissions(); $this->assertInstanceOf(Collection::class, $permissions); $this->assertTrue($permissions->contains('mocked')); } - public function test_should_not_fail_when_table_does_not_exist(): void + public function testShouldNotFailWhenTableDoesNotExist(): void { - $this->config->shouldReceive('get')->with('acl.permissions.entity')->once()->andReturn(Permission::class); - - $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->once()->andReturn($this->em); - - $this->em->shouldReceive('getUnitOfWork')->once()->andReturn($this->em); - $this->em->shouldReceive('getEntityPersister')->with(Permission::class)->once()->andReturn($this->em); - + $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); + $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn($this->em); - if (class_exists(MysqliException::class)) { - $driver = new Driver(); - $exception = new MysqliException('Base table or view not found: 1146 Table \'permissions\' doesn\'t exist', 1146, 1146); - $tableNotFoundException = DBALException::driverExceptionDuringQuery($driver, $exception, 'SELECT t0.id AS id_1, t0.name AS name_2, t0.modules AS modules_3 FROM permissions t0'); + $this->em->shouldReceive('getUnitOfWork')->andReturn($this->unitOfWork); + $this->unitOfWork->shouldReceive('getEntityPersister')->with(Permission::class)->andReturn($this->entityPersister); - $this->em->shouldReceive('loadAll')->once()->andThrow($tableNotFoundException); - } else { - // DBAL 3 removed MysqliException - $this->em->shouldReceive('loadAll')->once()->andThrow(new \Doctrine\DBAL\Exception\TableNotFoundException( - new \Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionFailed('Table not found'), null) - ); - } + // DBAL 3 removed MysqliException + $this->entityPersister->shouldReceive('loadAll')->andThrow(new TableNotFoundException( + new ConnectionFailed('Table not found'), + null, + )); $meta = new ClassMetadata(Permission::class); - $meta->table = [ - 'name' => 'permissions', - ]; - $this->em->shouldReceive('getClassMetadata')->once()->andReturn($meta); + $meta->table = ['name' => 'permissions']; + $this->em->shouldReceive('getClassMetadata')->andReturn($meta); $permissions = $this->driver->getAllPermissions(); $this->assertInstanceOf(Collection::class, $permissions); diff --git a/tests/Permissions/HasPermissionsTest.php b/tests/Permissions/HasPermissionsTest.php index 51fefa5..1baf792 100644 --- a/tests/Permissions/HasPermissionsTest.php +++ b/tests/Permissions/HasPermissionsTest.php @@ -1,273 +1,169 @@ user = new UserMock; - $this->userWithRoles = new UserMockWithRoles; + parent::setUp(); + + $this->user = entity(User::class)->create(); } - public function test_doesnt_have_permission_when_no_roles_and_no_permissions(): void + public function testDoesntHavePermissionWhenNoRolesAndNoPermissions(): void { $this->assertFalse($this->user->hasPermissionTo('create.post')); } - public function test_doesnt_have_permission_when_no_roles_with_other_permissions(): void + public function testDoesntHavePermissionWhenNoRolesWithOtherPermissions(): void { - $this->user->setPermissions([ - 'create.page', - ]); + $this->user->setPermissions(['create.page']); $this->assertFalse($this->user->hasPermissionTo('create.post')); } - public function test_doesnt_have_permission_with_roles_and_other_permissions(): void + public function testDoesntHavePermissionWithRolesAndOtherPermissions(): void { - $this->userWithRoles->setRoles([ - new RoleMock, + $this->user->setRoles([ + entity(Role::class)->make(), ]); - $this->userWithRoles->setPermissions([ - 'create.page', - ]); + $this->user->setPermissions(['create.page']); - $this->assertFalse($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertFalse($this->user->hasPermissionTo('create.post')); } - public function test_doesnt_have_permission_with_roles_with_other_permissions_and_other_permissions(): void + public function testDoesntHavePermissionWithRolesWithOtherPermissionsAndOtherPermissions(): void { - $role = new RoleMock; - $role->setPermissions([ - 'create.page', - ]); + $role = entity(Role::class)->make(); + $role->setPermissions(['create.page']); - $this->userWithRoles->setRoles([ - $role, - ]); + $this->user->setRoles([$role]); - $this->userWithRoles->setPermissions([ - 'create.page', - ]); + $this->user->setPermissions(['create.page']); - $this->assertFalse($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertFalse($this->user->hasPermissionTo('create.post')); } - public function test_doesnt_have_permission_with_permission_but_no_other_permissions(): void + public function testDoesntHavePermissionWithPermissionButNoOtherPermissions(): void { - $this->user->setPermissions([ - 'create.page', - ]); + $this->user->setPermissions(['create.page']); $this->assertFalse($this->user->hasPermissionTo(['create.post', 'create.comment'])); } - public function test_doesnt_have_permission_with_permission_but_not_all_other_permissions(): void + public function testDoesntHavePermissionWithPermissionButNotAllOtherPermissions(): void { $this->user->setPermissions([ 'create.page', - 'create.post' + 'create.post', ]); $this->assertFalse($this->user->hasPermissionTo(['create.post', 'create.page', 'create.comment'], true)); } - public function test_user_has_permission_when_no_roles_but_has_the_permission(): void + public function testUserHasPermissionWhenNoRolesButHasThePermission(): void { - $this->user->setPermissions([ - 'create.post', - ]); + $this->user->setPermissions(['create.post']); $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_user_has_permission_when_with_roles_but_has_the_permission(): void + public function testUserHasPermissionWhenWithRolesButHasThePermission(): void { - $this->userWithRoles->setRoles([ - new RoleMock, + $this->user->setRoles([ + entity(Role::class)->make(), ]); - $this->userWithRoles->setPermissions([ - 'create.post', - ]); + $this->user->setPermissions(['create.post']); - $this->assertTrue($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_user_has_permission_when_role_has_permission(): void + public function testUserHasPermissionWhenRoleHasPermission(): void { - $role = new RoleMock; - $role->setPermissions([ - 'create.post', - ]); + $role = entity(Role::class)->make(); + $role->setPermissions(['create.post']); - $this->userWithRoles->setRoles([ - $role, - ]); + $this->user->setRoles([$role]); - $this->assertTrue($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_user_has_permission_when_one_role_has_permission(): void + public function testUserHasPermissionWhenOneRoleHasPermission(): void { - $role = new RoleMock; - $role->setPermissions([ - 'create.post', - ]); + $role = entity(Role::class)->make(); + $role->setPermissions(['create.post']); - $this->userWithRoles->setRoles([ - new RoleMock, + $this->user->setRoles([ + entity(Role::class)->make(), $role, ]); - $this->assertTrue($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_can_check_if_has_permission_with_permission_objects(): void + public function testCanCheckIfHasPermissionWithPermissionObjects(): void { $this->user->setPermissions([ - new \LaravelDoctrine\ACL\Permissions\Permission('create.post'), + new Permission('create.post'), ]); $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_user_has_permission_when_role_has_permission_with_object(): void + public function testUserHasPermissionWhenRoleHasPermissionWithObject(): void { - $role = new RoleMock; + $role = entity(Role::class)->create(); $role->setPermissions([ - new \LaravelDoctrine\ACL\Permissions\Permission('create.post'), + new Permission('create.post'), ]); - $this->userWithRoles->setRoles([ - $role, - ]); + $this->user->setRoles([$role]); - $this->assertTrue($this->userWithRoles->hasPermissionTo('create.post')); + $this->assertTrue($this->user->hasPermissionTo('create.post')); } - public function test_has_permission_with_permission_but_not_all_other_permissions(): void + public function testHasPermissionWithPermissionButNotAllOtherPermissions(): void { - $this->user->setPermissions([ - 'create.page', - ]); + $this->user->setPermissions(['create.page']); $this->assertTrue($this->user->hasPermissionTo(['create.post', 'create.page', 'create.comment'])); } - public function test_has_permission_and_all_permissions() + public function testHasPermissionAndAllPermissions(): void { $this->user->setPermissions([ 'create.page', - 'create.post' + 'create.post', ]); $this->assertTrue($this->user->hasPermissionTo(['create.post', 'create.page'], true)); } - public function test_user_has_permission_by_object() + public function testUserHasPermissionByObject(): void { $this->user->setPermissions(['test.test']); - $this->assertTrue($this->user->hasPermissionTo(new \LaravelDoctrine\ACL\Permissions\Permission('test.test'))); - } - - public function test_user_has_object_permission_by_object(): void - { - $this->user->setPermissions([new \LaravelDoctrine\ACL\Permissions\Permission('test.test')]); - - $this->assertTrue($this->user->hasPermissionTo(new \LaravelDoctrine\ACL\Permissions\Permission('test.test'))); - } -} - -class UserMock implements HasPermissionsContract -{ - use HasPermissions; - - protected $permissions = []; - - public function getPermissions() - { - return $this->permissions; + $this->assertTrue($this->user->hasPermissionTo(new Permission('test.test'))); } - public function setPermissions($permissions) + public function testUserHasObjectPermissionByObject(): void { - $this->permissions = $permissions; - } -} - -class UserMockWithRoles implements HasPermissionsContract, HasRolesContract -{ - use HasPermissions, HasRoles; - - protected $permissions = []; - - protected $roles = []; - - public function getPermissions() - { - return $this->permissions; - } + $this->user->setPermissions([new Permission('test.test')]); - public function setPermissions($permissions) - { - $this->permissions = $permissions; - } - - public function getRoles() - { - return $this->roles; - } - - /** - * @param array $roles - */ - public function setRoles($roles) - { - $this->roles = $roles; - } -} - -class RoleMock implements Role -{ - use HasPermissions; - - protected $permissions = []; - - protected $roles = []; - - public function getPermissions() - { - return $this->permissions; - } - - public function setPermissions($permissions) - { - $this->permissions = $permissions; - } - - /** - * @return string - */ - public function getName() - { - return 'Admin'; + $this->assertTrue($this->user->hasPermissionTo(new Permission('test.test'))); } } diff --git a/tests/Permissions/PermissionManagerTest.php b/tests/Permissions/PermissionManagerTest.php index 627e1da..c9b3658 100644 --- a/tests/Permissions/PermissionManagerTest.php +++ b/tests/Permissions/PermissionManagerTest.php @@ -1,28 +1,26 @@ driver->shouldReceive('getAllPermissions')->once()->andReturn(new Collection([ - 'permission1', 'permissionKey2' => [ 'permissionValue1', - 'permissionValue2' + 'permissionValue2', ], 'permissionKey3' => [ 'permissionKey4' => [ 'permissionValue3', - 'permissionValue4' - ] - ] + 'permissionValue4', + ], + ], ])); - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); $config->shouldReceive('get')->with('acl.permissions.driver', 'config')->andReturn('config'); $this->assertEquals([ - 'permission1', 'permissionKey2.permissionValue1', 'permissionKey2.permissionValue2', 'permissionKey3.permissionKey4.permissionValue3', - 'permissionKey3.permissionKey4.permissionValue4' + 'permissionKey3.permissionKey4.permissionValue4', ], $this->manager->getPermissionsWithDotNotation()); } - public function test_when_should_use_default_permission_entity(): void + public function testWhenShouldUseDefaultPermissionEntity(): void { - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); $config->shouldReceive('get')->with('acl.permissions.driver', 'config')->andReturn('doctrine'); // Tests for leading slashes in case someone is providing a manually written FQN - $config->shouldReceive('get')->with('acl.permissions.entity', null)->andReturn("\\" . Permission::class); + $config->shouldReceive('get')->with('acl.permissions.entity', null)->andReturn('\\' . Permission::class); $this->assertTrue($this->manager->useDefaultPermissionEntity()); } - public function test_when_should_not_use_default_permission_entity_because_driver_is_not_doctrine(): void + public function testWhenShouldNotUseDefaultPermissionEntityBecauseDriverIsNotDoctrine(): void { - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); @@ -93,9 +94,9 @@ public function test_when_should_not_use_default_permission_entity_because_drive $this->assertFalse($this->manager->useDefaultPermissionEntity()); } - public function test_when_should_not_use_default_permission_entity_because_entity_is_different(): void + public function testWhenShouldNotUseDefaultPermissionEntityBecauseEntityIsDifferent(): void { - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); @@ -105,9 +106,9 @@ public function test_when_should_not_use_default_permission_entity_because_entit $this->assertFalse($this->manager->useDefaultPermissionEntity()); } - public function test_needs_doctrine(): void + public function testNeedsDoctrine(): void { - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); @@ -116,9 +117,9 @@ public function test_needs_doctrine(): void $this->assertTrue($this->manager->needsDoctrine()); } - public function test_does_not_need_doctrine(): void + public function testDoesNotNeedDoctrine(): void { - $config = m::mock(Config::class); + $config = m::mock(Repository::class); $this->container->shouldReceive('make')->with('config')->andReturn($config); @@ -126,4 +127,12 @@ public function test_does_not_need_doctrine(): void $this->assertFalse($this->manager->needsDoctrine()); } + + public function testThrowsDriverNotFoundException(): void + { + $this->expectException(DriverNotFound::class); + $manager = new PermissionManager($this->container); + // Do not extend with any driver, so the requested driver does not exist + $manager->driver('nonexistent'); + } } diff --git a/tests/Roles/HasRolesTest.php b/tests/Roles/HasRolesTest.php index c9c8e50..bb733a7 100644 --- a/tests/Roles/HasRolesTest.php +++ b/tests/Roles/HasRolesTest.php @@ -1,211 +1,89 @@ user = new UserMock2; - $this->admin = new RoleMock2('admin'); - $this->extraRole1 = new RoleMock2('extraRole1'); - $this->extraRole2 = new RoleMock2('extraRole2'); - } +use function entity; - public function test_doesnt_have_role_when_no_roles_assigned(): void +class HasRolesTest extends TestCase +{ + protected User|null $user; + protected Role|null $admin; + protected Role|null $extraRole1; + protected Role|null $extraRole2; + + public function setUp(): void { - $this->assertFalse($this->user->hasRole($this->admin)); + parent::setUp(); + + $this->user = entity(User::class)->create(); + $this->admin = entity(Role::class, 'admin')->create(); + $this->extraRole1 = entity(Role::class)->create(['name' => 'extraRole1']); + $this->extraRole2 = entity(Role::class)->create(['name' => 'extraRole2']); } - public function test_doesnt_have_role_by_name_when_no_roles_assigned(): void + public function testRolesAndRoleNamesCombinations(): void { + // Initial state: user has no roles + $this->assertFalse($this->user->hasRole($this->admin)); $this->assertFalse($this->user->hasRoleByName('admin')); - } - public function test_doesnt_have_role_when_when_other_role_assigned(): void - { - $this->user->setRoles([ - new RoleMock2('user'), - ]); + // User has a different role (not admin) + $this->user->setRoles([entity(Role::class, 'user')->create()]); $this->assertFalse($this->user->hasRole($this->admin)); - } + $this->assertFalse($this->user->hasRoleByName('admin')); - public function test_doesnt_have_any_role_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin - ]); + // User has only admin + $this->user->setRoles([$this->admin]); $this->assertFalse($this->user->hasRole([$this->extraRole1, $this->extraRole2])); - } - - public function test_doesnt_have_any_role_by_name_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin - ]); $this->assertFalse($this->user->hasRoleByName(['extraRole1', 'extraRole2'])); - } - - public function test_doesnt_have_all_roles_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin, - $this->extraRole1 - ]); - $this->assertFalse($this->user->hasRole([$this->admin, $this->extraRole1, $this->extraRole2], true)); - } - - public function test_doesnt_have_all_roles_by_name_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin, - $this->extraRole1 - ]); - $this->assertFalse($this->user->hasRoleByName(['admin', 'extraRole1', 'extraRole2'], true)); - } - - public function test_doesnt_have_role_by_name_when_when_other_role_assigned(): void - { - $this->user->setRoles([ - new RoleMock2('user'), - ]); - $this->assertFalse($this->user->hasRoleByName('admin')); - } - - public function test_has_role_when_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin, - ]); $this->assertTrue($this->user->hasRole($this->admin)); - } - - public function test_has_role_by_name_when_when_role_assigned(): void - { - $this->user->setRoles([ - $this->admin, - ]); $this->assertTrue($this->user->hasRoleByName('admin')); - } - public function test_has_any_role_when_role_assigned(): void - { + // User has admin and extraRole1 $this->user->setRoles([ $this->admin, $this->extraRole1, - $this->extraRole2 ]); - $this->assertTrue($this->user->hasRole([$this->admin, $this->extraRole1])); - } - - public function test_has_all_role_when_role_assigned(): void - { - $this->user->setRoles([ + $this->assertFalse($this->user->hasRole([ $this->admin, $this->extraRole1, - $this->extraRole2 - ]); - $this->assertTrue($this->user->hasRole([$this->admin, $this->extraRole1, $this->extraRole2], true)); - } - - public function test_has_any_role_by_name_when_role_assigned(): void - { + $this->extraRole2, + ], true)); + $this->assertFalse($this->user->hasRoleByName([ + 'admin', + 'extraRole1', + 'extraRole2', + ], true)); + + // User has admin, extraRole1, extraRole2 $this->user->setRoles([ $this->admin, $this->extraRole1, - $this->extraRole2 + $this->extraRole2, ]); - $this->assertTrue($this->user->hasRoleByName(['admin', 'extraRole1'])); - } - - public function test_has_all_role_by_name_when_role_assigned(): void - { - $this->user->setRoles([ + $this->assertTrue($this->user->hasRole([ $this->admin, $this->extraRole1, - $this->extraRole2 - ]); - $this->assertTrue($this->user->hasRoleByName(['admin', 'extraRole1', 'extraRole2'], true)); - } -} - -class UserMock2 implements HasRolesContract -{ - use HasRoles; - - protected $roles = []; - - public function getRoles() - { - return $this->roles; - } - - /** - * @param array $roles - */ - public function setRoles($roles) - { - $this->roles = $roles; - } -} - -class RoleMock2 implements Role -{ - use HasPermissions; - - protected $permissions = []; - - protected $roles = []; - - /** - * @var string - */ - protected $name; - - /** - * @param $name - */ - public function __construct($name) - { - $this->name = $name; - } - - public function getPermissions() - { - return $this->permissions; - } - - public function setPermissions($permissions) - { - $this->permissions = $permissions; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; + ])); + $this->assertTrue($this->user->hasRole([ + $this->admin, + $this->extraRole1, + $this->extraRole2, + ], true)); + $this->assertTrue($this->user->hasRoleByName([ + 'admin', + 'extraRole1', + ])); + $this->assertTrue($this->user->hasRoleByName([ + 'admin', + 'extraRole1', + 'extraRole2', + ], true)); } } diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..a3a955f --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,30 @@ +artisan('doctrine:schema:create'); + } + + public function tearDown(): void + { + parent::tearDown(); + } + + protected function em(): EntityManager + { + return $this->app->make(EntityManager::class); + } +} diff --git a/workbench/app/Entities/Organisation.php b/workbench/app/Entities/Organisation.php new file mode 100644 index 0000000..a6b471f --- /dev/null +++ b/workbench/app/Entities/Organisation.php @@ -0,0 +1,39 @@ +name = $name; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + return $this; + } +} diff --git a/workbench/app/Entities/Role.php b/workbench/app/Entities/Role.php new file mode 100644 index 0000000..1f4705d --- /dev/null +++ b/workbench/app/Entities/Role.php @@ -0,0 +1,57 @@ +name = $name; + $this->permissions = new ArrayCollection(); + } + + public function getName(): string + { + return $this->name; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getPermissions(): Collection + { + return $this->permissions; + } + + public function setPermissions($permissions): void + { + $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; + } +} diff --git a/workbench/app/Entities/User.php b/workbench/app/Entities/User.php new file mode 100644 index 0000000..fd5676b --- /dev/null +++ b/workbench/app/Entities/User.php @@ -0,0 +1,95 @@ +roles = new ArrayCollection(); + $this->permissions = new ArrayCollection(); + $this->organisations = new ArrayCollection(); + } + + public function getRoles(): Collection + { + return $this->roles; + } + + public function setRoles($roles): void + { + $this->roles = is_array($roles) ? new ArrayCollection($roles) : $roles; + } + + public function getPermissions(): Collection + { + return $this->permissions; + } + + public function setPermissions($permissions): void + { + $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; + } + + public function getOrganisations(): Collection + { + return $this->organisations; + } + + public function setOrganisations($organisations): void + { + $this->organisations = is_array($organisations) ? new ArrayCollection($organisations) : $organisations; + } +} diff --git a/workbench/app/Entities/UserJsonPermissions.php b/workbench/app/Entities/UserJsonPermissions.php new file mode 100644 index 0000000..06f339c --- /dev/null +++ b/workbench/app/Entities/UserJsonPermissions.php @@ -0,0 +1,53 @@ +permissions; + } + + public function setPermissions(array $permissions): self + { + $this->permissions = $permissions; + return $this; + } +} diff --git a/workbench/app/Entities/UserSingleOrg.php b/workbench/app/Entities/UserSingleOrg.php new file mode 100644 index 0000000..b5dba13 --- /dev/null +++ b/workbench/app/Entities/UserSingleOrg.php @@ -0,0 +1,93 @@ +roles = new ArrayCollection(); + } + + public function getRoles(): Collection + { + return $this->roles; + } + + public function setRoles($roles): void + { + $this->roles = is_array($roles) ? new ArrayCollection($roles) : $roles; + } + + public function getPermissions(): array + { + return $this->permissions; + } + + public function setPermissions(array $permissions): void + { + $this->permissions = $permissions; + } + + public function getOrganisation(): ?Organisation + { + return $this->organisation; + } + + public function setOrganisation($organisation): void + { + $this->organisation = $organisation; + } +} diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php new file mode 100644 index 0000000..e8cec9c --- /dev/null +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -0,0 +1,24 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + ) + ->withMiddleware(function (Middleware $middleware) { + // + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/workbench/bootstrap/cache/.gitkeep b/workbench/bootstrap/cache/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/workbench/bootstrap/cache/packages.php b/workbench/bootstrap/cache/packages.php new file mode 100755 index 0000000..ed5c8ab --- /dev/null +++ b/workbench/bootstrap/cache/packages.php @@ -0,0 +1,78 @@ + + array ( + 'providers' => + array ( + 0 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', + ), + ), + 'laravel-doctrine/orm' => + array ( + 'aliases' => + array ( + 'Doctrine' => 'LaravelDoctrine\\ORM\\Facades\\Doctrine', + 'Registry' => 'LaravelDoctrine\\ORM\\Facades\\Registry', + 'EntityManager' => 'LaravelDoctrine\\ORM\\Facades\\EntityManager', + ), + 'providers' => + array ( + 0 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', + ), + ), + 'laravel/pail' => + array ( + 'providers' => + array ( + 0 => 'Laravel\\Pail\\PailServiceProvider', + ), + ), + 'laravel/tinker' => + array ( + 'providers' => + array ( + 0 => 'Laravel\\Tinker\\TinkerServiceProvider', + ), + ), + 'nesbot/carbon' => + array ( + 'providers' => + array ( + 0 => 'Carbon\\Laravel\\ServiceProvider', + ), + ), + 'nunomaduro/collision' => + array ( + 'providers' => + array ( + 0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + ), + ), + 'nunomaduro/termwind' => + array ( + 'providers' => + array ( + 0 => 'Termwind\\Laravel\\TermwindServiceProvider', + ), + ), + 'orchestra/canvas' => + array ( + 'providers' => + array ( + 0 => 'Orchestra\\Canvas\\LaravelServiceProvider', + ), + ), + 'orchestra/canvas-core' => + array ( + 'providers' => + array ( + 0 => 'Orchestra\\Canvas\\Core\\LaravelServiceProvider', + ), + ), + 'sowl/laravel-doctrine-acl' => + array ( + 'providers' => + array ( + 0 => 'LaravelDoctrine\\ACL\\AclServiceProvider', + ), + ), +); \ No newline at end of file diff --git a/workbench/bootstrap/cache/services.php b/workbench/bootstrap/cache/services.php new file mode 100755 index 0000000..5576370 --- /dev/null +++ b/workbench/bootstrap/cache/services.php @@ -0,0 +1,242 @@ + + array ( + 0 => 'Illuminate\\Auth\\AuthServiceProvider', + 1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 2 => 'Illuminate\\Bus\\BusServiceProvider', + 3 => 'Illuminate\\Cache\\CacheServiceProvider', + 4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 5 => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', + 6 => 'Illuminate\\Cookie\\CookieServiceProvider', + 7 => 'Illuminate\\Database\\DatabaseServiceProvider', + 8 => 'Illuminate\\Encryption\\EncryptionServiceProvider', + 9 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', + 10 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', + 11 => 'Illuminate\\Hashing\\HashServiceProvider', + 12 => 'Illuminate\\Mail\\MailServiceProvider', + 13 => 'Illuminate\\Notifications\\NotificationServiceProvider', + 14 => 'Illuminate\\Pagination\\PaginationServiceProvider', + 15 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 16 => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 17 => 'Illuminate\\Queue\\QueueServiceProvider', + 18 => 'Illuminate\\Redis\\RedisServiceProvider', + 19 => 'Illuminate\\Session\\SessionServiceProvider', + 20 => 'Illuminate\\Translation\\TranslationServiceProvider', + 21 => 'Illuminate\\Validation\\ValidationServiceProvider', + 22 => 'Illuminate\\View\\ViewServiceProvider', + 23 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', + 24 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', + 25 => 'LaravelDoctrine\\ACL\\AclServiceProvider', + ), + 'eager' => + array ( + 0 => 'Illuminate\\Auth\\AuthServiceProvider', + 1 => 'Illuminate\\Cookie\\CookieServiceProvider', + 2 => 'Illuminate\\Database\\DatabaseServiceProvider', + 3 => 'Illuminate\\Encryption\\EncryptionServiceProvider', + 4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', + 5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', + 6 => 'Illuminate\\Notifications\\NotificationServiceProvider', + 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', + 8 => 'Illuminate\\Session\\SessionServiceProvider', + 9 => 'Illuminate\\View\\ViewServiceProvider', + 10 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', + 11 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', + 12 => 'LaravelDoctrine\\ACL\\AclServiceProvider', + ), + 'deferred' => + array ( + 'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', + 'cache' => 'Illuminate\\Cache\\CacheServiceProvider', + 'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider', + 'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider', + 'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider', + 'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider', + 'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Concurrency\\Console\\InvokeSerializedClosureCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\PruneStaleTagsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleInterruptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StorageUnlinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ApiInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\BroadcastingInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ChannelListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ClassMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnumMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\InterfaceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\JobMiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\LangPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\TraitMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Migrations\\Migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Concurrency\\ConcurrencyManager' => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', + 'hash' => 'Illuminate\\Hashing\\HashServiceProvider', + 'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider', + 'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider', + 'mailer' => 'Illuminate\\Mail\\MailServiceProvider', + 'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider', + 'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 'pipeline' => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 'queue' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider', + 'redis' => 'Illuminate\\Redis\\RedisServiceProvider', + 'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider', + 'translator' => 'Illuminate\\Translation\\TranslationServiceProvider', + 'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider', + 'validator' => 'Illuminate\\Validation\\ValidationServiceProvider', + 'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider', + 'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => 'Illuminate\\Validation\\ValidationServiceProvider', + ), + 'when' => + array ( + 'Illuminate\\Broadcasting\\BroadcastServiceProvider' => + array ( + ), + 'Illuminate\\Bus\\BusServiceProvider' => + array ( + ), + 'Illuminate\\Cache\\CacheServiceProvider' => + array ( + ), + 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' => + array ( + ), + 'Illuminate\\Concurrency\\ConcurrencyServiceProvider' => + array ( + ), + 'Illuminate\\Hashing\\HashServiceProvider' => + array ( + ), + 'Illuminate\\Mail\\MailServiceProvider' => + array ( + ), + 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' => + array ( + ), + 'Illuminate\\Pipeline\\PipelineServiceProvider' => + array ( + ), + 'Illuminate\\Queue\\QueueServiceProvider' => + array ( + ), + 'Illuminate\\Redis\\RedisServiceProvider' => + array ( + ), + 'Illuminate\\Translation\\TranslationServiceProvider' => + array ( + ), + 'Illuminate\\Validation\\ValidationServiceProvider' => + array ( + ), + ), +); \ No newline at end of file diff --git a/workbench/bootstrap/providers.php b/workbench/bootstrap/providers.php new file mode 100644 index 0000000..a18fdb8 --- /dev/null +++ b/workbench/bootstrap/providers.php @@ -0,0 +1,12 @@ + [ + 'driver' => 'doctrine', + 'entity' => LaravelDoctrine\ACL\Permissions\Permission::class, + 'list' => [ + 'role.attach', + 'role.detach', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Roles + |-------------------------------------------------------------------------- + */ + 'roles' => [ + 'entity' => Workbench\App\Entities\Role::class, + ], + + /* + |-------------------------------------------------------------------------- + | Organisations + |-------------------------------------------------------------------------- + */ + 'organisations' => [ + 'entity' => Workbench\App\Entities\Organisation::class, + ], +]; \ No newline at end of file diff --git a/workbench/config/auth.php b/workbench/config/auth.php new file mode 100644 index 0000000..a6d8521 --- /dev/null +++ b/workbench/config/auth.php @@ -0,0 +1,117 @@ + [ + 'guard' => env('AUTH_GUARD', 'web'), + 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'), + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | which utilizes session storage plus the Eloquent user provider. + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | If you have multiple user tables or models you may configure multiple + | providers to represent the model / table. These providers may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'doctrine', + 'model' => env('AUTH_MODEL', User::class), + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | These configuration options specify the behavior of Laravel's password + | reset functionality, including the table utilized for token storage + | and the user provider that is invoked to actually retrieve users. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'), + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | window expires and users are asked to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800), + +]; diff --git a/workbench/config/database.php b/workbench/config/database.php new file mode 100644 index 0000000..4180cc4 --- /dev/null +++ b/workbench/config/database.php @@ -0,0 +1,175 @@ + env('DB_CONNECTION', 'sqlite'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Below are all of the database connections defined for your application. + | An example configuration is provided for each database system which + | is supported by Laravel. You're free to add / remove connections. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DB_URL'), + 'database' => env('DB_DATABASE', ':memory:'), + 'prefix' => '', + 'prefix_indexes' => null, + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + 'busy_timeout' => null, + 'journal_mode' => null, + 'synchronous' => null, + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'mariadb' => [ + 'driver' => 'mariadb', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run on the database. + | + */ + + 'migrations' => [ + 'table' => 'migrations', + 'update_date_on_publish' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as Memcached. You may define your connection settings here. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + 'persistent' => env('REDIS_PERSISTENT', false), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/workbench/config/doctrine.php b/workbench/config/doctrine.php new file mode 100644 index 0000000..ad02498 --- /dev/null +++ b/workbench/config/doctrine.php @@ -0,0 +1,215 @@ + Warning: Proxy auto generation should only be enabled in dev! + | + */ + 'managers' => [ + 'default' => [ + 'dev' => env('APP_DEBUG', false), + 'meta' => env('DOCTRINE_METADATA', 'attributes'), + 'connection' => env('DB_CONNECTION', 'sqlite'), + 'paths' => [ + app_path('Entities') + ], + + 'repository' => Doctrine\ORM\EntityRepository::class, + + 'proxies' => [ + 'namespace' => 'DoctrineProxies', + 'path' => storage_path('proxies'), + 'auto_generate' => env('DOCTRINE_PROXY_AUTOGENERATE', false) + ], + + /* + |-------------------------------------------------------------------------- + | Doctrine events + |-------------------------------------------------------------------------- + | + | The listener array expects the key to be a Doctrine event + | e.g. Doctrine\ORM\Events::onFlush + | + */ + 'events' => [ + 'listeners' => [], + 'subscribers' => [] + ], + + 'filters' => [], + + /* + |-------------------------------------------------------------------------- + | Doctrine mapping types + |-------------------------------------------------------------------------- + | + | Link a Database Type to a Local Doctrine Type + | + | Using 'enum' => 'string' is the same of: + | $doctrineManager->extendAll(function (\Doctrine\ORM\Configuration $configuration, + | \Doctrine\DBAL\Connection $connection, + | \Doctrine\Common\EventManager $eventManager) { + | $connection->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); + | }); + | + | References: + | https://www.doctrine-project.org/projects/doctrine-orm/en/current/cookbook/custom-mapping-types.html + | https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#custom-mapping-types + | https://www.doctrine-project.org/projects/doctrine-orm/en/current/cookbook/advanced-field-value-conversion-using-custom-mapping-types.html + | https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html + | https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types-in-the-schematool + |-------------------------------------------------------------------------- + */ + 'mapping_types' => [ + //'enum' => 'string' + ], + + /** + * References: + * https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/architecture.html#middlewares + */ + 'middlewares' => [ + // Doctrine\DBAL\Logging\Middleware::class + ] + ] + ], + /* + |-------------------------------------------------------------------------- + | Doctrine Extensions + |-------------------------------------------------------------------------- + | + | Enable/disable Doctrine Extensions by adding or removing them from the list + | + | If you want to require custom extensions you will have to require + | laravel-doctrine/extensions in your composer.json + | + */ + 'extensions' => [ + //LaravelDoctrine\Extensions\Timestamps\TimestampableExtension::class, + //LaravelDoctrine\Extensions\SoftDeletes\SoftDeleteableExtension::class, + //LaravelDoctrine\Extensions\Sluggable\SluggableExtension::class, + //LaravelDoctrine\Extensions\Sortable\SortableExtension::class, + //LaravelDoctrine\Extensions\Tree\TreeExtension::class, + //LaravelDoctrine\Extensions\Loggable\LoggableExtension::class, + //LaravelDoctrine\Extensions\Blameable\BlameableExtension::class, + //LaravelDoctrine\Extensions\IpTraceable\IpTraceableExtension::class, + //LaravelDoctrine\Extensions\Translatable\TranslatableExtension::class + ], + /* + |-------------------------------------------------------------------------- + | Doctrine custom types + |-------------------------------------------------------------------------- + | + | Create a custom or override a Doctrine Type + |-------------------------------------------------------------------------- + */ + 'custom_types' => [ + ], + /* + |-------------------------------------------------------------------------- + | DQL custom datetime functions + |-------------------------------------------------------------------------- + */ + 'custom_datetime_functions' => [], + /* + |-------------------------------------------------------------------------- + | DQL custom numeric functions + |-------------------------------------------------------------------------- + */ + 'custom_numeric_functions' => [], + /* + |-------------------------------------------------------------------------- + | DQL custom string functions + |-------------------------------------------------------------------------- + */ + 'custom_string_functions' => [], + /* + |-------------------------------------------------------------------------- + | Register custom hydrators + |-------------------------------------------------------------------------- + */ + 'custom_hydration_modes' => [ + // e.g. 'hydrationModeName' => MyHydrator::class, + ], + /* + |-------------------------------------------------------------------------- + | Cache + |-------------------------------------------------------------------------- + | + | Configure meta-data, query and result caching here. + | Optionally you can enable second level caching. + | + | Available: apc|array|file|illuminate|memcached|php_file|redis + | + */ + 'cache' => [ + 'second_level' => false, + 'default' => env('DOCTRINE_CACHE', 'array'), + 'namespace' => null, + 'metadata' => [ + 'driver' => env('DOCTRINE_METADATA_CACHE', env('DOCTRINE_CACHE', 'array')), + 'namespace' => 'metadata', + ], + 'query' => [ + 'driver' => env('DOCTRINE_QUERY_CACHE', env('DOCTRINE_CACHE', 'array')), + 'namespace' => 'query', + ], + 'result' => [ + 'driver' => env('DOCTRINE_RESULT_CACHE', env('DOCTRINE_CACHE', 'array')), + 'namespace' => 'result', + ], + ], + /* + |-------------------------------------------------------------------------- + | Gedmo extensions + |-------------------------------------------------------------------------- + | + | Settings for Gedmo extensions + | If you want to use this you will have to require + | laravel-doctrine/extensions in your composer.json + | + */ + 'gedmo' => [ + 'all_mappings' => false + ], + /* + |-------------------------------------------------------------------------- + | Validation + |-------------------------------------------------------------------------- + | + | Enables the Doctrine Presence Verifier for Validation + | + */ + 'doctrine_presence_verifier' => true, + + /* + |-------------------------------------------------------------------------- + | Notifications + |-------------------------------------------------------------------------- + | + | Doctrine notifications channel + | + */ + 'notifications' => [ + 'channel' => 'database' + ] +]; diff --git a/workbench/config/migrations.php b/workbench/config/migrations.php new file mode 100644 index 0000000..216e18f --- /dev/null +++ b/workbench/config/migrations.php @@ -0,0 +1,67 @@ + [ + 'table_storage' => [ + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + 'table_name' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Schema filter + |-------------------------------------------------------------------------- + | + | Tables which are filtered by Regular Expression. You optionally + | exclude or limit to certain tables. The default will + | filter all tables. + | + */ + 'schema_filter' => '/^(?!password_resets|failed_jobs).*$/' + ], + + 'migrations_paths' => [ + 'Database\\Migrations' => database_path('migrations') + ], + + /* + |-------------------------------------------------------------------------- + | Migration Organize Directory + |-------------------------------------------------------------------------- + | + | Organize migrations file by directory. + | Possible values: "year", "year_and_month" and "none" + | + | none: + | directory/ + | "year": + | directory/2020/ + | "year_and_month": + | directory/2020/01/ + | + */ + 'organize_migrations' => 'none', + ], +]; diff --git a/workbench/config/session.php b/workbench/config/session.php new file mode 100644 index 0000000..e9b535a --- /dev/null +++ b/workbench/config/session.php @@ -0,0 +1,217 @@ + env('SESSION_DRIVER', 'array'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to expire immediately when the browser is closed then you may + | indicate that via the expire_on_close configuration option. + | + */ + + 'lifetime' => (int) env('SESSION_LIFETIME', 120), + + 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false), + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it's stored. All encryption is performed + | automatically by Laravel and you may use the session like normal. + | + */ + + 'encrypt' => env('SESSION_ENCRYPT', false), + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When utilizing the "file" session driver, the session files are placed + | on disk. The default storage location is defined here; however, you + | are free to provide another location where they should be stored. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table to + | be used to store sessions. Of course, a sensible default is defined + | for you; however, you're welcome to change this to another table. + | + */ + + 'table' => env('SESSION_TABLE', 'sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | When using one of the framework's cache driven session backends, you may + | define the cache store which should be used to store the session data + | between requests. This must match one of your defined cache stores. + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the session cookie that is created by + | the framework. Typically, you should not need to change this value + | since doing so does not grant a meaningful security improvement. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application, but you're free to change this when necessary. + | + */ + + 'path' => env('SESSION_PATH', '/'), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | This value determines the domain and subdomains the session cookie is + | available to. By default, the cookie will be available to the root + | domain and all subdomains. Typically, this shouldn't be changed. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. It's unlikely you should disable this option. + | + */ + + 'http_only' => env('SESSION_HTTP_ONLY', true), + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" to permit secure cross-site requests. + | + | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => env('SESSION_SAME_SITE', 'lax'), + + /* + |-------------------------------------------------------------------------- + | Partitioned Cookies + |-------------------------------------------------------------------------- + | + | Setting this value to true will tie the cookie to the top-level site for + | a cross-site context. Partitioned cookies are accepted by the browser + | when flagged "secure" and the Same-Site attribute is set to "none". + | + */ + + 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false), + +]; diff --git a/workbench/config/view.php b/workbench/config/view.php new file mode 100644 index 0000000..22b8a18 --- /dev/null +++ b/workbench/config/view.php @@ -0,0 +1,36 @@ + [ + resource_path('views'), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env( + 'VIEW_COMPILED_PATH', + realpath(storage_path('framework/views')) + ), + +]; diff --git a/workbench/database/README.md b/workbench/database/README.md new file mode 100644 index 0000000..4a57e5b --- /dev/null +++ b/workbench/database/README.md @@ -0,0 +1,79 @@ +# Laravel Doctrine ORM Entity Factories + +This guide explains how to create and use entity factories for Doctrine entities in the workbench. Factories are essential for generating test data and seeding your database in a consistent, maintainable way. + +## Defining an Entity Factory + +To define a factory for an entity, use the `$factory->define()` method in a factory file (e.g., `UserEntityFactory.php`). + +```php +$factory->define(App\Entities\User::class, function(Faker\Generator $faker) { + return [ + 'name' => $faker->name, + 'emailAddress' => $faker->email + ]; +}); +``` +- Use Doctrine entity property names (not database column names). +- You can define multiple types for the same entity using `defineAs`: + +```php +$factory->defineAs(App\Entities\User::class, 'admin', function(Faker\Generator $faker) { + return [ + 'name' => $faker->name, + 'emailAddress' => $faker->email, + 'isAdmin' => true + ]; +}); +``` + +## Using Factories in Seeds and Tests + +After defining factories, you can generate entities for tests or seeds using the `entity()` helper or the factory directly. + +- **Create (persist) a single entity:** + ```php + entity(App\Entities\User::class)->create(); + // or + $factory->of(App\Entities\User::class)->create(); + ``` + +- **Make (do not persist) a single entity:** + ```php + entity(App\Entities\User::class)->make(); + ``` + +- **Create multiple entities:** + ```php + entity(App\Entities\User::class, 3)->create(); + // or + $factory->of(App\Entities\User::class)->times(3)->create(); + ``` + +- **Create a specific type:** + ```php + entity(App\Entities\User::class, 'admin')->create(); + ``` + +## Passing Extra Attributes + +You can override default attributes by passing an array: + +```php +$factory->define(App\Entities\User::class, function(Faker\Generator $faker, array $attributes) { + return [ + 'name' => $attributes['name'] ?? $faker->name, + 'emailAddress' => $faker->email + ]; +}); + +$user = entity(App\Entities\User::class)->make(['name' => 'Taylor']); +``` + +## Notes +- The `entity()` helper returns an `Illuminate\Support\Collection` if you request multiple entities. +- Use `->make()` to get an instance without saving, or `->create()` to persist to the database. +- Always use property names as defined in your Doctrine entity. + +## References +- [Official Docs: Testing - Entity Factories](https://laravel-doctrine-orm-official.readthedocs.io/en/latest/testing.html) diff --git a/workbench/database/factories/.gitkeep b/workbench/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/workbench/database/factories/OrganisationFactory.php b/workbench/database/factories/OrganisationFactory.php new file mode 100644 index 0000000..3e49b90 --- /dev/null +++ b/workbench/database/factories/OrganisationFactory.php @@ -0,0 +1,10 @@ +define(Organisation::class, function(Faker\Generator $faker, array $attributes) { + return [ + 'name' => $attributes['name'] ?? $faker->unique()->company, + ]; +}); diff --git a/workbench/database/factories/PermissionFactory.php b/workbench/database/factories/PermissionFactory.php new file mode 100644 index 0000000..f09e5ad --- /dev/null +++ b/workbench/database/factories/PermissionFactory.php @@ -0,0 +1,32 @@ +define(Permission::class, static function (Generator $faker, array $attributes = []) { + return [ + 'name' => $attributes['name'] ?? $faker->unique()->word . '-' . $faker->unique()->word, + ]; +}); + +$factory->defineAs(Permission::class, 'view', static function () { + return [ + 'name' => 'view', + ]; +}); + +$factory->defineAs(Permission::class, 'edit', static function () { + return [ + 'name' => 'edit', + ]; +}); + +$factory->defineAs(Permission::class, 'delete', static function () { + return [ + 'name' => 'delete', + ]; +}); diff --git a/workbench/database/factories/RoleFactory.php b/workbench/database/factories/RoleFactory.php new file mode 100644 index 0000000..c277d2a --- /dev/null +++ b/workbench/database/factories/RoleFactory.php @@ -0,0 +1,27 @@ +define(Role::class, static function (Generator $faker, array $attributes = []) { + return [ + 'name' => $attributes['name'] ?? $faker->unique()->word . '-' . $faker->unique()->word, + ]; +}); + +$factory->defineAs(Role::class, 'admin', static function () { + return [ + 'name' => 'admin', + ]; +}); + +$factory->defineAs(Role::class, 'user', static function () { + return [ + 'name' => 'user', + ]; +}); + diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php new file mode 100644 index 0000000..11a26bf --- /dev/null +++ b/workbench/database/factories/UserFactory.php @@ -0,0 +1,24 @@ +define(User::class, static function (Generator $faker, array $attributes = []) { + return [ + 'name' => $faker->name(), + 'email' => $faker->safeEmail, + 'password' => 'password', + ]; +}); + +$factory->defineAs(User::class, 'test', static function (Generator $faker, array $attributes = []) { + return [ + 'name' => 'test', + 'email' => 'test@test.tld', + 'password' => 'password', + ]; +}); diff --git a/workbench/database/factories/UserJsonPermissions.php b/workbench/database/factories/UserJsonPermissions.php new file mode 100644 index 0000000..b1527b9 --- /dev/null +++ b/workbench/database/factories/UserJsonPermissions.php @@ -0,0 +1,16 @@ +define(UserJsonPermissions::class, static function (Generator $faker, array $attributes = []) { + return [ + 'name' => $attributes['name'] ?? $faker->name(), + 'email' => $attributes['email'] ?? $faker->safeEmail, + 'password' => 'password', + ]; +}); diff --git a/workbench/database/factories/UserSingleOrgFactory.php b/workbench/database/factories/UserSingleOrgFactory.php new file mode 100644 index 0000000..d4e6c8c --- /dev/null +++ b/workbench/database/factories/UserSingleOrgFactory.php @@ -0,0 +1,16 @@ +define(UserSingleOrg::class, static function (Generator $faker, array $attributes = []) { + return [ + 'name' => $attributes['name'] ?? $faker->name(), + 'email' => $attributes['email'] ?? $faker->safeEmail, + 'password' => 'password', + ]; +}); diff --git a/workbench/database/migrations/.gitkeep b/workbench/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..ce9bd15 --- /dev/null +++ b/workbench/database/seeders/DatabaseSeeder.php @@ -0,0 +1,23 @@ +create(); + + UserFactory::new()->create([ + 'name' => 'Test User', + 'email' => 'test@example.com', + ]); + } +} diff --git a/workbench/resources/views/.gitkeep b/workbench/resources/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/workbench/routes/console.php b/workbench/routes/console.php new file mode 100644 index 0000000..eff2ed2 --- /dev/null +++ b/workbench/routes/console.php @@ -0,0 +1,8 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote')->hourly(); diff --git a/workbench/routes/web.php b/workbench/routes/web.php new file mode 100644 index 0000000..86a06c5 --- /dev/null +++ b/workbench/routes/web.php @@ -0,0 +1,7 @@ + Date: Sun, 27 Apr 2025 13:46:19 +0300 Subject: [PATCH 2/9] docs(fixes): documentation update --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1dc015b..13768e4 100644 --- a/README.md +++ b/README.md @@ -40,5 +40,5 @@ or in the docs directory. Versions -------- -* Version 2 supports DBAL ^4.0, ORM ^3.0, and PHP 8.2. +* Version 2 supports Laravel 11-12, ORM ^3.0, DBAL ^4.0, and PHP 8.2. * Version 1 supports Laravel 6 - 11, DBAL ^2.0, ORM ^2.0, and PHP ^5.5 - ^8.0. diff --git a/composer.json b/composer.json index 09c2449..8374e5e 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "laravel-doctrine/acl", "type": "library", - "description": "Doctrine ACL for Doctrine 2 and Laravel", + "description": "ACL for Laravel and Doctrine", "license": "MIT", "keywords": [ "doctrine", From 9c0c95ba402df287a7b15609f6dfab9b23ed2af1 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Sun, 27 Apr 2025 13:46:48 +0300 Subject: [PATCH 3/9] chore(phpcs): added phpcs to workbench and refactored mapping namespace --- phpcs.xml.dist | 1 + src/Contracts/BelongsToOrganisations.php | 2 +- src/Contracts/HasPermissions.php | 2 +- src/Contracts/HasRoles.php | 2 +- src/Mappings/Builders/Builder.php | 6 +- src/Mappings/Builders/JsonArrayBuilder.php | 6 +- src/Mappings/Builders/ManyToManyBuilder.php | 9 +- src/Mappings/Builders/ManyToOneBuilder.php | 9 +- ...nfigAttribute.php => MappingAttribute.php} | 3 +- src/Mappings/RelationAttribute.php | 2 +- .../BelongsToOrganisationSubscriber.php | 6 +- .../BelongsToOrganisationsSubscriber.php | 6 +- .../Subscribers/HasPermissionsSubscriber.php | 6 +- .../Subscribers/HasRolesSubscriber.php | 6 +- .../Subscribers/MappedEventSubscriber.php | 8 +- workbench/app/Entities/Organisation.php | 7 +- workbench/app/Entities/Role.php | 19 +- workbench/app/Entities/User.php | 49 +- .../app/Entities/UserJsonPermissions.php | 14 +- workbench/app/Entities/UserSingleOrg.php | 51 +- .../Providers/WorkbenchServiceProvider.php | 4 +- workbench/bootstrap/app.php | 13 +- workbench/bootstrap/cache/packages.php | 140 +++--- workbench/bootstrap/cache/services.php | 475 +++++++++--------- workbench/bootstrap/providers.php | 3 +- workbench/config/acl.php | 14 +- workbench/config/auth.php | 2 + workbench/config/database.php | 4 +- workbench/config/doctrine.php | 51 +- workbench/config/migrations.php | 4 +- workbench/config/session.php | 4 +- workbench/config/view.php | 4 +- .../factories/OrganisationFactory.php | 7 +- .../database/factories/PermissionFactory.php | 18 +- workbench/database/factories/RoleFactory.php | 13 +- workbench/database/factories/UserFactory.php | 4 + .../factories/UserJsonPermissions.php | 4 + .../factories/UserSingleOrgFactory.php | 4 + workbench/database/seeders/DatabaseSeeder.php | 2 + workbench/routes/console.php | 4 +- workbench/routes/web.php | 4 +- 41 files changed, 517 insertions(+), 475 deletions(-) rename src/Mappings/{ConfigAttribute.php => MappingAttribute.php} (59%) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index c0e526a..76b6d6f 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -12,6 +12,7 @@ src tests + workbench/app diff --git a/src/Contracts/BelongsToOrganisations.php b/src/Contracts/BelongsToOrganisations.php index 87fb813..14342d9 100644 --- a/src/Contracts/BelongsToOrganisations.php +++ b/src/Contracts/BelongsToOrganisations.php @@ -8,6 +8,6 @@ interface BelongsToOrganisations { - /** @return Collection|Organisation[] */ + /** @return Collection|Organisation[] */ public function getOrganisations(): Collection|array; } diff --git a/src/Contracts/HasPermissions.php b/src/Contracts/HasPermissions.php index 18ee3ee..300956f 100644 --- a/src/Contracts/HasPermissions.php +++ b/src/Contracts/HasPermissions.php @@ -10,6 +10,6 @@ interface HasPermissions { public function hasPermissionTo(string $permission): bool; - /** @return Collection|Permission[] */ + /** @return Collection|Permission[]|Collection|string[] */ public function getPermissions(): Collection|array; } diff --git a/src/Contracts/HasRoles.php b/src/Contracts/HasRoles.php index 7c8edcd..a9cff1c 100644 --- a/src/Contracts/HasRoles.php +++ b/src/Contracts/HasRoles.php @@ -8,6 +8,6 @@ interface HasRoles { - /** @return Collection|Role[] */ + /** @return Collection|Role[] */ public function getRoles(): Collection|array; } diff --git a/src/Mappings/Builders/Builder.php b/src/Mappings/Builders/Builder.php index 2baf593..c6a9960 100644 --- a/src/Mappings/Builders/Builder.php +++ b/src/Mappings/Builders/Builder.php @@ -4,11 +4,11 @@ namespace LaravelDoctrine\ACL\Mappings\Builders; -use Doctrine\ORM\Mapping\ClassMetadata; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use Doctrine\Persistence\Mapping\ClassMetadata; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionProperty; interface Builder { - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void; + public function build(ClassMetadata $metadata, ReflectionProperty $property, MappingAttribute $attribute): void; } diff --git a/src/Mappings/Builders/JsonArrayBuilder.php b/src/Mappings/Builders/JsonArrayBuilder.php index c100f37..e949e9f 100644 --- a/src/Mappings/Builders/JsonArrayBuilder.php +++ b/src/Mappings/Builders/JsonArrayBuilder.php @@ -7,9 +7,9 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; use Doctrine\ORM\Mapping\Builder\FieldBuilder; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionProperty; class JsonArrayBuilder implements Builder @@ -18,7 +18,7 @@ public function __construct(protected Repository $config) { } - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void + public function build(ClassMetadata $metadata, ReflectionProperty $property, MappingAttribute $attribute): void { $builder = new FieldBuilder( new ClassMetadataBuilder($metadata), diff --git a/src/Mappings/Builders/ManyToManyBuilder.php b/src/Mappings/Builders/ManyToManyBuilder.php index bc0c223..4dc2adc 100644 --- a/src/Mappings/Builders/ManyToManyBuilder.php +++ b/src/Mappings/Builders/ManyToManyBuilder.php @@ -6,9 +6,10 @@ use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; use Doctrine\ORM\Mapping\Builder\ManyToManyAssociationBuilder; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionProperty; class ManyToManyBuilder implements Builder @@ -17,7 +18,7 @@ public function __construct(protected Repository $config) { } - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void + public function build(ClassMetadata $metadata, ReflectionProperty $property, MappingAttribute $attribute): void { $builder = new ManyToManyAssociationBuilder( new ClassMetadataBuilder($metadata), @@ -25,7 +26,7 @@ public function build(ClassMetadata $metadata, ReflectionProperty $property, Con 'fieldName' => $property->getName(), 'targetEntity' => $attribute->getTargetEntity($this->config), ], - ClassMetadata::MANY_TO_MANY, + OrmClassMetadata::MANY_TO_MANY, ); if (isset($attribute->inversedBy) && $attribute->inversedBy) { diff --git a/src/Mappings/Builders/ManyToOneBuilder.php b/src/Mappings/Builders/ManyToOneBuilder.php index c802e40..97a74e9 100644 --- a/src/Mappings/Builders/ManyToOneBuilder.php +++ b/src/Mappings/Builders/ManyToOneBuilder.php @@ -6,9 +6,10 @@ use Doctrine\ORM\Mapping\Builder\AssociationBuilder; use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionProperty; class ManyToOneBuilder implements Builder @@ -17,7 +18,7 @@ public function __construct(protected Repository $config) { } - public function build(ClassMetadata $metadata, ReflectionProperty $property, ConfigAttribute $attribute): void + public function build(ClassMetadata $metadata, ReflectionProperty $property, MappingAttribute $attribute): void { $builder = new AssociationBuilder( new ClassMetadataBuilder($metadata), @@ -25,7 +26,7 @@ public function build(ClassMetadata $metadata, ReflectionProperty $property, Con 'fieldName' => $property->getName(), 'targetEntity' => $attribute->getTargetEntity($this->config), ], - ClassMetadata::MANY_TO_ONE, + OrmClassMetadata::MANY_TO_ONE, ); if (isset($attribute->inversedBy) && $attribute->inversedBy) { diff --git a/src/Mappings/ConfigAttribute.php b/src/Mappings/MappingAttribute.php similarity index 59% rename from src/Mappings/ConfigAttribute.php rename to src/Mappings/MappingAttribute.php index fc099cd..88b6b60 100644 --- a/src/Mappings/ConfigAttribute.php +++ b/src/Mappings/MappingAttribute.php @@ -4,9 +4,10 @@ namespace LaravelDoctrine\ACL\Mappings; +use Doctrine\ORM\Mapping\MappingAttribute as DoctrineMappingAttribute; use Illuminate\Contracts\Config\Repository; -interface ConfigAttribute +interface MappingAttribute extends DoctrineMappingAttribute { public function getTargetEntity(Repository $config): string|null; } diff --git a/src/Mappings/RelationAttribute.php b/src/Mappings/RelationAttribute.php index cb58812..c1a11aa 100644 --- a/src/Mappings/RelationAttribute.php +++ b/src/Mappings/RelationAttribute.php @@ -4,7 +4,7 @@ namespace LaravelDoctrine\ACL\Mappings; -abstract class RelationAttribute implements ConfigAttribute +abstract class RelationAttribute implements MappingAttribute { public string|null $targetEntity; public string|null $mappedBy; diff --git a/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php b/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php index 4a9103a..9cb56d0 100644 --- a/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php +++ b/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php @@ -4,12 +4,12 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation as BelongsToOrganisationContract; use LaravelDoctrine\ACL\Mappings\BelongsToOrganisation; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToOneBuilder; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; class BelongsToOrganisationSubscriber extends MappedEventSubscriber { @@ -23,7 +23,7 @@ protected function shouldBeMapped(ClassMetadata $metadata): bool return $this->getInstance($metadata) instanceof BelongsToOrganisationContract; } - protected function getBuilder(ConfigAttribute $attribute): Builder + protected function getBuilder(MappingAttribute $attribute): Builder { return new ManyToOneBuilder($this->config); } diff --git a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php index f40094c..a4b8bb7 100644 --- a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php +++ b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php @@ -4,12 +4,12 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations as BelongsToOrganisationsContract; use LaravelDoctrine\ACL\Mappings\BelongsToOrganisations; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; class BelongsToOrganisationsSubscriber extends MappedEventSubscriber { @@ -23,7 +23,7 @@ protected function shouldBeMapped(ClassMetadata $metadata): bool return $this->getInstance($metadata) instanceof BelongsToOrganisationsContract; } - protected function getBuilder(ConfigAttribute $attribute): Builder + protected function getBuilder(MappingAttribute $attribute): Builder { return new ManyToManyBuilder($this->config); } diff --git a/src/Mappings/Subscribers/HasPermissionsSubscriber.php b/src/Mappings/Subscribers/HasPermissionsSubscriber.php index ba987af..6177acf 100644 --- a/src/Mappings/Subscribers/HasPermissionsSubscriber.php +++ b/src/Mappings/Subscribers/HasPermissionsSubscriber.php @@ -4,13 +4,13 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\JsonArrayBuilder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; use LaravelDoctrine\ACL\Mappings\HasPermissions; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; class HasPermissionsSubscriber extends MappedEventSubscriber { @@ -24,7 +24,7 @@ public function getAttributeClass(): string return HasPermissions::class; } - protected function getBuilder(ConfigAttribute $attribute): Builder + protected function getBuilder(MappingAttribute $attribute): Builder { // If there's a target entity, create pivot table if ($attribute->getTargetEntity($this->config)) { diff --git a/src/Mappings/Subscribers/HasRolesSubscriber.php b/src/Mappings/Subscribers/HasRolesSubscriber.php index 4debd13..a01dd4b 100644 --- a/src/Mappings/Subscribers/HasRolesSubscriber.php +++ b/src/Mappings/Subscribers/HasRolesSubscriber.php @@ -4,12 +4,12 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; use LaravelDoctrine\ACL\Mappings\HasRoles; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; class HasRolesSubscriber extends MappedEventSubscriber { @@ -23,7 +23,7 @@ protected function shouldBeMapped(ClassMetadata $metadata): bool return $this->getInstance($metadata) instanceof HasRolesContract; } - protected function getBuilder(ConfigAttribute $attribute): Builder + protected function getBuilder(MappingAttribute $attribute): Builder { return new ManyToManyBuilder($this->config); } diff --git a/src/Mappings/Subscribers/MappedEventSubscriber.php b/src/Mappings/Subscribers/MappedEventSubscriber.php index 0ab732b..6bf9349 100644 --- a/src/Mappings/Subscribers/MappedEventSubscriber.php +++ b/src/Mappings/Subscribers/MappedEventSubscriber.php @@ -7,20 +7,20 @@ use Doctrine\Common\EventSubscriber; use Doctrine\ORM\Event\LoadClassMetadataEventArgs; use Doctrine\ORM\Events; -use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Persistence\Mapping\ClassMetadata; use Illuminate\Contracts\Config\Repository; use LaravelDoctrine\ACL\Mappings\Builders\Builder; -use LaravelDoctrine\ACL\Mappings\ConfigAttribute; +use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionClass; abstract class MappedEventSubscriber implements EventSubscriber { - /** @return class-string */ + /** @return class-string */ abstract public function getAttributeClass(): string; abstract protected function shouldBeMapped(ClassMetadata $metadata): bool; - abstract protected function getBuilder(ConfigAttribute $attribute): Builder; + abstract protected function getBuilder(MappingAttribute $attribute): Builder; public function __construct(protected Repository $config) { diff --git a/workbench/app/Entities/Organisation.php b/workbench/app/Entities/Organisation.php index a6b471f..b809430 100644 --- a/workbench/app/Entities/Organisation.php +++ b/workbench/app/Entities/Organisation.php @@ -1,5 +1,7 @@ name = $name; } - public function getId(): ?int + public function getId(): int|null { return $this->id; } @@ -34,6 +36,7 @@ public function getName(): string public function setName(string $name): self { $this->name = $name; + return $this; } } diff --git a/workbench/app/Entities/Role.php b/workbench/app/Entities/Role.php index 1f4705d..09633c6 100644 --- a/workbench/app/Entities/Role.php +++ b/workbench/app/Entities/Role.php @@ -7,11 +7,13 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use LaravelDoctrine\ACL\Contracts\Role as RoleContract; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Mappings\HasPermissions as MappingsHasPermissions; +use LaravelDoctrine\ACL\Contracts\Role as RoleContract; +use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Permissions\HasPermissions; +use function is_array; + #[ORM\Entity] #[ORM\Table(name: 'roles')] class Role implements RoleContract, HasPermissionsContract @@ -26,12 +28,13 @@ class Role implements RoleContract, HasPermissionsContract #[ORM\Column(name: 'name', type: 'string', unique: true)] protected string $name; - #[MappingsHasPermissions()] + /** @var Collection */ + #[ACL\HasPermissions()] public Collection $permissions; public function __construct(string $name) { - $this->name = $name; + $this->name = $name; $this->permissions = new ArrayCollection(); } @@ -40,18 +43,22 @@ public function getName(): string return $this->name; } - public function getId(): ?int + public function getId(): int|null { return $this->id; } + /** @return Collection */ public function getPermissions(): Collection { return $this->permissions; } - public function setPermissions($permissions): void + /** @param Collection|string[] $permissions */ + public function setPermissions(Collection|array $permissions): self { $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; + + return $this; } } diff --git a/workbench/app/Entities/User.php b/workbench/app/Entities/User.php index fd5676b..2f88b2e 100644 --- a/workbench/app/Entities/User.php +++ b/workbench/app/Entities/User.php @@ -7,23 +7,23 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; -use LaravelDoctrine\ORM\Auth\Authenticatable; use Illuminate\Foundation\Auth\Access\Authorizable; -use Illuminate\Auth\Passwords\CanResetPassword; -use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations as BelongsToOrganisationsContract; -use LaravelDoctrine\ACL\Mappings\BelongsToOrganisations; -use LaravelDoctrine\ACL\Mappings\HasPermissions as MappingsHasPermissions; -use LaravelDoctrine\ACL\Mappings\HasRoles as MappingsHasRoles; +use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; +use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; +use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation; -use LaravelDoctrine\ACL\Roles\HasRoles; use LaravelDoctrine\ACL\Permissions\HasPermissions; +use LaravelDoctrine\ACL\Roles\HasRoles; +use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; +use function is_array; + #[ORM\Entity] #[ORM\Table()] class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRolesContract, HasPermissionsContract, BelongsToOrganisationsContract @@ -47,49 +47,64 @@ class User implements AuthenticatableContract, AuthorizableContract, CanResetPas #[ORM\Column(name: 'email')] public string $email; - #[MappingsHasRoles()] + /** @var Collection */ + #[ACL\HasRoles()] public Collection $roles; - #[MappingsHasPermissions()] + /** @var Collection */ + #[ACL\HasPermissions()] public Collection $permissions; - #[BelongsToOrganisations()] + /** @var Collection */ + #[ACL\BelongsToOrganisations()] public Collection $organisations; public function __construct() { - $this->roles = new ArrayCollection(); - $this->permissions = new ArrayCollection(); + $this->roles = new ArrayCollection(); + $this->permissions = new ArrayCollection(); $this->organisations = new ArrayCollection(); } + /** @return Collection */ public function getRoles(): Collection { return $this->roles; } - public function setRoles($roles): void + /** @param Collection|Role[] $roles */ + public function setRoles(Collection|array $roles): self { $this->roles = is_array($roles) ? new ArrayCollection($roles) : $roles; + + return $this; } + /** @return Collection */ public function getPermissions(): Collection { return $this->permissions; } - public function setPermissions($permissions): void + /** @param Collection|string[] $permissions */ + public function setPermissions(Collection|array $permissions): self { $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; + + return $this; } + /** @return Collection */ public function getOrganisations(): Collection { return $this->organisations; } - public function setOrganisations($organisations): void + /** @param Collection|Organisation[] $organisations */ + public function setOrganisations(Collection|array $organisations): self { $this->organisations = is_array($organisations) ? new ArrayCollection($organisations) : $organisations; + + return $this; } } diff --git a/workbench/app/Entities/UserJsonPermissions.php b/workbench/app/Entities/UserJsonPermissions.php index 06f339c..fb60db2 100644 --- a/workbench/app/Entities/UserJsonPermissions.php +++ b/workbench/app/Entities/UserJsonPermissions.php @@ -5,15 +5,15 @@ namespace Workbench\App\Entities; use Doctrine\ORM\Mapping as ORM; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; -use LaravelDoctrine\ORM\Auth\Authenticatable; use Illuminate\Foundation\Auth\Access\Authorizable; -use Illuminate\Auth\Passwords\CanResetPassword; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Mappings\HasPermissions as MappingsHasPermissions; +use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Permissions\HasPermissions; +use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; #[ORM\Entity] @@ -37,17 +37,21 @@ class UserJsonPermissions implements AuthenticatableContract, AuthorizableContra #[ORM\Column(name: 'email')] public string $email; - #[MappingsHasPermissions(inversedBy: 'users')] + /** @var array */ + #[ACL\HasPermissions(inversedBy: 'users')] public array $permissions = []; + /** @return array */ public function getPermissions(): array { return $this->permissions; } + /** @param array $permissions */ public function setPermissions(array $permissions): self { $this->permissions = $permissions; + return $this; } } diff --git a/workbench/app/Entities/UserSingleOrg.php b/workbench/app/Entities/UserSingleOrg.php index b5dba13..4b3641f 100644 --- a/workbench/app/Entities/UserSingleOrg.php +++ b/workbench/app/Entities/UserSingleOrg.php @@ -4,25 +4,26 @@ namespace Workbench\App\Entities; -use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; -use LaravelDoctrine\ORM\Auth\Authenticatable; use Illuminate\Foundation\Auth\Access\Authorizable; -use Illuminate\Auth\Passwords\CanResetPassword; -use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation as BelongsToOrganisationContract; -use LaravelDoctrine\ACL\Mappings\BelongsToOrganisation; -use LaravelDoctrine\ACL\Mappings\HasRoles as MappingsHasRoles; +use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; +use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; +use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation as TraitBelongsToOrganisation; -use LaravelDoctrine\ACL\Roles\HasRoles; use LaravelDoctrine\ACL\Permissions\HasPermissions; +use LaravelDoctrine\ACL\Roles\HasRoles; +use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; +use function is_array; + #[ORM\Entity] #[ORM\Table()] class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRolesContract, HasPermissionsContract, BelongsToOrganisationContract @@ -46,48 +47,64 @@ class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, Ca #[ORM\Column(name: 'email')] public string $email; - #[MappingsHasRoles()] + /** @var Collection */ + #[ACL\HasRoles()] public Collection $roles; + /** @var array */ #[ORM\Column(type: 'json')] public array $permissions = []; - #[BelongsToOrganisation()] - public ?Organisation $organisation = null; - + #[ACL\BelongsToOrganisation()] + public Organisation|null $organisation = null; public function __construct() { $this->roles = new ArrayCollection(); } + public function getId(): int|null + { + return $this->id; + } + + /** @return Collection */ public function getRoles(): Collection { return $this->roles; } - public function setRoles($roles): void + /** @param Collection|Role[] $roles */ + public function setRoles(Collection|array $roles): self { $this->roles = is_array($roles) ? new ArrayCollection($roles) : $roles; + + return $this; } + /** @return array */ public function getPermissions(): array { return $this->permissions; } - public function setPermissions(array $permissions): void + /** @param array $permissions */ + public function setPermissions(array $permissions): self { $this->permissions = $permissions; + + return $this; } - public function getOrganisation(): ?Organisation + public function getOrganisation(): Organisation|null { return $this->organisation; } - public function setOrganisation($organisation): void + public function setOrganisation(Organisation|null $organisation): self { $this->organisation = $organisation; + + return $this; } } diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php index e8cec9c..99148d7 100644 --- a/workbench/app/Providers/WorkbenchServiceProvider.php +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -1,5 +1,7 @@ withRouting( - web: __DIR__.'/../routes/web.php', - commands: __DIR__.'/../routes/console.php', + web: __DIR__ . '/../routes/web.php', + commands: __DIR__ . '/../routes/console.php', ) - ->withMiddleware(function (Middleware $middleware) { - // + ->withMiddleware(static function (Middleware $middleware): void { }) - ->withExceptions(function (Exceptions $exceptions) { - // + ->withExceptions(static function (Exceptions $exceptions): void { })->create(); diff --git a/workbench/bootstrap/cache/packages.php b/workbench/bootstrap/cache/packages.php index ed5c8ab..2ee8916 100755 --- a/workbench/bootstrap/cache/packages.php +++ b/workbench/bootstrap/cache/packages.php @@ -1,78 +1,62 @@ - - array ( - 'providers' => - array ( - 0 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', - ), - ), - 'laravel-doctrine/orm' => - array ( - 'aliases' => - array ( - 'Doctrine' => 'LaravelDoctrine\\ORM\\Facades\\Doctrine', - 'Registry' => 'LaravelDoctrine\\ORM\\Facades\\Registry', - 'EntityManager' => 'LaravelDoctrine\\ORM\\Facades\\EntityManager', - ), - 'providers' => - array ( - 0 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', - ), - ), - 'laravel/pail' => - array ( - 'providers' => - array ( - 0 => 'Laravel\\Pail\\PailServiceProvider', - ), - ), - 'laravel/tinker' => - array ( - 'providers' => - array ( - 0 => 'Laravel\\Tinker\\TinkerServiceProvider', - ), - ), - 'nesbot/carbon' => - array ( - 'providers' => - array ( - 0 => 'Carbon\\Laravel\\ServiceProvider', - ), - ), - 'nunomaduro/collision' => - array ( - 'providers' => - array ( - 0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - ), - ), - 'nunomaduro/termwind' => - array ( - 'providers' => - array ( - 0 => 'Termwind\\Laravel\\TermwindServiceProvider', - ), - ), - 'orchestra/canvas' => - array ( - 'providers' => - array ( - 0 => 'Orchestra\\Canvas\\LaravelServiceProvider', - ), - ), - 'orchestra/canvas-core' => - array ( - 'providers' => - array ( - 0 => 'Orchestra\\Canvas\\Core\\LaravelServiceProvider', - ), - ), - 'sowl/laravel-doctrine-acl' => - array ( - 'providers' => - array ( - 0 => 'LaravelDoctrine\\ACL\\AclServiceProvider', - ), - ), -); \ No newline at end of file + + [ + 'providers' => + [0 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider'], + ], + 'laravel-doctrine/orm' => + [ + 'aliases' => + [ + 'Doctrine' => 'LaravelDoctrine\\ORM\\Facades\\Doctrine', + 'Registry' => 'LaravelDoctrine\\ORM\\Facades\\Registry', + 'EntityManager' => 'LaravelDoctrine\\ORM\\Facades\\EntityManager', + ], + 'providers' => + [0 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider'], + ], + 'laravel/pail' => + [ + 'providers' => + [0 => 'Laravel\\Pail\\PailServiceProvider'], + ], + 'laravel/tinker' => + [ + 'providers' => + [0 => 'Laravel\\Tinker\\TinkerServiceProvider'], + ], + 'nesbot/carbon' => + [ + 'providers' => + [0 => 'Carbon\\Laravel\\ServiceProvider'], + ], + 'nunomaduro/collision' => + [ + 'providers' => + [0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider'], + ], + 'nunomaduro/termwind' => + [ + 'providers' => + [0 => 'Termwind\\Laravel\\TermwindServiceProvider'], + ], + 'orchestra/canvas' => + [ + 'providers' => + [0 => 'Orchestra\\Canvas\\LaravelServiceProvider'], + ], + 'orchestra/canvas-core' => + [ + 'providers' => + [0 => 'Orchestra\\Canvas\\Core\\LaravelServiceProvider'], + ], + 'sowl/laravel-doctrine-acl' => + [ + 'providers' => + [0 => 'LaravelDoctrine\\ACL\\AclServiceProvider'], + ], +]; diff --git a/workbench/bootstrap/cache/services.php b/workbench/bootstrap/cache/services.php index 5576370..6a8922a 100755 --- a/workbench/bootstrap/cache/services.php +++ b/workbench/bootstrap/cache/services.php @@ -1,242 +1,233 @@ - - array ( - 0 => 'Illuminate\\Auth\\AuthServiceProvider', - 1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 2 => 'Illuminate\\Bus\\BusServiceProvider', - 3 => 'Illuminate\\Cache\\CacheServiceProvider', - 4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 5 => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', - 6 => 'Illuminate\\Cookie\\CookieServiceProvider', - 7 => 'Illuminate\\Database\\DatabaseServiceProvider', - 8 => 'Illuminate\\Encryption\\EncryptionServiceProvider', - 9 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', - 10 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', - 11 => 'Illuminate\\Hashing\\HashServiceProvider', - 12 => 'Illuminate\\Mail\\MailServiceProvider', - 13 => 'Illuminate\\Notifications\\NotificationServiceProvider', - 14 => 'Illuminate\\Pagination\\PaginationServiceProvider', - 15 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 16 => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 17 => 'Illuminate\\Queue\\QueueServiceProvider', - 18 => 'Illuminate\\Redis\\RedisServiceProvider', - 19 => 'Illuminate\\Session\\SessionServiceProvider', - 20 => 'Illuminate\\Translation\\TranslationServiceProvider', - 21 => 'Illuminate\\Validation\\ValidationServiceProvider', - 22 => 'Illuminate\\View\\ViewServiceProvider', - 23 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', - 24 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', - 25 => 'LaravelDoctrine\\ACL\\AclServiceProvider', - ), - 'eager' => - array ( - 0 => 'Illuminate\\Auth\\AuthServiceProvider', - 1 => 'Illuminate\\Cookie\\CookieServiceProvider', - 2 => 'Illuminate\\Database\\DatabaseServiceProvider', - 3 => 'Illuminate\\Encryption\\EncryptionServiceProvider', - 4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', - 5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', - 6 => 'Illuminate\\Notifications\\NotificationServiceProvider', - 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', - 8 => 'Illuminate\\Session\\SessionServiceProvider', - 9 => 'Illuminate\\View\\ViewServiceProvider', - 10 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', - 11 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', - 12 => 'LaravelDoctrine\\ACL\\AclServiceProvider', - ), - 'deferred' => - array ( - 'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', - 'cache' => 'Illuminate\\Cache\\CacheServiceProvider', - 'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider', - 'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider', - 'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider', - 'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider', - 'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Concurrency\\Console\\InvokeSerializedClosureCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\PruneStaleTagsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleInterruptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StorageUnlinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ApiInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\BroadcastingInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ChannelListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ClassMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnumMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\InterfaceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\JobMiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\LangPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\TraitMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Migrations\\Migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Concurrency\\ConcurrencyManager' => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', - 'hash' => 'Illuminate\\Hashing\\HashServiceProvider', - 'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider', - 'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider', - 'mailer' => 'Illuminate\\Mail\\MailServiceProvider', - 'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider', - 'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 'pipeline' => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 'queue' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider', - 'redis' => 'Illuminate\\Redis\\RedisServiceProvider', - 'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider', - 'translator' => 'Illuminate\\Translation\\TranslationServiceProvider', - 'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider', - 'validator' => 'Illuminate\\Validation\\ValidationServiceProvider', - 'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider', - 'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => 'Illuminate\\Validation\\ValidationServiceProvider', - ), - 'when' => - array ( - 'Illuminate\\Broadcasting\\BroadcastServiceProvider' => - array ( - ), - 'Illuminate\\Bus\\BusServiceProvider' => - array ( - ), - 'Illuminate\\Cache\\CacheServiceProvider' => - array ( - ), - 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' => - array ( - ), - 'Illuminate\\Concurrency\\ConcurrencyServiceProvider' => - array ( - ), - 'Illuminate\\Hashing\\HashServiceProvider' => - array ( - ), - 'Illuminate\\Mail\\MailServiceProvider' => - array ( - ), - 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' => - array ( - ), - 'Illuminate\\Pipeline\\PipelineServiceProvider' => - array ( - ), - 'Illuminate\\Queue\\QueueServiceProvider' => - array ( - ), - 'Illuminate\\Redis\\RedisServiceProvider' => - array ( - ), - 'Illuminate\\Translation\\TranslationServiceProvider' => - array ( - ), - 'Illuminate\\Validation\\ValidationServiceProvider' => - array ( - ), - ), -); \ No newline at end of file + + [ + 0 => 'Illuminate\\Auth\\AuthServiceProvider', + 1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 2 => 'Illuminate\\Bus\\BusServiceProvider', + 3 => 'Illuminate\\Cache\\CacheServiceProvider', + 4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 5 => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', + 6 => 'Illuminate\\Cookie\\CookieServiceProvider', + 7 => 'Illuminate\\Database\\DatabaseServiceProvider', + 8 => 'Illuminate\\Encryption\\EncryptionServiceProvider', + 9 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', + 10 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', + 11 => 'Illuminate\\Hashing\\HashServiceProvider', + 12 => 'Illuminate\\Mail\\MailServiceProvider', + 13 => 'Illuminate\\Notifications\\NotificationServiceProvider', + 14 => 'Illuminate\\Pagination\\PaginationServiceProvider', + 15 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 16 => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 17 => 'Illuminate\\Queue\\QueueServiceProvider', + 18 => 'Illuminate\\Redis\\RedisServiceProvider', + 19 => 'Illuminate\\Session\\SessionServiceProvider', + 20 => 'Illuminate\\Translation\\TranslationServiceProvider', + 21 => 'Illuminate\\Validation\\ValidationServiceProvider', + 22 => 'Illuminate\\View\\ViewServiceProvider', + 23 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', + 24 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', + 25 => 'LaravelDoctrine\\ACL\\AclServiceProvider', + ], + 'eager' => + [ + 0 => 'Illuminate\\Auth\\AuthServiceProvider', + 1 => 'Illuminate\\Cookie\\CookieServiceProvider', + 2 => 'Illuminate\\Database\\DatabaseServiceProvider', + 3 => 'Illuminate\\Encryption\\EncryptionServiceProvider', + 4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', + 5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', + 6 => 'Illuminate\\Notifications\\NotificationServiceProvider', + 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', + 8 => 'Illuminate\\Session\\SessionServiceProvider', + 9 => 'Illuminate\\View\\ViewServiceProvider', + 10 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', + 11 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', + 12 => 'LaravelDoctrine\\ACL\\AclServiceProvider', + ], + 'deferred' => + [ + 'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', + 'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', + 'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', + 'cache' => 'Illuminate\\Cache\\CacheServiceProvider', + 'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider', + 'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider', + 'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider', + 'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider', + 'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Concurrency\\Console\\InvokeSerializedClosureCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\PruneStaleTagsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Console\\Scheduling\\ScheduleInterruptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StorageUnlinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ApiInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\BroadcastingInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ChannelListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ClassMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConfigPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EnumMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\InterfaceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\JobMiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\LangPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\TraitMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Foundation\\Console\\ViewMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Migrations\\Migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', + 'Illuminate\\Concurrency\\ConcurrencyManager' => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', + 'hash' => 'Illuminate\\Hashing\\HashServiceProvider', + 'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider', + 'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider', + 'mailer' => 'Illuminate\\Mail\\MailServiceProvider', + 'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider', + 'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', + 'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 'pipeline' => 'Illuminate\\Pipeline\\PipelineServiceProvider', + 'queue' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider', + 'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider', + 'redis' => 'Illuminate\\Redis\\RedisServiceProvider', + 'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider', + 'translator' => 'Illuminate\\Translation\\TranslationServiceProvider', + 'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider', + 'validator' => 'Illuminate\\Validation\\ValidationServiceProvider', + 'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider', + 'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => 'Illuminate\\Validation\\ValidationServiceProvider', + ], + 'when' => + [ + 'Illuminate\\Broadcasting\\BroadcastServiceProvider' => + [], + 'Illuminate\\Bus\\BusServiceProvider' => + [], + 'Illuminate\\Cache\\CacheServiceProvider' => + [], + 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' => + [], + 'Illuminate\\Concurrency\\ConcurrencyServiceProvider' => + [], + 'Illuminate\\Hashing\\HashServiceProvider' => + [], + 'Illuminate\\Mail\\MailServiceProvider' => + [], + 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' => + [], + 'Illuminate\\Pipeline\\PipelineServiceProvider' => + [], + 'Illuminate\\Queue\\QueueServiceProvider' => + [], + 'Illuminate\\Redis\\RedisServiceProvider' => + [], + 'Illuminate\\Translation\\TranslationServiceProvider' => + [], + 'Illuminate\\Validation\\ValidationServiceProvider' => + [], + ], +]; diff --git a/workbench/bootstrap/providers.php b/workbench/bootstrap/providers.php index a18fdb8..d216fbd 100644 --- a/workbench/bootstrap/providers.php +++ b/workbench/bootstrap/providers.php @@ -1,11 +1,12 @@ [ 'driver' => 'doctrine', - 'entity' => LaravelDoctrine\ACL\Permissions\Permission::class, + 'entity' => Permission::class, 'list' => [ 'role.attach', 'role.detach', @@ -26,7 +32,7 @@ |-------------------------------------------------------------------------- */ 'roles' => [ - 'entity' => Workbench\App\Entities\Role::class, + 'entity' => Role::class, ], /* @@ -35,6 +41,6 @@ |-------------------------------------------------------------------------- */ 'organisations' => [ - 'entity' => Workbench\App\Entities\Organisation::class, + 'entity' => Organisation::class, ], -]; \ No newline at end of file +]; diff --git a/workbench/config/auth.php b/workbench/config/auth.php index a6d8521..2c1866e 100644 --- a/workbench/config/auth.php +++ b/workbench/config/auth.php @@ -1,5 +1,7 @@ [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'), 'persistent' => env('REDIS_PERSISTENT', false), ], diff --git a/workbench/config/doctrine.php b/workbench/config/doctrine.php index ad02498..0e73e5a 100644 --- a/workbench/config/doctrine.php +++ b/workbench/config/doctrine.php @@ -1,5 +1,9 @@ env('APP_DEBUG', false), 'meta' => env('DOCTRINE_METADATA', 'attributes'), 'connection' => env('DB_CONNECTION', 'sqlite'), - 'paths' => [ - app_path('Entities') - ], + 'paths' => [app_path('Entities')], - 'repository' => Doctrine\ORM\EntityRepository::class, + 'repository' => EntityRepository::class, 'proxies' => [ 'namespace' => 'DoctrineProxies', 'path' => storage_path('proxies'), - 'auto_generate' => env('DOCTRINE_PROXY_AUTOGENERATE', false) + 'auto_generate' => env('DOCTRINE_PROXY_AUTOGENERATE', false), ], /* @@ -52,7 +54,7 @@ */ 'events' => [ 'listeners' => [], - 'subscribers' => [] + 'subscribers' => [], ], 'filters' => [], @@ -79,18 +81,14 @@ | https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types-in-the-schematool |-------------------------------------------------------------------------- */ - 'mapping_types' => [ - //'enum' => 'string' - ], + 'mapping_types' => [], /** * References: * https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/architecture.html#middlewares */ - 'middlewares' => [ - // Doctrine\DBAL\Logging\Middleware::class - ] - ] + 'middlewares' => [], + ], ], /* |-------------------------------------------------------------------------- @@ -103,17 +101,7 @@ | laravel-doctrine/extensions in your composer.json | */ - 'extensions' => [ - //LaravelDoctrine\Extensions\Timestamps\TimestampableExtension::class, - //LaravelDoctrine\Extensions\SoftDeletes\SoftDeleteableExtension::class, - //LaravelDoctrine\Extensions\Sluggable\SluggableExtension::class, - //LaravelDoctrine\Extensions\Sortable\SortableExtension::class, - //LaravelDoctrine\Extensions\Tree\TreeExtension::class, - //LaravelDoctrine\Extensions\Loggable\LoggableExtension::class, - //LaravelDoctrine\Extensions\Blameable\BlameableExtension::class, - //LaravelDoctrine\Extensions\IpTraceable\IpTraceableExtension::class, - //LaravelDoctrine\Extensions\Translatable\TranslatableExtension::class - ], + 'extensions' => [], /* |-------------------------------------------------------------------------- | Doctrine custom types @@ -122,8 +110,7 @@ | Create a custom or override a Doctrine Type |-------------------------------------------------------------------------- */ - 'custom_types' => [ - ], + 'custom_types' => [], /* |-------------------------------------------------------------------------- | DQL custom datetime functions @@ -147,9 +134,7 @@ | Register custom hydrators |-------------------------------------------------------------------------- */ - 'custom_hydration_modes' => [ - // e.g. 'hydrationModeName' => MyHydrator::class, - ], + 'custom_hydration_modes' => [], /* |-------------------------------------------------------------------------- | Cache @@ -188,9 +173,7 @@ | laravel-doctrine/extensions in your composer.json | */ - 'gedmo' => [ - 'all_mappings' => false - ], + 'gedmo' => ['all_mappings' => false], /* |-------------------------------------------------------------------------- | Validation @@ -209,7 +192,5 @@ | Doctrine notifications channel | */ - 'notifications' => [ - 'channel' => 'database' - ] + 'notifications' => ['channel' => 'database'], ]; diff --git a/workbench/config/migrations.php b/workbench/config/migrations.php index 216e18f..bd2b2dc 100644 --- a/workbench/config/migrations.php +++ b/workbench/config/migrations.php @@ -39,11 +39,11 @@ | filter all tables. | */ - 'schema_filter' => '/^(?!password_resets|failed_jobs).*$/' + 'schema_filter' => '/^(?!password_resets|failed_jobs).*$/', ], 'migrations_paths' => [ - 'Database\\Migrations' => database_path('migrations') + 'Database\\Migrations' => database_path('migrations'), ], /* diff --git a/workbench/config/session.php b/workbench/config/session.php index e9b535a..1917915 100644 --- a/workbench/config/session.php +++ b/workbench/config/session.php @@ -1,5 +1,7 @@ env( 'SESSION_COOKIE', - Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + Str::slug(env('APP_NAME', 'laravel'), '_') . '_session', ), /* diff --git a/workbench/config/view.php b/workbench/config/view.php index 22b8a18..528cbf4 100644 --- a/workbench/config/view.php +++ b/workbench/config/view.php @@ -1,5 +1,7 @@ env( 'VIEW_COMPILED_PATH', - realpath(storage_path('framework/views')) + realpath(storage_path('framework/views')), ), ]; diff --git a/workbench/database/factories/OrganisationFactory.php b/workbench/database/factories/OrganisationFactory.php index 3e49b90..04ed19b 100644 --- a/workbench/database/factories/OrganisationFactory.php +++ b/workbench/database/factories/OrganisationFactory.php @@ -1,9 +1,14 @@ define(Organisation::class, function(Faker\Generator $faker, array $attributes) { + +$factory->define(Organisation::class, static function (Generator $faker, array $attributes) { return [ 'name' => $attributes['name'] ?? $faker->unique()->company, ]; diff --git a/workbench/database/factories/PermissionFactory.php b/workbench/database/factories/PermissionFactory.php index f09e5ad..c5b4721 100644 --- a/workbench/database/factories/PermissionFactory.php +++ b/workbench/database/factories/PermissionFactory.php @@ -1,12 +1,16 @@ define(Permission::class, static function (Generator $faker, array $attributes = []) { return [ 'name' => $attributes['name'] ?? $faker->unique()->word . '-' . $faker->unique()->word, @@ -14,19 +18,13 @@ }); $factory->defineAs(Permission::class, 'view', static function () { - return [ - 'name' => 'view', - ]; + return ['name' => 'view']; }); $factory->defineAs(Permission::class, 'edit', static function () { - return [ - 'name' => 'edit', - ]; + return ['name' => 'edit']; }); $factory->defineAs(Permission::class, 'delete', static function () { - return [ - 'name' => 'delete', - ]; + return ['name' => 'delete']; }); diff --git a/workbench/database/factories/RoleFactory.php b/workbench/database/factories/RoleFactory.php index c277d2a..4c9eeae 100644 --- a/workbench/database/factories/RoleFactory.php +++ b/workbench/database/factories/RoleFactory.php @@ -1,12 +1,16 @@ define(Role::class, static function (Generator $faker, array $attributes = []) { return [ 'name' => $attributes['name'] ?? $faker->unique()->word . '-' . $faker->unique()->word, @@ -14,14 +18,9 @@ }); $factory->defineAs(Role::class, 'admin', static function () { - return [ - 'name' => 'admin', - ]; + return ['name' => 'admin']; }); $factory->defineAs(Role::class, 'user', static function () { - return [ - 'name' => 'user', - ]; + return ['name' => 'user']; }); - diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php index 11a26bf..5a67bac 100644 --- a/workbench/database/factories/UserFactory.php +++ b/workbench/database/factories/UserFactory.php @@ -1,12 +1,16 @@ define(User::class, static function (Generator $faker, array $attributes = []) { return [ 'name' => $faker->name(), diff --git a/workbench/database/factories/UserJsonPermissions.php b/workbench/database/factories/UserJsonPermissions.php index b1527b9..fc44090 100644 --- a/workbench/database/factories/UserJsonPermissions.php +++ b/workbench/database/factories/UserJsonPermissions.php @@ -1,12 +1,16 @@ define(UserJsonPermissions::class, static function (Generator $faker, array $attributes = []) { return [ 'name' => $attributes['name'] ?? $faker->name(), diff --git a/workbench/database/factories/UserSingleOrgFactory.php b/workbench/database/factories/UserSingleOrgFactory.php index d4e6c8c..d825f04 100644 --- a/workbench/database/factories/UserSingleOrgFactory.php +++ b/workbench/database/factories/UserSingleOrgFactory.php @@ -1,12 +1,16 @@ define(UserSingleOrg::class, static function (Generator $faker, array $attributes = []) { return [ 'name' => $attributes['name'] ?? $faker->name(), diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php index ce9bd15..17e1f56 100644 --- a/workbench/database/seeders/DatabaseSeeder.php +++ b/workbench/database/seeders/DatabaseSeeder.php @@ -1,5 +1,7 @@ comment(Inspiring::quote()); })->purpose('Display an inspiring quote')->hourly(); diff --git a/workbench/routes/web.php b/workbench/routes/web.php index 86a06c5..f3f93c1 100644 --- a/workbench/routes/web.php +++ b/workbench/routes/web.php @@ -1,7 +1,9 @@ Date: Sun, 27 Apr 2025 15:13:57 +0300 Subject: [PATCH 4/9] refactor: use same approach for config as ORM --- docs/permissions.rst | 2 +- docs/usage.rst | 2 +- src/AclServiceProvider.php | 9 +- .../ConfigPermissionsProvider.php | 22 ++++ .../DoctrinePermissionsProvider.php | 56 ++++++++++ src/Configurations/PermissionsProvider.php | 14 +++ src/Organisations/BelongsToOrganisation.php | 16 +-- src/{Permissions => }/PermissionManager.php | 8 +- src/Permissions/ConfigPermissionDriver.php | 22 ---- src/Permissions/DoctrinePermissionDriver.php | 79 ------------- src/Permissions/Driver/Config.php | 23 ++++ src/Permissions/Driver/Doctrine.php | 27 +++++ .../{ => Driver}/PermissionDriver.php | 2 +- src/Permissions/HasPermissions.php | 12 +- src/Permissions/Manager.php | 40 ------- .../DoctrinePermissionsProviderTest.php | 56 ++++++++++ .../PermissionManagerTest.php | 45 +++++++- tests/Integration/AclServiceProviderTest.php | 28 ++++- .../ConfigPermissionDriverTest.php | 36 ------ .../DoctrinePermissionDriverTest.php | 105 ------------------ .../Driver/ConfigPermissionDriverTest.php | 20 ++++ .../Driver/DoctrinePermissionDriverTest.php | 27 +++++ workbench/app/Entities/Role.php | 4 +- workbench/app/Entities/User.php | 4 +- 24 files changed, 339 insertions(+), 320 deletions(-) create mode 100644 src/Configurations/ConfigPermissionsProvider.php create mode 100644 src/Configurations/DoctrinePermissionsProvider.php create mode 100644 src/Configurations/PermissionsProvider.php rename src/{Permissions => }/PermissionManager.php (89%) delete mode 100644 src/Permissions/ConfigPermissionDriver.php delete mode 100644 src/Permissions/DoctrinePermissionDriver.php create mode 100644 src/Permissions/Driver/Config.php create mode 100644 src/Permissions/Driver/Doctrine.php rename src/Permissions/{ => Driver}/PermissionDriver.php (75%) delete mode 100644 src/Permissions/Manager.php create mode 100644 tests/Configurations/DoctrinePermissionsProviderTest.php rename tests/{Permissions => Configurations}/PermissionManagerTest.php (69%) delete mode 100644 tests/Permissions/ConfigPermissionDriverTest.php delete mode 100644 tests/Permissions/DoctrinePermissionDriverTest.php create mode 100644 tests/Permissions/Driver/ConfigPermissionDriverTest.php create mode 100644 tests/Permissions/Driver/DoctrinePermissionDriverTest.php diff --git a/docs/permissions.rst b/docs/permissions.rst index 6202aef..2866b98 100644 --- a/docs/permissions.rst +++ b/docs/permissions.rst @@ -36,7 +36,7 @@ Getting all permissions ~~~~~~~~~~~~~~~~~~~~~~~ You can get a list of all permissions with the -``LaravelDoctrine\ACL\Permissions\PermissionManager`` +``LaravelDoctrine\ACL\PermissionManager`` .. code:: php diff --git a/docs/usage.rst b/docs/usage.rst index e9c2df7..feabe5b 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -71,7 +71,7 @@ Use the `PermissionManager` to retrieve all permissions: .. code-block:: php - $manager = app(LaravelDoctrine\ACL\Permissions\PermissionManager::class); + $manager = app(LaravelDoctrine\ACL\PermissionManager::class); $manager->getAllPermissions(); diff --git a/src/AclServiceProvider.php b/src/AclServiceProvider.php index 245a91e..72f71db 100644 --- a/src/AclServiceProvider.php +++ b/src/AclServiceProvider.php @@ -8,16 +8,12 @@ use Illuminate\Support\ServiceProvider; use LaravelDoctrine\ACL\Contracts\HasPermissions; use LaravelDoctrine\ACL\Mappings\RegisterMappedEventSubscribers; -use LaravelDoctrine\ACL\Permissions\PermissionManager; use LaravelDoctrine\ORM\DoctrineManager; use const DIRECTORY_SEPARATOR; class AclServiceProvider extends ServiceProvider { - /** - * Register the service provider. - */ public function register(): void { $this->mergeConfig(); @@ -35,13 +31,13 @@ protected function registerDoctrineMappings(): void protected function registerPaths(): void { - $manager = $this->app->make(DoctrineManager::class); $permissionManager = $this->app->make(PermissionManager::class); if (! $permissionManager->useDefaultPermissionEntity()) { return; } + $manager = $this->app->make(DoctrineManager::class); $manager->addPaths([ __DIR__ . DIRECTORY_SEPARATOR . 'Permissions', ]); @@ -60,9 +56,6 @@ protected function registerGatePermissions(): void }); } - /** - * Merge config. - */ protected function mergeConfig(): void { $this->mergeConfigFrom( diff --git a/src/Configurations/ConfigPermissionsProvider.php b/src/Configurations/ConfigPermissionsProvider.php new file mode 100644 index 0000000..87dabfa --- /dev/null +++ b/src/Configurations/ConfigPermissionsProvider.php @@ -0,0 +1,22 @@ +config->get('acl.permissions.list', [])); + } +} diff --git a/src/Configurations/DoctrinePermissionsProvider.php b/src/Configurations/DoctrinePermissionsProvider.php new file mode 100644 index 0000000..88ca8e6 --- /dev/null +++ b/src/Configurations/DoctrinePermissionsProvider.php @@ -0,0 +1,56 @@ +getEntityManager(); + $metadata = $em->getClassMetadata($this->getPermissionClass()); + + return new Doctrine(new EntityRepository($em, $metadata)); + } + + protected function getPermissionClass(): string + { + $class = $this->config->get('acl.permissions.entity'); + + if (! $class) { + throw new RunTimeException( + 'Failed to configure doctrine permissions. No entity class provided.', + ); + } + + return $class; + } + + protected function getEntityManager(): EntityManagerInterface + { + $em = $this->registry->getManagerForClass($this->getPermissionClass()); + + if (! $em) { + throw new RunTimeException( + 'Failed to configure doctrine permissions.' + . ' No entity manager found for entity: ' . $this->getPermissionClass() . '.', + ); + } + + return $em; + } +} diff --git a/src/Configurations/PermissionsProvider.php b/src/Configurations/PermissionsProvider.php new file mode 100644 index 0000000..28d3a25 --- /dev/null +++ b/src/Configurations/PermissionsProvider.php @@ -0,0 +1,14 @@ +getOrganisations() as $o) { if ($this->getOrganisationName($org) === $o->getName()) { return true; @@ -51,8 +47,8 @@ public function belongsToOrganisation(OrganisationContract|string|array $org, bo return false; } - protected function getOrganisationName(OrganisationContract|string $org): string + protected function getOrganisationName(Organisation|string $org): string { - return $org instanceof OrganisationContract ? $org->getName() : $org; + return $org instanceof Organisation ? $org->getName() : $org; } } diff --git a/src/Permissions/PermissionManager.php b/src/PermissionManager.php similarity index 89% rename from src/Permissions/PermissionManager.php rename to src/PermissionManager.php index 31fe330..f488619 100644 --- a/src/Permissions/PermissionManager.php +++ b/src/PermissionManager.php @@ -2,10 +2,12 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Permissions; +namespace LaravelDoctrine\ACL; use Illuminate\Support\Arr; use Illuminate\Support\Collection; +use LaravelDoctrine\ACL\Permissions\Permission; +use LaravelDoctrine\ORM\Configuration\Manager; use function is_array; use function is_numeric; @@ -55,12 +57,12 @@ public function getDefaultDriver(): string public function getNamespace(): string { - return __NAMESPACE__; + return __NAMESPACE__ . '\\Configurations'; } public function getClassSuffix(): string { - return 'PermissionDriver'; + return 'PermissionsProvider'; } public function useDefaultPermissionEntity(): bool diff --git a/src/Permissions/ConfigPermissionDriver.php b/src/Permissions/ConfigPermissionDriver.php deleted file mode 100644 index 7f97090..0000000 --- a/src/Permissions/ConfigPermissionDriver.php +++ /dev/null @@ -1,22 +0,0 @@ -repository->get('acl.permissions.list', []), - ); - } -} diff --git a/src/Permissions/DoctrinePermissionDriver.php b/src/Permissions/DoctrinePermissionDriver.php deleted file mode 100644 index 4672e4e..0000000 --- a/src/Permissions/DoctrinePermissionDriver.php +++ /dev/null @@ -1,79 +0,0 @@ -getRepository()) { - try { - $permissions = $this->getRepository()->findAll(); - } catch (TableNotFoundException) { - $permissions = []; - } - - return new Collection( - $this->mapToArrayOfNames($permissions), - ); - } - - return new Collection(); - } - - /** - * @param array $permissions - * - * @return array - */ - protected function mapToArrayOfNames(array $permissions): array - { - $permissions = array_map(static function (Permission $permission) { - return $permission->getName(); - }, $permissions); - - return $permissions; - } - - protected function getEntityName(): string|null - { - return $this->config->get('acl.permissions.entity'); - } - - protected function getEntityManager(): EntityManagerInterface|null - { - return $this->registry->getManagerForClass( - $this->getEntityName(), - ); - } - - protected function getRepository(): EntityRepository|null - { - if ($this->getEntityManager()) { - $metadata = $this->getEntityManager()->getClassMetadata($this->getEntityName()); - - return new EntityRepository( - $this->getEntityManager(), - $metadata, - ); - } - - return null; - } -} diff --git a/src/Permissions/Driver/Config.php b/src/Permissions/Driver/Config.php new file mode 100644 index 0000000..be3a0c5 --- /dev/null +++ b/src/Permissions/Driver/Config.php @@ -0,0 +1,23 @@ + */ + public function __construct(protected array $permissions) + { + $this->collection = new Collection($this->permissions); + } + + public function getAllPermissions(): Collection + { + return $this->collection; + } +} diff --git a/src/Permissions/Driver/Doctrine.php b/src/Permissions/Driver/Doctrine.php new file mode 100644 index 0000000..446e9b2 --- /dev/null +++ b/src/Permissions/Driver/Doctrine.php @@ -0,0 +1,27 @@ +repository->findAll(); + $permissions = array_map(static fn (Permission $permission) => $permission->getName(), $permissions); + + return new Collection($permissions); + } +} diff --git a/src/Permissions/PermissionDriver.php b/src/Permissions/Driver/PermissionDriver.php similarity index 75% rename from src/Permissions/PermissionDriver.php rename to src/Permissions/Driver/PermissionDriver.php index 5389f9c..c3853dc 100644 --- a/src/Permissions/PermissionDriver.php +++ b/src/Permissions/Driver/PermissionDriver.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Permissions; +namespace LaravelDoctrine\ACL\Permissions\Driver; use Illuminate\Support\Collection; diff --git a/src/Permissions/HasPermissions.php b/src/Permissions/HasPermissions.php index e904c6c..25f8936 100644 --- a/src/Permissions/HasPermissions.php +++ b/src/Permissions/HasPermissions.php @@ -5,14 +5,14 @@ namespace LaravelDoctrine\ACL\Permissions; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesHasRoles; -use LaravelDoctrine\ACL\Contracts\Permission as PermissionContract; +use LaravelDoctrine\ACL\Contracts\HasRoles; +use LaravelDoctrine\ACL\Contracts\Permission; use function is_array; trait HasPermissions { - public function hasPermissionTo(PermissionContract|string|array $name, bool $requireAll = false): bool + public function hasPermissionTo(Permission|string|array $name, bool $requireAll = false): bool { if (is_array($name)) { foreach ($name as $n) { @@ -38,7 +38,7 @@ public function hasPermissionTo(PermissionContract|string|array $name, bool $req } } - if ($this instanceof HasRolesHasRoles) { + if ($this instanceof HasRoles) { foreach ($this->getRoles() as $role) { if (! ($role instanceof HasPermissionsContract)) { continue; @@ -53,8 +53,8 @@ public function hasPermissionTo(PermissionContract|string|array $name, bool $req return false; } - protected function getPermissionName(PermissionContract|string $permission): string + protected function getPermissionName(Permission|string $permission): string { - return $permission instanceof PermissionContract ? $permission->getName() : $permission; + return $permission instanceof Permission ? $permission->getName() : $permission; } } diff --git a/src/Permissions/Manager.php b/src/Permissions/Manager.php deleted file mode 100644 index 5620452..0000000 --- a/src/Permissions/Manager.php +++ /dev/null @@ -1,40 +0,0 @@ - $settings - * - * @throws DriverNotFound - */ - protected function createDriver(string $driver, array $settings = [], bool $resolve = true): mixed - { - $class = $this->getNamespace() . '\\' . Str::studly($driver) . $this->getClassSuffix(); - - // We'll check to see if a creator method exists for the given driver. If not we - // will check for a custom driver creator, which allows developers to create - // drivers using their own customized driver creator Closure to create it. - if (isset($this->customCreators[$driver])) { - return $this->callCustomCreator($driver); - } - - if (class_exists($class)) { - return $this->container->make($class); - } - - throw new DriverNotFound(sprintf('Driver [%s] not supported.', $driver)); - } -} diff --git a/tests/Configurations/DoctrinePermissionsProviderTest.php b/tests/Configurations/DoctrinePermissionsProviderTest.php new file mode 100644 index 0000000..788caaf --- /dev/null +++ b/tests/Configurations/DoctrinePermissionsProviderTest.php @@ -0,0 +1,56 @@ +shouldReceive('get')->with('acl.permissions.entity')->andReturn(null); + + $provider = new DoctrinePermissionsProvider($registry, $config); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to configure doctrine permissions. No entity class provided.'); + // Call protected method via reflection + $reflection = new ReflectionClass($provider); + $method = $reflection->getMethod('getPermissionClass'); + $method->setAccessible(true); + $method->invoke($provider); + } + + public function testThrowsExceptionWhenNoEntityManagerFound(): void + { + $registry = m::mock(ManagerRegistry::class); + $config = m::mock(Repository::class); + $config->shouldReceive('get')->with('acl.permissions.entity')->andReturn('Some\\Entity\\Class'); + $registry->shouldReceive('getManagerForClass')->with('Some\\Entity\\Class')->andReturn(null); + + $provider = new DoctrinePermissionsProvider($registry, $config); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to configure doctrine permissions. No entity manager found for entity: Some\\Entity\\Class.'); + // Call protected method via reflection + $reflection = new ReflectionClass($provider); + $method = $reflection->getMethod('getEntityManager'); + $method->setAccessible(true); + $method->invoke($provider); + } +} diff --git a/tests/Permissions/PermissionManagerTest.php b/tests/Configurations/PermissionManagerTest.php similarity index 69% rename from tests/Permissions/PermissionManagerTest.php rename to tests/Configurations/PermissionManagerTest.php index c9b3658..1735d9c 100644 --- a/tests/Permissions/PermissionManagerTest.php +++ b/tests/Configurations/PermissionManagerTest.php @@ -2,17 +2,21 @@ declare(strict_types=1); -namespace Tests\Permissions; +namespace Tests\Configurations; +use Doctrine\Persistence\ManagerRegistry; use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\Container\Container; use Illuminate\Support\Collection; +use LaravelDoctrine\ACL\Configurations\DoctrinePermissionsProvider; +use LaravelDoctrine\ACL\PermissionManager; +use LaravelDoctrine\ACL\Permissions\Driver\PermissionDriver; use LaravelDoctrine\ACL\Permissions\Permission; -use LaravelDoctrine\ACL\Permissions\PermissionDriver; -use LaravelDoctrine\ACL\Permissions\PermissionManager; use LaravelDoctrine\ORM\Exceptions\DriverNotFound; use Mockery as m; use PHPUnit\Framework\TestCase; +use ReflectionClass; +use RuntimeException; class PermissionManagerTest extends TestCase { @@ -135,4 +139,39 @@ public function testThrowsDriverNotFoundException(): void // Do not extend with any driver, so the requested driver does not exist $manager->driver('nonexistent'); } + + public function testDoctrinePermissionsProviderThrowsExceptionWhenNoEntityClassProvided(): void + { + $registry = m::mock(ManagerRegistry::class); + $config = m::mock(Repository::class); + $config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(null); + + $provider = new DoctrinePermissionsProvider($registry, $config); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to configure doctrine permissions. No entity class provided.'); + // Call protected method via reflection + $reflection = new ReflectionClass($provider); + $method = $reflection->getMethod('getPermissionClass'); + $method->setAccessible(true); + $method->invoke($provider); + } + + public function testDoctrinePermissionsProviderThrowsExceptionWhenNoEntityManagerFound(): void + { + $registry = m::mock(ManagerRegistry::class); + $config = m::mock(Repository::class); + $config->shouldReceive('get')->with('acl.permissions.entity')->andReturn('Some\\Entity\\Class'); + $registry->shouldReceive('getManagerForClass')->with('Some\\Entity\\Class')->andReturn(null); + + $provider = new DoctrinePermissionsProvider($registry, $config); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to configure doctrine permissions. No entity manager found for entity: Some\\Entity\\Class.'); + // Call protected method via reflection + $reflection = new ReflectionClass($provider); + $method = $reflection->getMethod('getEntityManager'); + $method->setAccessible(true); + $method->invoke($provider); + } } diff --git a/tests/Integration/AclServiceProviderTest.php b/tests/Integration/AclServiceProviderTest.php index 5d8722b..200cb30 100644 --- a/tests/Integration/AclServiceProviderTest.php +++ b/tests/Integration/AclServiceProviderTest.php @@ -5,7 +5,11 @@ namespace Tests\Integration; use Illuminate\Contracts\Auth\Access\Gate; -use LaravelDoctrine\ACL\Permissions\PermissionManager; +use LaravelDoctrine\ACL\AclServiceProvider; +use LaravelDoctrine\ACL\PermissionManager; +use LaravelDoctrine\ORM\DoctrineManager; +use Mockery; +use ReflectionClass; use Tests\TestCase; use Workbench\App\Entities\User; @@ -45,4 +49,26 @@ public function testNoPermissionsDefinedWhenManagerReturnsEmpty(): void $this->assertFalse($gate->has('any.permission')); } + + public function testRegisterPathsSkipsWhenNotUsingDefaultPermissionEntity(): void + { + // Arrange: Mock PermissionManager + $manager = Mockery::mock(PermissionManager::class); + $manager->shouldReceive('useDefaultPermissionEntity')->once()->andReturn(false); + + // We expect that DoctrineManager::addPaths should NOT be called + $doctrineManager = Mockery::mock(DoctrineManager::class); + $doctrineManager->shouldNotReceive('addPaths'); + + $this->app->instance(PermissionManager::class, $manager); + $this->app->instance(DoctrineManager::class, $doctrineManager); + + // Act: Call registerPaths via reflection + $provider = $this->app->getProvider(AclServiceProvider::class); + $reflection = new ReflectionClass($provider); + $method = $reflection->getMethod('registerPaths'); + $method->setAccessible(true); + + $this->assertNull($method->invoke($provider)); + } } diff --git a/tests/Permissions/ConfigPermissionDriverTest.php b/tests/Permissions/ConfigPermissionDriverTest.php deleted file mode 100644 index bfd5346..0000000 --- a/tests/Permissions/ConfigPermissionDriverTest.php +++ /dev/null @@ -1,36 +0,0 @@ -config = m::mock(Repository::class); - $this->driver = new ConfigPermissionDriver($this->config); - } - - public function testCanGetAllPermissions(): void - { - $this->config->shouldReceive('get')->with('acl.permissions.list', [])->once()->andReturn(['mocked']); - - $permissions = $this->driver->getAllPermissions(); - $this->assertInstanceOf(Collection::class, $permissions); - $this->assertTrue($permissions->contains('mocked')); - } -} diff --git a/tests/Permissions/DoctrinePermissionDriverTest.php b/tests/Permissions/DoctrinePermissionDriverTest.php deleted file mode 100644 index 3c44917..0000000 --- a/tests/Permissions/DoctrinePermissionDriverTest.php +++ /dev/null @@ -1,105 +0,0 @@ -config = m::mock(Repository::class); - $this->registry = m::mock(ManagerRegistry::class); - $this->em = m::mock(EntityManagerInterface::class); - $this->unitOfWork = m::mock(UnitOfWork::class); - $this->entityPersister = m::mock(EntityPersister::class); - $this->driver = new DoctrinePermissionDriver($this->registry, $this->config); - } - - protected function tearDown(): void - { - m::close(); - } - - public function testNoEntityManagerFound(): void - { - $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); - - $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn(null); - - $collection = $this->driver->getAllPermissions(); - $this->assertInstanceOf(Collection::class, $collection); - $this->assertTrue($collection->isEmpty()); - } - - public function testCanGetAllPermissions(): void - { - $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); - - $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn($this->em); - - $this->em->shouldReceive('getUnitOfWork')->andReturn($this->unitOfWork); - $this->unitOfWork->shouldReceive('getEntityPersister')->with(Permission::class)->andReturn($this->entityPersister); - $this->entityPersister->shouldReceive('loadAll')->andReturn([ - new Permission('mocked'), - ]); - - $meta = new ClassMetadata(Permission::class); - $meta->table = ['name' => 'permissions']; - $this->em->shouldReceive('getClassMetadata')->andReturn($meta); - - $permissions = $this->driver->getAllPermissions(); - $this->assertInstanceOf(Collection::class, $permissions); - $this->assertTrue($permissions->contains('mocked')); - } - - public function testShouldNotFailWhenTableDoesNotExist(): void - { - $this->config->shouldReceive('get')->with('acl.permissions.entity')->andReturn(Permission::class); - - $this->registry->shouldReceive('getManagerForClass')->with(Permission::class)->andReturn($this->em); - - $this->em->shouldReceive('getUnitOfWork')->andReturn($this->unitOfWork); - $this->unitOfWork->shouldReceive('getEntityPersister')->with(Permission::class)->andReturn($this->entityPersister); - - // DBAL 3 removed MysqliException - $this->entityPersister->shouldReceive('loadAll')->andThrow(new TableNotFoundException( - new ConnectionFailed('Table not found'), - null, - )); - - $meta = new ClassMetadata(Permission::class); - $meta->table = ['name' => 'permissions']; - $this->em->shouldReceive('getClassMetadata')->andReturn($meta); - - $permissions = $this->driver->getAllPermissions(); - $this->assertInstanceOf(Collection::class, $permissions); - $this->assertTrue($permissions->isEmpty()); - } -} diff --git a/tests/Permissions/Driver/ConfigPermissionDriverTest.php b/tests/Permissions/Driver/ConfigPermissionDriverTest.php new file mode 100644 index 0000000..d750c06 --- /dev/null +++ b/tests/Permissions/Driver/ConfigPermissionDriverTest.php @@ -0,0 +1,20 @@ +assertTrue($emptyConfig->getAllPermissions()->isEmpty()); + + $config = new Config(['mocked']); + $this->assertTrue($config->getAllPermissions()->contains('mocked')); + } +} diff --git a/tests/Permissions/Driver/DoctrinePermissionDriverTest.php b/tests/Permissions/Driver/DoctrinePermissionDriverTest.php new file mode 100644 index 0000000..be2f6dd --- /dev/null +++ b/tests/Permissions/Driver/DoctrinePermissionDriverTest.php @@ -0,0 +1,27 @@ +shouldReceive('findAll')->andReturn([ + new Permission('mocked'), + ]); + + $driver = new Doctrine($repository); + + $permissions = $driver->getAllPermissions(); + $this->assertTrue($permissions->contains('mocked')); + } +} diff --git a/workbench/app/Entities/Role.php b/workbench/app/Entities/Role.php index 09633c6..6637313 100644 --- a/workbench/app/Entities/Role.php +++ b/workbench/app/Entities/Role.php @@ -48,13 +48,13 @@ public function getId(): int|null return $this->id; } - /** @return Collection */ + /** @return Collection */ public function getPermissions(): Collection { return $this->permissions; } - /** @param Collection|string[] $permissions */ + /** @param Collection|Permission[] $permissions */ public function setPermissions(Collection|array $permissions): self { $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; diff --git a/workbench/app/Entities/User.php b/workbench/app/Entities/User.php index 2f88b2e..8a9e493 100644 --- a/workbench/app/Entities/User.php +++ b/workbench/app/Entities/User.php @@ -80,13 +80,13 @@ public function setRoles(Collection|array $roles): self return $this; } - /** @return Collection */ + /** @return Collection */ public function getPermissions(): Collection { return $this->permissions; } - /** @param Collection|string[] $permissions */ + /** @param Collection|Permission[] $permissions */ public function setPermissions(Collection|array $permissions): self { $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; From 9392911fd3f3a646f10de70cd8664ca97dfa81b7 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Sun, 27 Apr 2025 15:23:18 +0300 Subject: [PATCH 5/9] refactor: improve mappings classes readability --- docs/organisations.rst | 6 +++--- docs/permissions.rst | 2 +- docs/roles.rst | 4 ++-- src/{Mappings => Attribute}/BelongsToOrganisation.php | 6 +++--- src/{Mappings => Attribute}/BelongsToOrganisations.php | 6 +++--- src/{Mappings => Attribute}/HasPermissions.php | 6 +++--- src/{Mappings => Attribute}/HasRoles.php | 6 +++--- src/{Mappings => Attribute}/MappingAttribute.php | 6 +++--- src/{Mappings => Attribute}/RelationAttribute.php | 8 ++------ src/Mappings/Builders/Builder.php | 2 +- src/Mappings/Builders/JsonArrayBuilder.php | 6 +++--- src/Mappings/Builders/ManyToManyBuilder.php | 6 +++--- src/Mappings/Builders/ManyToOneBuilder.php | 6 +++--- src/Mappings/RegisterMappedEventSubscribers.php | 9 +++++---- .../Subscribers/BelongsToOrganisationSubscriber.php | 4 ++-- .../Subscribers/BelongsToOrganisationsSubscriber.php | 4 ++-- src/Mappings/Subscribers/HasPermissionsSubscriber.php | 4 ++-- src/Mappings/Subscribers/HasRolesSubscriber.php | 4 ++-- src/Mappings/Subscribers/MappedEventSubscriber.php | 6 +++--- src/Permissions/Permission.php | 6 +++--- workbench/app/Entities/Role.php | 3 +-- workbench/app/Entities/User.php | 8 ++++---- workbench/app/Entities/UserJsonPermissions.php | 3 +-- workbench/app/Entities/UserSingleOrg.php | 6 +++--- 24 files changed, 61 insertions(+), 66 deletions(-) rename src/{Mappings => Attribute}/BelongsToOrganisation.php (82%) rename src/{Mappings => Attribute}/BelongsToOrganisations.php (83%) rename src/{Mappings => Attribute}/HasPermissions.php (86%) rename src/{Mappings => Attribute}/HasRoles.php (83%) rename src/{Mappings => Attribute}/MappingAttribute.php (51%) rename src/{Mappings => Attribute}/RelationAttribute.php (78%) diff --git a/docs/organisations.rst b/docs/organisations.rst index d81ac4e..0584753 100644 --- a/docs/organisations.rst +++ b/docs/organisations.rst @@ -16,7 +16,7 @@ you will have to create an entity that implements use Doctrine\ORM\Mapping as ORM; use LaravelDoctrine\ACL\Contracts\Organisation; - use LaravelDoctrine\ACL\Mappings as ACL; + use LaravelDoctrine\ACL\Attribute as ACL; #[ORM\Entity] class Team implements Organisation @@ -47,7 +47,7 @@ The User class should implement indexBy = $indexBy; } - public function getTargetEntity(Repository $config): string|null + public function getTargetEntity(Config $config): string|null { return $this->targetEntity ?: $config->get('acl.organisations.entity', 'Organisation'); } diff --git a/src/Mappings/BelongsToOrganisations.php b/src/Attribute/BelongsToOrganisations.php similarity index 83% rename from src/Mappings/BelongsToOrganisations.php rename to src/Attribute/BelongsToOrganisations.php index 0463ba9..c35e6b4 100644 --- a/src/Mappings/BelongsToOrganisations.php +++ b/src/Attribute/BelongsToOrganisations.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Mappings; +namespace LaravelDoctrine\ACL\Attribute; use Attribute; -use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Config\Repository as Config; #[Attribute(Attribute::TARGET_PROPERTY)] final class BelongsToOrganisations extends RelationAttribute @@ -27,7 +27,7 @@ public function __construct( $this->indexBy = $indexBy; } - public function getTargetEntity(Repository $config): string|null + public function getTargetEntity(Config $config): string|null { return $this->targetEntity ?: $config->get('acl.organisations.entity', 'Organisation'); } diff --git a/src/Mappings/HasPermissions.php b/src/Attribute/HasPermissions.php similarity index 86% rename from src/Mappings/HasPermissions.php rename to src/Attribute/HasPermissions.php index 314092d..ddd92a4 100644 --- a/src/Mappings/HasPermissions.php +++ b/src/Attribute/HasPermissions.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Mappings; +namespace LaravelDoctrine\ACL\Attribute; use Attribute; -use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Config\Repository as Config; #[Attribute(Attribute::TARGET_PROPERTY)] final class HasPermissions extends RelationAttribute @@ -27,7 +27,7 @@ public function __construct( $this->indexBy = $indexBy; } - public function getTargetEntity(Repository $config): string|null + public function getTargetEntity(Config $config): string|null { // Config driver has no target entity if ($config->get('acl.permissions.driver', 'config') === 'config') { diff --git a/src/Mappings/HasRoles.php b/src/Attribute/HasRoles.php similarity index 83% rename from src/Mappings/HasRoles.php rename to src/Attribute/HasRoles.php index 2ab5018..b04b7b9 100644 --- a/src/Mappings/HasRoles.php +++ b/src/Attribute/HasRoles.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Mappings; +namespace LaravelDoctrine\ACL\Attribute; use Attribute; -use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Config\Repository as Config; #[Attribute(Attribute::TARGET_PROPERTY)] final class HasRoles extends RelationAttribute @@ -27,7 +27,7 @@ public function __construct( $this->indexBy = $indexBy; } - public function getTargetEntity(Repository $config): string|null + public function getTargetEntity(Config $config): string|null { return $this->targetEntity ?: $config->get('acl.roles.entity', 'Role'); } diff --git a/src/Mappings/MappingAttribute.php b/src/Attribute/MappingAttribute.php similarity index 51% rename from src/Mappings/MappingAttribute.php rename to src/Attribute/MappingAttribute.php index 88b6b60..c8954d7 100644 --- a/src/Mappings/MappingAttribute.php +++ b/src/Attribute/MappingAttribute.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Mappings; +namespace LaravelDoctrine\ACL\Attribute; use Doctrine\ORM\Mapping\MappingAttribute as DoctrineMappingAttribute; -use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Config\Repository as Config; interface MappingAttribute extends DoctrineMappingAttribute { - public function getTargetEntity(Repository $config): string|null; + public function getTargetEntity(Config $config): string|null; } diff --git a/src/Mappings/RelationAttribute.php b/src/Attribute/RelationAttribute.php similarity index 78% rename from src/Mappings/RelationAttribute.php rename to src/Attribute/RelationAttribute.php index c1a11aa..86561d7 100644 --- a/src/Mappings/RelationAttribute.php +++ b/src/Attribute/RelationAttribute.php @@ -2,19 +2,15 @@ declare(strict_types=1); -namespace LaravelDoctrine\ACL\Mappings; +namespace LaravelDoctrine\ACL\Attribute; abstract class RelationAttribute implements MappingAttribute { public string|null $targetEntity; public string|null $mappedBy; - /** @var string[] */ public array|null $cascade; - - public string $fetch = 'LAZY'; - + public string $fetch = 'LAZY'; public bool $orphanRemoval = false; - public string|null $indexBy; } diff --git a/src/Mappings/Builders/Builder.php b/src/Mappings/Builders/Builder.php index c6a9960..446cccf 100644 --- a/src/Mappings/Builders/Builder.php +++ b/src/Mappings/Builders/Builder.php @@ -5,7 +5,7 @@ namespace LaravelDoctrine\ACL\Mappings\Builders; use Doctrine\Persistence\Mapping\ClassMetadata; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use ReflectionProperty; interface Builder diff --git a/src/Mappings/Builders/JsonArrayBuilder.php b/src/Mappings/Builders/JsonArrayBuilder.php index e949e9f..c6c0e9c 100644 --- a/src/Mappings/Builders/JsonArrayBuilder.php +++ b/src/Mappings/Builders/JsonArrayBuilder.php @@ -8,13 +8,13 @@ use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; use Doctrine\ORM\Mapping\Builder\FieldBuilder; use Doctrine\Persistence\Mapping\ClassMetadata; -use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; +use Illuminate\Contracts\Config\Repository as Config; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use ReflectionProperty; class JsonArrayBuilder implements Builder { - public function __construct(protected Repository $config) + public function __construct(protected Config $config) { } diff --git a/src/Mappings/Builders/ManyToManyBuilder.php b/src/Mappings/Builders/ManyToManyBuilder.php index 4dc2adc..423abf0 100644 --- a/src/Mappings/Builders/ManyToManyBuilder.php +++ b/src/Mappings/Builders/ManyToManyBuilder.php @@ -8,13 +8,13 @@ use Doctrine\ORM\Mapping\Builder\ManyToManyAssociationBuilder; use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata; use Doctrine\Persistence\Mapping\ClassMetadata; -use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; +use Illuminate\Contracts\Config\Repository as Config; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use ReflectionProperty; class ManyToManyBuilder implements Builder { - public function __construct(protected Repository $config) + public function __construct(protected Config $config) { } diff --git a/src/Mappings/Builders/ManyToOneBuilder.php b/src/Mappings/Builders/ManyToOneBuilder.php index 97a74e9..82823c6 100644 --- a/src/Mappings/Builders/ManyToOneBuilder.php +++ b/src/Mappings/Builders/ManyToOneBuilder.php @@ -8,13 +8,13 @@ use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder; use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata; use Doctrine\Persistence\Mapping\ClassMetadata; -use Illuminate\Contracts\Config\Repository; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; +use Illuminate\Contracts\Config\Repository as Config; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use ReflectionProperty; class ManyToOneBuilder implements Builder { - public function __construct(protected Repository $config) + public function __construct(protected Config $config) { } diff --git a/src/Mappings/RegisterMappedEventSubscribers.php b/src/Mappings/RegisterMappedEventSubscribers.php index a5521c9..f7fe0e4 100644 --- a/src/Mappings/RegisterMappedEventSubscribers.php +++ b/src/Mappings/RegisterMappedEventSubscribers.php @@ -7,17 +7,19 @@ use Doctrine\Common\EventManager; use Doctrine\DBAL\Connection; use Doctrine\ORM\Configuration; +use Illuminate\Contracts\Config\Repository as Config; use LaravelDoctrine\ACL\Mappings\Subscribers\BelongsToOrganisationsSubscriber; use LaravelDoctrine\ACL\Mappings\Subscribers\BelongsToOrganisationSubscriber; use LaravelDoctrine\ACL\Mappings\Subscribers\HasPermissionsSubscriber; use LaravelDoctrine\ACL\Mappings\Subscribers\HasRolesSubscriber; +use LaravelDoctrine\ACL\Mappings\Subscribers\MappedEventSubscriber; use LaravelDoctrine\ORM\DoctrineExtender; use function app; class RegisterMappedEventSubscribers implements DoctrineExtender { - /** @var class-string[] $subscribers */ + /** @var array> $subscribers */ protected array $subscribers = [ BelongsToOrganisationsSubscriber::class, BelongsToOrganisationSubscriber::class, @@ -27,10 +29,9 @@ class RegisterMappedEventSubscribers implements DoctrineExtender public function extend(Configuration $configuration, Connection $connection, EventManager $eventManager): void { + $config = app(Config::class); foreach ($this->subscribers as $subscriber) { - $eventManager->addEventSubscriber( - new $subscriber(app('config')), - ); + $eventManager->addEventSubscriber(new $subscriber($config)); } } } diff --git a/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php b/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php index 9cb56d0..4e75512 100644 --- a/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php +++ b/src/Mappings/Subscribers/BelongsToOrganisationSubscriber.php @@ -5,11 +5,11 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; use Doctrine\Persistence\Mapping\ClassMetadata; +use LaravelDoctrine\ACL\Attribute\BelongsToOrganisation; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation as BelongsToOrganisationContract; -use LaravelDoctrine\ACL\Mappings\BelongsToOrganisation; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToOneBuilder; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; class BelongsToOrganisationSubscriber extends MappedEventSubscriber { diff --git a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php index a4b8bb7..922e458 100644 --- a/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php +++ b/src/Mappings/Subscribers/BelongsToOrganisationsSubscriber.php @@ -5,11 +5,11 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; use Doctrine\Persistence\Mapping\ClassMetadata; +use LaravelDoctrine\ACL\Attribute\BelongsToOrganisations; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations as BelongsToOrganisationsContract; -use LaravelDoctrine\ACL\Mappings\BelongsToOrganisations; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; class BelongsToOrganisationsSubscriber extends MappedEventSubscriber { diff --git a/src/Mappings/Subscribers/HasPermissionsSubscriber.php b/src/Mappings/Subscribers/HasPermissionsSubscriber.php index 6177acf..fe37c2e 100644 --- a/src/Mappings/Subscribers/HasPermissionsSubscriber.php +++ b/src/Mappings/Subscribers/HasPermissionsSubscriber.php @@ -5,12 +5,12 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; use Doctrine\Persistence\Mapping\ClassMetadata; +use LaravelDoctrine\ACL\Attribute\HasPermissions; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\JsonArrayBuilder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\HasPermissions; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; class HasPermissionsSubscriber extends MappedEventSubscriber { diff --git a/src/Mappings/Subscribers/HasRolesSubscriber.php b/src/Mappings/Subscribers/HasRolesSubscriber.php index a01dd4b..b084e88 100644 --- a/src/Mappings/Subscribers/HasRolesSubscriber.php +++ b/src/Mappings/Subscribers/HasRolesSubscriber.php @@ -5,11 +5,11 @@ namespace LaravelDoctrine\ACL\Mappings\Subscribers; use Doctrine\Persistence\Mapping\ClassMetadata; +use LaravelDoctrine\ACL\Attribute\HasRoles; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; use LaravelDoctrine\ACL\Mappings\Builders\Builder; use LaravelDoctrine\ACL\Mappings\Builders\ManyToManyBuilder; -use LaravelDoctrine\ACL\Mappings\HasRoles; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; class HasRolesSubscriber extends MappedEventSubscriber { diff --git a/src/Mappings/Subscribers/MappedEventSubscriber.php b/src/Mappings/Subscribers/MappedEventSubscriber.php index 6bf9349..3532d75 100644 --- a/src/Mappings/Subscribers/MappedEventSubscriber.php +++ b/src/Mappings/Subscribers/MappedEventSubscriber.php @@ -8,9 +8,9 @@ use Doctrine\ORM\Event\LoadClassMetadataEventArgs; use Doctrine\ORM\Events; use Doctrine\Persistence\Mapping\ClassMetadata; -use Illuminate\Contracts\Config\Repository; +use Illuminate\Contracts\Config\Repository as Config; +use LaravelDoctrine\ACL\Attribute\MappingAttribute; use LaravelDoctrine\ACL\Mappings\Builders\Builder; -use LaravelDoctrine\ACL\Mappings\MappingAttribute; use ReflectionClass; abstract class MappedEventSubscriber implements EventSubscriber @@ -22,7 +22,7 @@ abstract protected function shouldBeMapped(ClassMetadata $metadata): bool; abstract protected function getBuilder(MappingAttribute $attribute): Builder; - public function __construct(protected Repository $config) + public function __construct(protected Config $config) { } diff --git a/src/Permissions/Permission.php b/src/Permissions/Permission.php index 2809724..d71abb1 100644 --- a/src/Permissions/Permission.php +++ b/src/Permissions/Permission.php @@ -13,17 +13,17 @@ class Permission implements PermissionContract #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue(strategy: 'AUTO')] - protected int $id; + protected int|null $id = null; #[ORM\Column(type: 'string')] - protected string|null $name; + protected string|null $name = null; public function __construct(string $name) { $this->name = $name; } - public function getId(): int + public function getId(): int|null { return $this->id; } diff --git a/workbench/app/Entities/Role.php b/workbench/app/Entities/Role.php index 6637313..c65f3e3 100644 --- a/workbench/app/Entities/Role.php +++ b/workbench/app/Entities/Role.php @@ -9,7 +9,6 @@ use Doctrine\ORM\Mapping as ORM; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Contracts\Role as RoleContract; -use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Permissions\HasPermissions; use function is_array; @@ -29,7 +28,7 @@ class Role implements RoleContract, HasPermissionsContract protected string $name; /** @var Collection */ - #[ACL\HasPermissions()] + #[\LaravelDoctrine\ACL\Attribute\HasPermissions()] public Collection $permissions; public function __construct(string $name) diff --git a/workbench/app/Entities/User.php b/workbench/app/Entities/User.php index 8a9e493..a9b141a 100644 --- a/workbench/app/Entities/User.php +++ b/workbench/app/Entities/User.php @@ -12,10 +12,10 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; +use LaravelDoctrine\ACL\Attribute\BelongsToOrganisations; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations as BelongsToOrganisationsContract; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; -use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation; use LaravelDoctrine\ACL\Permissions\HasPermissions; use LaravelDoctrine\ACL\Roles\HasRoles; @@ -48,15 +48,15 @@ class User implements AuthenticatableContract, AuthorizableContract, CanResetPas public string $email; /** @var Collection */ - #[ACL\HasRoles()] + #[\LaravelDoctrine\ACL\Attribute\HasRoles()] public Collection $roles; /** @var Collection */ - #[ACL\HasPermissions()] + #[\LaravelDoctrine\ACL\Attribute\HasPermissions()] public Collection $permissions; /** @var Collection */ - #[ACL\BelongsToOrganisations()] + #[BelongsToOrganisations()] public Collection $organisations; public function __construct() diff --git a/workbench/app/Entities/UserJsonPermissions.php b/workbench/app/Entities/UserJsonPermissions.php index fb60db2..f0cf9e1 100644 --- a/workbench/app/Entities/UserJsonPermissions.php +++ b/workbench/app/Entities/UserJsonPermissions.php @@ -11,7 +11,6 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Permissions\HasPermissions; use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; @@ -38,7 +37,7 @@ class UserJsonPermissions implements AuthenticatableContract, AuthorizableContra public string $email; /** @var array */ - #[ACL\HasPermissions(inversedBy: 'users')] + #[\LaravelDoctrine\ACL\Attribute\HasPermissions(inversedBy: 'users')] public array $permissions = []; /** @return array */ diff --git a/workbench/app/Entities/UserSingleOrg.php b/workbench/app/Entities/UserSingleOrg.php index 4b3641f..6b7c902 100644 --- a/workbench/app/Entities/UserSingleOrg.php +++ b/workbench/app/Entities/UserSingleOrg.php @@ -12,10 +12,10 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; +use LaravelDoctrine\ACL\Attribute\BelongsToOrganisation; use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation as BelongsToOrganisationContract; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; -use LaravelDoctrine\ACL\Mappings as ACL; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation as TraitBelongsToOrganisation; use LaravelDoctrine\ACL\Permissions\HasPermissions; use LaravelDoctrine\ACL\Roles\HasRoles; @@ -48,14 +48,14 @@ class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, Ca public string $email; /** @var Collection */ - #[ACL\HasRoles()] + #[\LaravelDoctrine\ACL\Attribute\HasRoles()] public Collection $roles; /** @var array */ #[ORM\Column(type: 'json')] public array $permissions = []; - #[ACL\BelongsToOrganisation()] + #[BelongsToOrganisation()] public Organisation|null $organisation = null; public function __construct() From 98a1a8713836650c4d1eb49f8c75562288726976 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Sun, 27 Apr 2025 16:52:33 +0300 Subject: [PATCH 6/9] fix(docs): CI badge in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13768e4..2b2290b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Laravel Doctrine ACL Laravel Doctrine ACL is a package that provides RBAC (Role-Based Access Control) functionality for Laravel applications using Doctrine. It allows you to manage roles, permissions, and organisations, and seamlessly integrates with Laravel's Authorization system. -[![Build Status](https://github.com/ScholarshipOwl/laravel-doctrine-acl/actions/workflows/php.yml/badge.svg)](https://github.com/ScholarshipOwl/laravel-doctrine-acl/actions) +[![Build Status](https://github.com/laravel-doctrine/acl/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laravel-doctrine/acl/actions) [![Code Coverage](https://codecov.io/gh/laravel-doctrine/acl/graph/badge.svg?token=3CpQzDXOWX)](https://codecov.io/gh/laravel-doctrine/acl) [![PHPStan](https://img.shields.io/badge/PHPStan-level%201-brightgreen.svg)](https://img.shields.io/badge/PHPStan-level%201-brightgreen.svg) [![Documentation](https://readthedocs.org/projects/laravel-doctrine-acl-official/badge/?version=latest)](https://laravel-doctrine-acl-official.readthedocs.io/en/latest/) From 2a78a9bad147b65ece9f7987e3ba7b20283c9f95 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Mon, 28 Apr 2025 12:15:46 +0300 Subject: [PATCH 7/9] refactor: small fixes --- config/acl.php | 19 +- src/AclServiceProvider.php | 14 ++ src/Permissions/Driver/Config.php | 4 +- workbench/bootstrap/cache/packages.php | 62 ------- workbench/bootstrap/cache/services.php | 233 ------------------------- 5 files changed, 27 insertions(+), 305 deletions(-) delete mode 100755 workbench/bootstrap/cache/packages.php delete mode 100755 workbench/bootstrap/cache/services.php diff --git a/config/acl.php b/config/acl.php index 767a8e8..5f72a9b 100644 --- a/config/acl.php +++ b/config/acl.php @@ -2,14 +2,6 @@ return [ - /* - |-------------------------------------------------------------------------- - | Roles - |-------------------------------------------------------------------------- - */ - 'roles' => [ - 'entity' => App\Entities\Role::class, - ], /* |-------------------------------------------------------------------------- | Permissions @@ -24,6 +16,17 @@ 'entity' => LaravelDoctrine\ACL\Permissions\Permission::class, 'list' => [], ], + + + /* + |-------------------------------------------------------------------------- + | Roles + |-------------------------------------------------------------------------- + */ + 'roles' => [ + 'entity' => App\Entities\Role::class, + ], + /* |-------------------------------------------------------------------------- | Organisations diff --git a/src/AclServiceProvider.php b/src/AclServiceProvider.php index 72f71db..2d27430 100644 --- a/src/AclServiceProvider.php +++ b/src/AclServiceProvider.php @@ -10,10 +10,17 @@ use LaravelDoctrine\ACL\Mappings\RegisterMappedEventSubscribers; use LaravelDoctrine\ORM\DoctrineManager; +use function config_path; + use const DIRECTORY_SEPARATOR; class AclServiceProvider extends ServiceProvider { + public function boot(): void + { + $this->publishConfig(); + } + public function register(): void { $this->mergeConfig(); @@ -56,6 +63,13 @@ protected function registerGatePermissions(): void }); } + protected function publishConfig(): void + { + $this->publishes([ + $this->getConfigPath() => config_path('acl.php'), + ], 'config'); + } + protected function mergeConfig(): void { $this->mergeConfigFrom( diff --git a/src/Permissions/Driver/Config.php b/src/Permissions/Driver/Config.php index be3a0c5..4945e99 100644 --- a/src/Permissions/Driver/Config.php +++ b/src/Permissions/Driver/Config.php @@ -11,9 +11,9 @@ class Config implements PermissionDriver protected Collection $collection; /** @var array */ - public function __construct(protected array $permissions) + public function __construct(array $permissions) { - $this->collection = new Collection($this->permissions); + $this->collection = new Collection($permissions); } public function getAllPermissions(): Collection diff --git a/workbench/bootstrap/cache/packages.php b/workbench/bootstrap/cache/packages.php deleted file mode 100755 index 2ee8916..0000000 --- a/workbench/bootstrap/cache/packages.php +++ /dev/null @@ -1,62 +0,0 @@ - - [ - 'providers' => - [0 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider'], - ], - 'laravel-doctrine/orm' => - [ - 'aliases' => - [ - 'Doctrine' => 'LaravelDoctrine\\ORM\\Facades\\Doctrine', - 'Registry' => 'LaravelDoctrine\\ORM\\Facades\\Registry', - 'EntityManager' => 'LaravelDoctrine\\ORM\\Facades\\EntityManager', - ], - 'providers' => - [0 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider'], - ], - 'laravel/pail' => - [ - 'providers' => - [0 => 'Laravel\\Pail\\PailServiceProvider'], - ], - 'laravel/tinker' => - [ - 'providers' => - [0 => 'Laravel\\Tinker\\TinkerServiceProvider'], - ], - 'nesbot/carbon' => - [ - 'providers' => - [0 => 'Carbon\\Laravel\\ServiceProvider'], - ], - 'nunomaduro/collision' => - [ - 'providers' => - [0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider'], - ], - 'nunomaduro/termwind' => - [ - 'providers' => - [0 => 'Termwind\\Laravel\\TermwindServiceProvider'], - ], - 'orchestra/canvas' => - [ - 'providers' => - [0 => 'Orchestra\\Canvas\\LaravelServiceProvider'], - ], - 'orchestra/canvas-core' => - [ - 'providers' => - [0 => 'Orchestra\\Canvas\\Core\\LaravelServiceProvider'], - ], - 'sowl/laravel-doctrine-acl' => - [ - 'providers' => - [0 => 'LaravelDoctrine\\ACL\\AclServiceProvider'], - ], -]; diff --git a/workbench/bootstrap/cache/services.php b/workbench/bootstrap/cache/services.php deleted file mode 100755 index 6a8922a..0000000 --- a/workbench/bootstrap/cache/services.php +++ /dev/null @@ -1,233 +0,0 @@ - - [ - 0 => 'Illuminate\\Auth\\AuthServiceProvider', - 1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 2 => 'Illuminate\\Bus\\BusServiceProvider', - 3 => 'Illuminate\\Cache\\CacheServiceProvider', - 4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 5 => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', - 6 => 'Illuminate\\Cookie\\CookieServiceProvider', - 7 => 'Illuminate\\Database\\DatabaseServiceProvider', - 8 => 'Illuminate\\Encryption\\EncryptionServiceProvider', - 9 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', - 10 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', - 11 => 'Illuminate\\Hashing\\HashServiceProvider', - 12 => 'Illuminate\\Mail\\MailServiceProvider', - 13 => 'Illuminate\\Notifications\\NotificationServiceProvider', - 14 => 'Illuminate\\Pagination\\PaginationServiceProvider', - 15 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 16 => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 17 => 'Illuminate\\Queue\\QueueServiceProvider', - 18 => 'Illuminate\\Redis\\RedisServiceProvider', - 19 => 'Illuminate\\Session\\SessionServiceProvider', - 20 => 'Illuminate\\Translation\\TranslationServiceProvider', - 21 => 'Illuminate\\Validation\\ValidationServiceProvider', - 22 => 'Illuminate\\View\\ViewServiceProvider', - 23 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', - 24 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', - 25 => 'LaravelDoctrine\\ACL\\AclServiceProvider', - ], - 'eager' => - [ - 0 => 'Illuminate\\Auth\\AuthServiceProvider', - 1 => 'Illuminate\\Cookie\\CookieServiceProvider', - 2 => 'Illuminate\\Database\\DatabaseServiceProvider', - 3 => 'Illuminate\\Encryption\\EncryptionServiceProvider', - 4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', - 5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider', - 6 => 'Illuminate\\Notifications\\NotificationServiceProvider', - 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', - 8 => 'Illuminate\\Session\\SessionServiceProvider', - 9 => 'Illuminate\\View\\ViewServiceProvider', - 10 => 'LaravelDoctrine\\ORM\\DoctrineServiceProvider', - 11 => 'LaravelDoctrine\\Migrations\\MigrationsServiceProvider', - 12 => 'LaravelDoctrine\\ACL\\AclServiceProvider', - ], - 'deferred' => - [ - 'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider', - 'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', - 'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider', - 'cache' => 'Illuminate\\Cache\\CacheServiceProvider', - 'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider', - 'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider', - 'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider', - 'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider', - 'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Concurrency\\Console\\InvokeSerializedClosureCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\PruneStaleTagsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Console\\Scheduling\\ScheduleInterruptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StorageUnlinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ApiInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\BroadcastingInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ChannelListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ClassMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConfigPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EnumMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\InterfaceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\JobMiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\LangPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\TraitMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Foundation\\Console\\ViewMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Migrations\\Migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider', - 'Illuminate\\Concurrency\\ConcurrencyManager' => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider', - 'hash' => 'Illuminate\\Hashing\\HashServiceProvider', - 'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider', - 'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider', - 'mailer' => 'Illuminate\\Mail\\MailServiceProvider', - 'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider', - 'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider', - 'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 'pipeline' => 'Illuminate\\Pipeline\\PipelineServiceProvider', - 'queue' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider', - 'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider', - 'redis' => 'Illuminate\\Redis\\RedisServiceProvider', - 'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider', - 'translator' => 'Illuminate\\Translation\\TranslationServiceProvider', - 'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider', - 'validator' => 'Illuminate\\Validation\\ValidationServiceProvider', - 'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider', - 'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => 'Illuminate\\Validation\\ValidationServiceProvider', - ], - 'when' => - [ - 'Illuminate\\Broadcasting\\BroadcastServiceProvider' => - [], - 'Illuminate\\Bus\\BusServiceProvider' => - [], - 'Illuminate\\Cache\\CacheServiceProvider' => - [], - 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' => - [], - 'Illuminate\\Concurrency\\ConcurrencyServiceProvider' => - [], - 'Illuminate\\Hashing\\HashServiceProvider' => - [], - 'Illuminate\\Mail\\MailServiceProvider' => - [], - 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' => - [], - 'Illuminate\\Pipeline\\PipelineServiceProvider' => - [], - 'Illuminate\\Queue\\QueueServiceProvider' => - [], - 'Illuminate\\Redis\\RedisServiceProvider' => - [], - 'Illuminate\\Translation\\TranslationServiceProvider' => - [], - 'Illuminate\\Validation\\ValidationServiceProvider' => - [], - ], -]; From 0575128369c21bfc4ab4455cda0d621267342905 Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Mon, 28 Apr 2025 12:33:58 +0300 Subject: [PATCH 8/9] refacotr: use Laravel approach With prefix for the traits --- docs/core-concepts.rst | 2 +- docs/permissions.rst | 8 +++---- docs/roles.rst | 2 +- ...HasPermissions.php => WithPermissions.php} | 2 +- src/Roles/{HasRoles.php => WithRoles.php} | 2 +- workbench/app/Entities/Role.php | 11 +++++---- workbench/app/Entities/User.php | 24 +++++++++---------- .../app/Entities/UserJsonPermissions.php | 11 +++++---- workbench/app/Entities/UserSingleOrg.php | 22 ++++++++--------- 9 files changed, 43 insertions(+), 41 deletions(-) rename src/Permissions/{HasPermissions.php => WithPermissions.php} (98%) rename src/Roles/{HasRoles.php => WithRoles.php} (98%) diff --git a/docs/core-concepts.rst b/docs/core-concepts.rst index 22d565d..84205b2 100644 --- a/docs/core-concepts.rst +++ b/docs/core-concepts.rst @@ -11,7 +11,7 @@ A permission is a singular ability to perform an action. Read more at `permissions `_. * Both users and roles can have permissions. -* Implement ``LaravelDoctrine\ACL\Contracts\HasPermissions`` and use the ``HasPermissions`` trait. +* Implement ``LaravelDoctrine\ACL\Contracts\HasPermissions`` and use the ``WithPermissions`` trait. * Permissions can be managed via config or Doctrine database tables (see below). diff --git a/docs/permissions.rst b/docs/permissions.rst index 271a89a..3ccd440 100644 --- a/docs/permissions.rst +++ b/docs/permissions.rst @@ -5,7 +5,7 @@ Permissions Both User and Role can have permissions. To add this behaviour we can simply add the ``LaravelDoctrine\ACL\Contracts\HasPermissions`` interface to them. We can also add the -``LaravelDoctrine\ACL\Permissions\HasPermissions`` trait to have some +``LaravelDoctrine\ACL\Permissions\WithPermissions`` trait to have some nice helpers. We can use the ``#[ACL\HasPermissions]`` attribute to define the permissions relation. @@ -15,13 +15,13 @@ define the permissions relation. use Doctrine\ORM\Mapping as ORM; use LaravelDoctrine\ACL\Attribute as ACL; - use LaravelDoctrine\ACL\Permissions\HasPermissions; + use LaravelDoctrine\ACL\Permissions\WithPermissions; use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionContract; #[ORM\Entity] class User implements HasPermissionContract { - use HasPermissions; + use WithPermissions; #[ACL\HasPermissions] protected $permissions; @@ -80,7 +80,7 @@ Checking if a User or Role has permission On the User or Role entity ^^^^^^^^^^^^^^^^^^^^^^^^^^ -When adding the ``LaravelDoctrine\ACL\Permissions\HasPermissions`` trait +When adding the ``LaravelDoctrine\ACL\Permissions\WithPermissions`` trait you will get a ``hasPermissionTo`` method. First the ``User`` entity will check if it has the right permission itself. If not it will search in its roles. If none of them has permission, it will return false. diff --git a/docs/roles.rst b/docs/roles.rst index ef98a26..2d26558 100644 --- a/docs/roles.rst +++ b/docs/roles.rst @@ -93,7 +93,7 @@ the user and their roles. This means: 2. If not found, check all permissions assigned to each of the user’s roles. -- This logic is implemented in the ``HasPermissions`` trait (see +- This logic is implemented in the ``WithPermissions`` trait (see source), which first checks the user’s permissions, then iterates over all roles (if any) and checks their permissions recursively. diff --git a/src/Permissions/HasPermissions.php b/src/Permissions/WithPermissions.php similarity index 98% rename from src/Permissions/HasPermissions.php rename to src/Permissions/WithPermissions.php index 25f8936..f16571e 100644 --- a/src/Permissions/HasPermissions.php +++ b/src/Permissions/WithPermissions.php @@ -10,7 +10,7 @@ use function is_array; -trait HasPermissions +trait WithPermissions { public function hasPermissionTo(Permission|string|array $name, bool $requireAll = false): bool { diff --git a/src/Roles/HasRoles.php b/src/Roles/WithRoles.php similarity index 98% rename from src/Roles/HasRoles.php rename to src/Roles/WithRoles.php index e6e3e5b..87dab1f 100644 --- a/src/Roles/HasRoles.php +++ b/src/Roles/WithRoles.php @@ -9,7 +9,7 @@ use function is_array; -trait HasRoles +trait WithRoles { public function hasRole(Role|array $role, bool $requireAll = false): bool { diff --git a/workbench/app/Entities/Role.php b/workbench/app/Entities/Role.php index c65f3e3..609efa2 100644 --- a/workbench/app/Entities/Role.php +++ b/workbench/app/Entities/Role.php @@ -7,17 +7,18 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; +use LaravelDoctrine\ACL\Attribute as ACL; use LaravelDoctrine\ACL\Contracts\Role as RoleContract; -use LaravelDoctrine\ACL\Permissions\HasPermissions; +use LaravelDoctrine\ACL\Permissions\Permission; +use LaravelDoctrine\ACL\Permissions\WithPermissions; use function is_array; #[ORM\Entity] #[ORM\Table(name: 'roles')] -class Role implements RoleContract, HasPermissionsContract +class Role implements RoleContract { - use HasPermissions; + use WithPermissions; #[ORM\Id] #[ORM\GeneratedValue] @@ -28,7 +29,7 @@ class Role implements RoleContract, HasPermissionsContract protected string $name; /** @var Collection */ - #[\LaravelDoctrine\ACL\Attribute\HasPermissions()] + #[ACL\HasPermissions] public Collection $permissions; public function __construct(string $name) diff --git a/workbench/app/Entities/User.php b/workbench/app/Entities/User.php index a9b141a..be993f0 100644 --- a/workbench/app/Entities/User.php +++ b/workbench/app/Entities/User.php @@ -12,13 +12,13 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; -use LaravelDoctrine\ACL\Attribute\BelongsToOrganisations; -use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations as BelongsToOrganisationsContract; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; +use LaravelDoctrine\ACL\Attribute as ACL; +use LaravelDoctrine\ACL\Contracts\BelongsToOrganisations; +use LaravelDoctrine\ACL\Contracts\HasPermissions; +use LaravelDoctrine\ACL\Contracts\HasRoles; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation; -use LaravelDoctrine\ACL\Permissions\HasPermissions; -use LaravelDoctrine\ACL\Roles\HasRoles; +use LaravelDoctrine\ACL\Permissions\WithPermissions; +use LaravelDoctrine\ACL\Roles\WithRoles; use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; @@ -26,14 +26,14 @@ #[ORM\Entity] #[ORM\Table()] -class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRolesContract, HasPermissionsContract, BelongsToOrganisationsContract +class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRoles, HasPermissions, BelongsToOrganisations { use Authenticatable; use Authorizable; use CanResetPassword; use Notifiable; - use HasRoles; - use HasPermissions; + use WithRoles; + use WithPermissions; use BelongsToOrganisation; #[ORM\Id] @@ -48,15 +48,15 @@ class User implements AuthenticatableContract, AuthorizableContract, CanResetPas public string $email; /** @var Collection */ - #[\LaravelDoctrine\ACL\Attribute\HasRoles()] + #[ACL\HasRoles] public Collection $roles; /** @var Collection */ - #[\LaravelDoctrine\ACL\Attribute\HasPermissions()] + #[ACL\HasPermissions] public Collection $permissions; /** @var Collection */ - #[BelongsToOrganisations()] + #[ACL\BelongsToOrganisations] public Collection $organisations; public function __construct() diff --git a/workbench/app/Entities/UserJsonPermissions.php b/workbench/app/Entities/UserJsonPermissions.php index f0cf9e1..89b831f 100644 --- a/workbench/app/Entities/UserJsonPermissions.php +++ b/workbench/app/Entities/UserJsonPermissions.php @@ -10,20 +10,21 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Permissions\HasPermissions; +use LaravelDoctrine\ACL\Attribute as ACL; +use LaravelDoctrine\ACL\Contracts\HasPermissions; +use LaravelDoctrine\ACL\Permissions\WithPermissions; use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; #[ORM\Entity] #[ORM\Table()] -class UserJsonPermissions implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasPermissionsContract +class UserJsonPermissions implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasPermissions { use Authenticatable; use Authorizable; use CanResetPassword; use Notifiable; - use HasPermissions; + use WithPermissions; #[ORM\Id] #[ORM\GeneratedValue] @@ -37,7 +38,7 @@ class UserJsonPermissions implements AuthenticatableContract, AuthorizableContra public string $email; /** @var array */ - #[\LaravelDoctrine\ACL\Attribute\HasPermissions(inversedBy: 'users')] + #[ACL\HasPermissions(inversedBy: 'users')] public array $permissions = []; /** @return array */ diff --git a/workbench/app/Entities/UserSingleOrg.php b/workbench/app/Entities/UserSingleOrg.php index 6b7c902..4921eaa 100644 --- a/workbench/app/Entities/UserSingleOrg.php +++ b/workbench/app/Entities/UserSingleOrg.php @@ -12,13 +12,13 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; -use LaravelDoctrine\ACL\Attribute\BelongsToOrganisation; -use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation as BelongsToOrganisationContract; -use LaravelDoctrine\ACL\Contracts\HasPermissions as HasPermissionsContract; -use LaravelDoctrine\ACL\Contracts\HasRoles as HasRolesContract; +use LaravelDoctrine\ACL\Attribute as ACL; +use LaravelDoctrine\ACL\Contracts\BelongsToOrganisation; +use LaravelDoctrine\ACL\Contracts\HasPermissions; +use LaravelDoctrine\ACL\Contracts\HasRoles; use LaravelDoctrine\ACL\Organisations\BelongsToOrganisation as TraitBelongsToOrganisation; -use LaravelDoctrine\ACL\Permissions\HasPermissions; -use LaravelDoctrine\ACL\Roles\HasRoles; +use LaravelDoctrine\ACL\Permissions\WithPermissions; +use LaravelDoctrine\ACL\Roles\WithRoles; use LaravelDoctrine\ORM\Auth\Authenticatable; use LaravelDoctrine\ORM\Notifications\Notifiable; @@ -26,14 +26,14 @@ #[ORM\Entity] #[ORM\Table()] -class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRolesContract, HasPermissionsContract, BelongsToOrganisationContract +class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasRoles, HasPermissions, BelongsToOrganisation { use Authenticatable; use Authorizable; use CanResetPassword; use Notifiable; - use HasRoles; - use HasPermissions; + use WithRoles; + use WithPermissions; use TraitBelongsToOrganisation; #[ORM\Id] @@ -48,14 +48,14 @@ class UserSingleOrg implements AuthenticatableContract, AuthorizableContract, Ca public string $email; /** @var Collection */ - #[\LaravelDoctrine\ACL\Attribute\HasRoles()] + #[ACL\HasRoles()] public Collection $roles; /** @var array */ #[ORM\Column(type: 'json')] public array $permissions = []; - #[BelongsToOrganisation()] + #[ACL\BelongsToOrganisation()] public Organisation|null $organisation = null; public function __construct() From adb20273b999aca6e67af175408e8d73fa34de3e Mon Sep 17 00:00:00 2001 From: Pavel Z Date: Mon, 28 Apr 2025 12:52:04 +0300 Subject: [PATCH 9/9] feat(stubs): publish entities from stubs --- docs/configurations.rst | 19 +++++++++ docs/organisations.rst | 10 +++++ docs/permissions.rst | 10 +++++ docs/roles.rst | 8 ++++ src/AclServiceProvider.php | 23 +++++++++++ src/Permissions/Permission.php | 2 +- stubs/Organisation.php | 37 ++++++++++++++++++ stubs/Permission.php | 37 ++++++++++++++++++ stubs/Role.php | 71 ++++++++++++++++++++++++++++++++++ 9 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 stubs/Organisation.php create mode 100644 stubs/Permission.php create mode 100644 stubs/Role.php diff --git a/docs/configurations.rst b/docs/configurations.rst index 87f44d5..ac5636f 100644 --- a/docs/configurations.rst +++ b/docs/configurations.rst @@ -55,6 +55,25 @@ Organisations - **entity**: The fully qualified class name of your Organisation entity. By default, this is `App\Entities\Organisation`. You may customize this to point to your own Organisation entity class implementing `LaravelDoctrine\ACL\Contracts\Organisation`. +Entities +======== + +You can use the stubs as a starting point for your own entities. + +You may publish the stubs for the entities by running the following command: + +.. code-block:: bash + + php artisan vendor:publish --tag="acl-entities" + +This command will publish the stubs for the entities to the `app/Entities` directory. + + * [`app/Entities/Permission.php`](../stubs/Permission.php) - The stub for the Permission entity. + * [`app/Entities/Role.php`](../stubs/Role.php) - The stub for the Role entity. + * [`app/Entities/Organisation.php`](../stubs/Organisation.php) - The stub for the Organisation entity. + +> **Note**: Pay attention that we published a stub for Permission so you should update `acl.permission.entity` in the config file. + .. role:: raw-html(raw) :format: html diff --git a/docs/organisations.rst b/docs/organisations.rst index 0584753..065979b 100644 --- a/docs/organisations.rst +++ b/docs/organisations.rst @@ -35,6 +35,16 @@ you will have to create an entity that implements } } +You can use the Organisation stub as a starting point for your own entity. + +.. code-block:: bash + + php artisan vendor:publish --tag="acl-entity-organisation" + +This command will publish the [`Organisation`](../stubs/Organisation.php) stub for the Organisation entity to the `app/Entities` directory. + +> **Note**: Pay attention that we published a stub for Organisation so you should update `acl.organisation.entity` in the config file. + User can belong to one organisation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/permissions.rst b/docs/permissions.rst index 3ccd440..7e6fc3e 100644 --- a/docs/permissions.rst +++ b/docs/permissions.rst @@ -32,6 +32,16 @@ define the permissions relation. } } +You can use the Permission stub as a starting point for your own entity. + +.. code-block:: bash + + php artisan vendor:publish --tag="acl-entity-permission" + +This command will publish the [`Permission`](../stubs/Permission.php) stub for the Permission entity to the `app/Entities` directory. + +> **Note**: Pay attention that we published a stub for Permission so you should update `acl.permission.entity` in the config file. + Getting all permissions ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/roles.rst b/docs/roles.rst index 2d26558..ca70a31 100644 --- a/docs/roles.rst +++ b/docs/roles.rst @@ -37,7 +37,15 @@ set to ``App\Entities\Role``. } } +You can use the Role stub as a starting point for your own entity. +.. code-block:: bash + + php artisan vendor:publish --tag="acl-entity-role" + +This command will publish the [`Role`](../stubs/Role.php) stub for the Role entity to the `app/Entities` directory. + +> **Note**: Pay attention that we published a stub for Role so you should update `acl.role.entity` in the config file. A User has Roles ---------------- diff --git a/src/AclServiceProvider.php b/src/AclServiceProvider.php index 2d27430..8fa270d 100644 --- a/src/AclServiceProvider.php +++ b/src/AclServiceProvider.php @@ -10,6 +10,7 @@ use LaravelDoctrine\ACL\Mappings\RegisterMappedEventSubscribers; use LaravelDoctrine\ORM\DoctrineManager; +use function app_path; use function config_path; use const DIRECTORY_SEPARATOR; @@ -19,6 +20,7 @@ class AclServiceProvider extends ServiceProvider public function boot(): void { $this->publishConfig(); + $this->publishEntities(); } public function register(): void @@ -82,4 +84,25 @@ protected function getConfigPath(): string { return __DIR__ . '/../config/acl.php'; } + + /** + * Publish default entity stubs separately with specific tags/groups. + */ + protected function publishEntities(): void + { + // Permission entity + $this->publishes([ + __DIR__ . '/../stubs/Permission.php' => app_path('Entities/Permission.php'), + ], ['acl-entities', 'acl-entity-permission']); + + // Role entity + $this->publishes([ + __DIR__ . '/../stubs/Role.php' => app_path('Entities/Role.php'), + ], ['acl-entities', 'acl-entity-role']); + + // Organisation entity + $this->publishes([ + __DIR__ . '/../stubs/Organisation.php' => app_path('Entities/Organisation.php'), + ], ['acl-entities', 'acl-entity-organisation']); + } } diff --git a/src/Permissions/Permission.php b/src/Permissions/Permission.php index d71abb1..31807a8 100644 --- a/src/Permissions/Permission.php +++ b/src/Permissions/Permission.php @@ -16,7 +16,7 @@ class Permission implements PermissionContract protected int|null $id = null; #[ORM\Column(type: 'string')] - protected string|null $name = null; + protected string $name; public function __construct(string $name) { diff --git a/stubs/Organisation.php b/stubs/Organisation.php new file mode 100644 index 0000000..8094dc9 --- /dev/null +++ b/stubs/Organisation.php @@ -0,0 +1,37 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } +} diff --git a/stubs/Permission.php b/stubs/Permission.php new file mode 100644 index 0000000..709a47a --- /dev/null +++ b/stubs/Permission.php @@ -0,0 +1,37 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } +} + + diff --git a/stubs/Role.php b/stubs/Role.php new file mode 100644 index 0000000..3daf4e8 --- /dev/null +++ b/stubs/Role.php @@ -0,0 +1,71 @@ + */ + #[ACL\HasPermissions] + public Collection $permissions; + + public function __construct() + { + $this->permissions = new ArrayCollection(); + } + + public function getId(): int|null + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + /** @return Collection */ + public function getPermissions(): Collection + { + return $this->permissions; + } + + /** @param Collection|Permission[] $permissions */ + public function setPermissions(Collection|array $permissions): self + { + $this->permissions = is_array($permissions) ? new ArrayCollection($permissions) : $permissions; + + return $this; + } +} + +