From d7c6c7a2237d8e82056f7d7e10be3098c2c53558 Mon Sep 17 00:00:00 2001 From: Dennis Riehle Date: Mon, 18 Oct 2021 10:59:52 +0200 Subject: [PATCH 1/5] moved docs --- README.md | 2 +- docs/{ => en}/authentication.md | 0 docs/{ => en}/caching.md | 48 ++++++++++++++++----------------- docs/{ => en}/cli.md | 0 docs/{ => en}/form-element.md | 0 docs/{ => en}/index.md | 0 docs/{ => en}/paginator.md | 0 docs/{ => en}/validator.md | 0 8 files changed, 25 insertions(+), 25 deletions(-) rename docs/{ => en}/authentication.md (100%) rename docs/{ => en}/caching.md (97%) rename docs/{ => en}/cli.md (100%) rename docs/{ => en}/form-element.md (100%) rename docs/{ => en}/index.md (100%) rename docs/{ => en}/paginator.md (100%) rename docs/{ => en}/validator.md (100%) diff --git a/README.md b/README.md index 1e0c00307..c40543039 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ and [DoctrineMongoODMModule](https://github.com/doctrine/DoctrineMongoODMModule) ## Documentation -Please check the [`docs` dir](https://github.com/doctrine/DoctrineModule/tree/master/docs) +Please check the [`docs` dir](https://github.com/doctrine/DoctrineModule/tree/master/docs/en) for more detailed documentation on the features provided by this module. ## Installation diff --git a/docs/authentication.md b/docs/en/authentication.md similarity index 100% rename from docs/authentication.md rename to docs/en/authentication.md diff --git a/docs/caching.md b/docs/en/caching.md similarity index 97% rename from docs/caching.md rename to docs/en/caching.md index daa548489..d214273b1 100644 --- a/docs/caching.md +++ b/docs/en/caching.md @@ -1,24 +1,24 @@ -# Caching - -DoctrineModule provides bridging between -[`Laminas\Cache`](https://github.com/laminas/laminas-cache) -and [`Doctrine\Common\Cache`](https://github.com/doctrine/common/tree/master/lib/Doctrine/Common/Cache). -This may be useful in case you want to share configured cache instances across doctrine, symfony -and laminas projects. - -You may use `Laminas\Cache` within your doctrine-related projects as following: - -```php -$laminasCache = new \Laminas\Cache\Storage\Adapter\Memory(); // any storage adapter is OK here -$doctrineCache = new \DoctrineModule\Cache\LaminasStorageCache($laminasCache); -// now use $doctrineCache as a normal Doctrine\Common\Cache\Cache instance -``` - -You may use `Doctrine\Common\Cache` within your Laminas projects as following: - -```php -$doctrineCache = new \Doctrine\Common\Cache\ArrayCache(); // any doctrine cache is OK here -$adapterOptions = new \Laminas\Cache\Storage\Adapter\AdapterOptions(); -$laminasCacheStorage = new \DoctrineModule\Cache\DoctrineCacheStorage($adapterOptions, $doctrineCache); -// now use $laminasCacheStorage as a normal Laminas\Cache\Storage\StorageInterface instance. -``` +# Caching + +DoctrineModule provides bridging between +[`Laminas\Cache`](https://github.com/laminas/laminas-cache) +and [`Doctrine\Common\Cache`](https://github.com/doctrine/common/tree/master/lib/Doctrine/Common/Cache). +This may be useful in case you want to share configured cache instances across doctrine, symfony +and laminas projects. + +You may use `Laminas\Cache` within your doctrine-related projects as following: + +```php +$laminasCache = new \Laminas\Cache\Storage\Adapter\Memory(); // any storage adapter is OK here +$doctrineCache = new \DoctrineModule\Cache\LaminasStorageCache($laminasCache); +// now use $doctrineCache as a normal Doctrine\Common\Cache\Cache instance +``` + +You may use `Doctrine\Common\Cache` within your Laminas projects as following: + +```php +$doctrineCache = new \Doctrine\Common\Cache\ArrayCache(); // any doctrine cache is OK here +$adapterOptions = new \Laminas\Cache\Storage\Adapter\AdapterOptions(); +$laminasCacheStorage = new \DoctrineModule\Cache\DoctrineCacheStorage($adapterOptions, $doctrineCache); +// now use $laminasCacheStorage as a normal Laminas\Cache\Storage\StorageInterface instance. +``` diff --git a/docs/cli.md b/docs/en/cli.md similarity index 100% rename from docs/cli.md rename to docs/en/cli.md diff --git a/docs/form-element.md b/docs/en/form-element.md similarity index 100% rename from docs/form-element.md rename to docs/en/form-element.md diff --git a/docs/index.md b/docs/en/index.md similarity index 100% rename from docs/index.md rename to docs/en/index.md diff --git a/docs/paginator.md b/docs/en/paginator.md similarity index 100% rename from docs/paginator.md rename to docs/en/paginator.md diff --git a/docs/validator.md b/docs/en/validator.md similarity index 100% rename from docs/validator.md rename to docs/en/validator.md From 4b17478b7a41ad2a2bff9a13a51be6ec282d4fd5 Mon Sep 17 00:00:00 2001 From: Dennis Riehle Date: Mon, 18 Oct 2021 11:00:23 +0200 Subject: [PATCH 2/5] converted docs to RST using pandoc --- docs/en/authentication.md | 255 -------------------------- docs/en/authentication.rst | 329 ++++++++++++++++++++++++++++++++++ docs/en/caching.md | 24 --- docs/en/caching.rst | 27 +++ docs/en/cli.md | 42 ----- docs/en/cli.rst | 45 +++++ docs/en/form-element.md | 331 ---------------------------------- docs/en/form-element.rst | 356 +++++++++++++++++++++++++++++++++++++ docs/en/index.md | 19 -- docs/en/index.rst | 44 +++++ docs/en/paginator.md | 80 --------- docs/en/paginator.rst | 97 ++++++++++ docs/en/validator.md | 176 ------------------ docs/en/validator.rst | 205 +++++++++++++++++++++ 14 files changed, 1103 insertions(+), 927 deletions(-) delete mode 100644 docs/en/authentication.md create mode 100644 docs/en/authentication.rst delete mode 100644 docs/en/caching.md create mode 100644 docs/en/caching.rst delete mode 100644 docs/en/cli.md create mode 100644 docs/en/cli.rst delete mode 100644 docs/en/form-element.md create mode 100644 docs/en/form-element.rst delete mode 100644 docs/en/index.md create mode 100644 docs/en/index.rst delete mode 100644 docs/en/paginator.md create mode 100644 docs/en/paginator.rst delete mode 100644 docs/en/validator.md create mode 100644 docs/en/validator.rst diff --git a/docs/en/authentication.md b/docs/en/authentication.md deleted file mode 100644 index 1848a6ff4..000000000 --- a/docs/en/authentication.md +++ /dev/null @@ -1,255 +0,0 @@ -# Authentication - -Authentication through Doctrine is fully supported by DoctrineModule through an authentication adapter, and a specific storage implementation that relies on the database. Most of the time, those classes will be used in conjunction with `Laminas\Authentication\AuthenticationService` class. - -### Simple example - -In order to authenticate a user (or anything else) against Doctrine, the following workflow is used: - -1. Set configuration that contains options about the entity that is authenticated (credential property, identity property…). It is not necessary to create a separate authentication adapter, this will be automatically created by the DoctrineModule based on the defined configuration. -2. Create a storage adapter. If the authentication succeeds, the identifier of the entity will be automatically stored in session. -3. Create a `Laminas\Authentication\AuthenticationService`instance that contains both the authentication adapter and the storage adapter. - -#### Authentication factory - -To make your life easier, DoctrineModule provides an Authentication factory through the ``DoctrineModule\Options\Authentication`` class. - -The first task is to configure the Authentication by adding the ``authentication`` key to the ``doctrine`` key in your config file (we assume here that the entity we want to authentication is simply called `Application\Entity\User`): - -```php -// in your module.config.php: - -return [ - 'doctrine' => [ - 'authentication' => [ - 'orm_default' => [ - 'object_manager' => 'Doctrine\ORM\EntityManager', - 'identity_class' => 'Application\Entity\User', - 'identity_property' => 'email', - 'credential_property' => 'password', - ], - ], - ], -]; -``` - -Here are some explanations about the keys: - -* the `object_manager` key can either be a concrete instance of a `Doctrine\Persistence\ObjectManager` or a single string that will fetched from the Service Manager in order to get a concrete instance. If you are using DoctrineORMModule, you can simply write 'Doctrine\ORM\EntityManager' (as the EntityManager implements the class `Doctrine\Persistence\ObjectManager`). -* the `identity_class` contains the FQCN of the entity that will be used during the authentication process. -* the `identity_property` contains the name of the property that will be used as the identity property (most often, this is email, username…). Please note that we are talking here of the PROPERTY, not the table column name (although it can be the same in most of the cases). -* the `credential_property` contains the name of the property that will be used as the credential property (most often, this is password…). - -The authentication accept some more options that can be used : - -* the `object_repository` can be used instead of the `object_manager` key. Most of the time you won't deal with the one, as specifying the `identity_class` name will automatically fetch the `object_repository` for you. -* the `credential_callable` is a very useful option that allow you to perform some custom logic when checking if the credential is correct. For instance, if your password are encrypted using Bcrypt algorithm, you will need to perform specific logic. This option can be any callable function (closure, class method…). This function will be given the complete entity fetched from the database, and the credential that was given by the user during the authentication process. - -Here is an example code that adds the `credential_callable` function to our previous example : - -```php -// in your module.config.php: - -return [ - 'doctrine' => [ - 'authentication' => [ - 'orm_default' => [ - 'object_manager' => 'Doctrine\ORM\EntityManager', - 'identity_class' => 'Application\Entity\User', - 'identity_property' => 'email', - 'credential_property' => 'password', - 'credential_callable' => function (User $user, $passwordGiven) { - return my_awesome_check_test($user->getPassword(), $passwordGiven); - }, - ], - ], - ], -]; -``` - -Here is another example that uses a controller method as the *credential_callable* callback. Note that the controller method must be declared *public static*. - -```php -// in your module.config.php: - -return [ - 'doctrine' => [ - 'authentication' => [ - 'orm_default' => [ - 'object_manager' => 'Doctrine\ORM\EntityManager', - 'identity_class' => 'Application\Entity\User', - 'identity_property' => 'email', - 'credential_property' => 'password', - 'credential_callable' => 'Application\Controller\UserController::verifyCredential' - ], - ], - ], -]; - -// in UserController.php - -public static function verifyCredential(User $user, $inputPassword) -{ - return password_verify($inputPassword, $user->getPassword()); -} -``` - - -#### Creating the AuthenticationService - -Now that we have configured the authentication, we still need to tell Laminas how to construct a correct ``Laminas\Authentication\AuthenticationService`` instance. For this, add the following code in your Module.php class: - -```php -namespace Application; - -use Laminas\Authentication\AuthenticationService; - -class Module -{ - public function getServiceConfig() - { - return [ - 'factories' => [ - 'Laminas\Authentication\AuthenticationService' => function ($serviceManager) { - // If you are using DoctrineORMModule: - return $serviceManager->get('doctrine.authenticationservice.orm_default'); - - // If you are using DoctrineODMModule: - return $serviceManager->get('doctrine.authenticationservice.odm_default'); - }, - ], - ]; - } -} -``` - -Please note that I am using here a ``Laminas\Authentication\AuthenticationService`` name, but it can be anything else (``my_auth_service``…). However, using the name ``Laminas\Authentication\AuthenticationService`` will allow it to be recognised by the Laminas [Identity view helper](https://docs.laminas.dev/laminas-view/helpers/identity/). - -In Laminas, you can inject the ``Laminas\Authentication\AuthenticationService`` into your controller factories as in the example below: - -```php -get('doctrine.authenticationservice.orm_default'); - return new $requestedName($authenticationService); - } -} -``` - -#### Using the AuthenticationService - -Now that we have defined how to create a `Laminas\Authentication\AuthenticationService` object we can use it in our code. For more information about Laminas authentication mechanisms please read [the laminas-authentication documentation](https://docs.laminas.dev/laminas-authentication/). - -Here is an example of how we could use it from a controller action (we stripped any Form things for simplicity): - -```php -public function loginAction() -{ - $data = $this->getRequest()->getPost(); - - // If you used another name for the authentication service, change it here - $authService = $this->getServiceLocator()->get('Laminas\Authentication\AuthenticationService'); - - $adapter = $authService->getAdapter(); - $adapter->setIdentityValue($data['login']); - $adapter->setCredentialValue($data['password']); - $authResult = $authService->authenticate(); - - if ($authResult->isValid()) { - return $this->redirect()->toRoute('home'); - } - - return new ViewModel([ - 'error' => 'Your authentication credentials are not valid', - ]); -} -``` - -Instead of Zend Framework 2, you can do like this in Zend Framework 3 and Laminas: - -```php - -public function __construct(AuthenticationService $authenticationService) -{ - $this->authenticationService = $authenticationService; -} - -public function loginAction() -{ - $data = $this->getRequest()->getPost(); - - $adapter = $this->authenticationService->getAdapter(); - $adapter->setIdentity($data['login']); - $adapter->setCredential($data['password']); - $authResult = $this->authenticationService->authenticate(); - - if ($authResult->isValid()) { - return $this->redirect()->toRoute('home'); - } - - return new ViewModel([ - 'error' => 'Your authentication credentials are not valid', - ]); -} - -``` - -Of course, doing this in the controller is not the best practice, and you'd better move that kind of logic to a service layer. But this is how it works. - -Note that when the authentication is valid, we first get the identity : - -```php -$identity = $authenticationResult->getIdentity(); -``` - -This will return the full entity (in our case, an `Application\Entity\User` instance). However, storing a full entity in session is not a recommended practice. That's why, when writing the identity : - -```php -$authService->getStorage()->write($identity); -``` - -The storage automatically extracts ONLY the identifier values and only store this in session (this avoid to store in session a serialized entity, which is a bad practice). Later, when you want to retrieve the logged user : - -```php -$authenticationService = $services->get('Laminas\Authentication\AuthenticationService'); -$authenticatedUser = $authenticationService->getIdentity(); -``` - -The authentication storage will automatically handle the conversion from saved data to managed entity and the opposite. It will avoid serializing entities since that is a strongly discouraged practice. - -#### View helper and controller helper - -You may also need to know if there is an authenticated user within your other controllers or in views. Laminas provides a controller plugin and a view helper you may use. - -Here is how you use it in your controller : - -```php -public function testAction() -{ - if ($user = $this->identity()) { - // someone is logged ! - } else { - // not logged in - } -} -``` - -And in your view : - -```php -identity()) { - echo 'Logged in as ' . $this->escapeHtml($user->getUsername()); - } else { - echo 'Not logged in'; - } -?> -``` diff --git a/docs/en/authentication.rst b/docs/en/authentication.rst new file mode 100644 index 000000000..3b97ab3fc --- /dev/null +++ b/docs/en/authentication.rst @@ -0,0 +1,329 @@ +Authentication +============== + +Authentication through Doctrine is fully supported by DoctrineModule +through an authentication adapter, and a specific storage implementation +that relies on the database. Most of the time, those classes will be +used in conjunction with +``Laminas\Authentication\AuthenticationService`` class. + +Simple example +~~~~~~~~~~~~~~ + +In order to authenticate a user (or anything else) against Doctrine, the +following workflow is used: + +1. Set configuration that contains options about the entity that is + authenticated (credential property, identity property…). It is not + necessary to create a separate authentication adapter, this will be + automatically created by the DoctrineModule based on the defined + configuration. +2. Create a storage adapter. If the authentication succeeds, the + identifier of the entity will be automatically stored in session. +3. Create a ``Laminas\Authentication\AuthenticationService``\ instance + that contains both the authentication adapter and the storage + adapter. + +Authentication factory +^^^^^^^^^^^^^^^^^^^^^^ + +To make your life easier, DoctrineModule provides an Authentication +factory through the ``DoctrineModule\Options\Authentication`` class. + +The first task is to configure the Authentication by adding the +``authentication`` key to the ``doctrine`` key in your config file (we +assume here that the entity we want to authentication is simply called +``Application\Entity\User``): + +.. code:: php + + // in your module.config.php: + + return [ + 'doctrine' => [ + 'authentication' => [ + 'orm_default' => [ + 'object_manager' => 'Doctrine\ORM\EntityManager', + 'identity_class' => 'Application\Entity\User', + 'identity_property' => 'email', + 'credential_property' => 'password', + ], + ], + ], + ]; + +Here are some explanations about the keys: + +- the ``object_manager`` key can either be a concrete instance of a + ``Doctrine\Persistence\ObjectManager`` or a single string that will + fetched from the Service Manager in order to get a concrete instance. + If you are using DoctrineORMModule, you can simply write + ‘Doctrine:raw-latex:`\ORM`:raw-latex:`\EntityManager`’ (as the + EntityManager implements the class + ``Doctrine\Persistence\ObjectManager``). +- the ``identity_class`` contains the FQCN of the entity that will be + used during the authentication process. +- the ``identity_property`` contains the name of the property that will + be used as the identity property (most often, this is email, + username…). Please note that we are talking here of the PROPERTY, not + the table column name (although it can be the same in most of the + cases). +- the ``credential_property`` contains the name of the property that + will be used as the credential property (most often, this is + password…). + +The authentication accept some more options that can be used : + +- the ``object_repository`` can be used instead of the + ``object_manager`` key. Most of the time you won’t deal with the one, + as specifying the ``identity_class`` name will automatically fetch + the ``object_repository`` for you. +- the ``credential_callable`` is a very useful option that allow you to + perform some custom logic when checking if the credential is correct. + For instance, if your password are encrypted using Bcrypt algorithm, + you will need to perform specific logic. This option can be any + callable function (closure, class method…). This function will be + given the complete entity fetched from the database, and the + credential that was given by the user during the authentication + process. + +Here is an example code that adds the ``credential_callable`` function +to our previous example : + +.. code:: php + + // in your module.config.php: + + return [ + 'doctrine' => [ + 'authentication' => [ + 'orm_default' => [ + 'object_manager' => 'Doctrine\ORM\EntityManager', + 'identity_class' => 'Application\Entity\User', + 'identity_property' => 'email', + 'credential_property' => 'password', + 'credential_callable' => function (User $user, $passwordGiven) { + return my_awesome_check_test($user->getPassword(), $passwordGiven); + }, + ], + ], + ], + ]; + +Here is another example that uses a controller method as the +*credential_callable* callback. Note that the controller method must be +declared *public static*. + +.. code:: php + + // in your module.config.php: + + return [ + 'doctrine' => [ + 'authentication' => [ + 'orm_default' => [ + 'object_manager' => 'Doctrine\ORM\EntityManager', + 'identity_class' => 'Application\Entity\User', + 'identity_property' => 'email', + 'credential_property' => 'password', + 'credential_callable' => 'Application\Controller\UserController::verifyCredential' + ], + ], + ], + ]; + + // in UserController.php + + public static function verifyCredential(User $user, $inputPassword) + { + return password_verify($inputPassword, $user->getPassword()); + } + +Creating the AuthenticationService +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that we have configured the authentication, we still need to tell +Laminas how to construct a correct +``Laminas\Authentication\AuthenticationService`` instance. For this, add +the following code in your Module.php class: + +.. code:: php + + namespace Application; + + use Laminas\Authentication\AuthenticationService; + + class Module + { + public function getServiceConfig() + { + return [ + 'factories' => [ + 'Laminas\Authentication\AuthenticationService' => function ($serviceManager) { + // If you are using DoctrineORMModule: + return $serviceManager->get('doctrine.authenticationservice.orm_default'); + + // If you are using DoctrineODMModule: + return $serviceManager->get('doctrine.authenticationservice.odm_default'); + }, + ], + ]; + } + } + +Please note that I am using here a +``Laminas\Authentication\AuthenticationService`` name, but it can be +anything else (``my_auth_service``\ …). However, using the name +``Laminas\Authentication\AuthenticationService`` will allow it to be +recognised by the Laminas `Identity view +helper `__. + +In Laminas, you can inject the +``Laminas\Authentication\AuthenticationService`` into your controller +factories as in the example below: + +.. code:: php + + get('doctrine.authenticationservice.orm_default'); + return new $requestedName($authenticationService); + } + } + +Using the AuthenticationService +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that we have defined how to create a +``Laminas\Authentication\AuthenticationService`` object we can use it in +our code. For more information about Laminas authentication mechanisms +please read `the laminas-authentication +documentation `__. + +Here is an example of how we could use it from a controller action (we +stripped any Form things for simplicity): + +.. code:: php + + public function loginAction() + { + $data = $this->getRequest()->getPost(); + + // If you used another name for the authentication service, change it here + $authService = $this->getServiceLocator()->get('Laminas\Authentication\AuthenticationService'); + + $adapter = $authService->getAdapter(); + $adapter->setIdentityValue($data['login']); + $adapter->setCredentialValue($data['password']); + $authResult = $authService->authenticate(); + + if ($authResult->isValid()) { + return $this->redirect()->toRoute('home'); + } + + return new ViewModel([ + 'error' => 'Your authentication credentials are not valid', + ]); + } + +Instead of Zend Framework 2, you can do like this in Zend Framework 3 +and Laminas: + +.. code:: php + + + public function __construct(AuthenticationService $authenticationService) + { + $this->authenticationService = $authenticationService; + } + + public function loginAction() + { + $data = $this->getRequest()->getPost(); + + $adapter = $this->authenticationService->getAdapter(); + $adapter->setIdentity($data['login']); + $adapter->setCredential($data['password']); + $authResult = $this->authenticationService->authenticate(); + + if ($authResult->isValid()) { + return $this->redirect()->toRoute('home'); + } + + return new ViewModel([ + 'error' => 'Your authentication credentials are not valid', + ]); + } + +Of course, doing this in the controller is not the best practice, and +you’d better move that kind of logic to a service layer. But this is how +it works. + +Note that when the authentication is valid, we first get the identity : + +.. code:: php + + $identity = $authenticationResult->getIdentity(); + +This will return the full entity (in our case, an +``Application\Entity\User`` instance). However, storing a full entity in +session is not a recommended practice. That’s why, when writing the +identity : + +.. code:: php + + $authService->getStorage()->write($identity); + +The storage automatically extracts ONLY the identifier values and only +store this in session (this avoid to store in session a serialized +entity, which is a bad practice). Later, when you want to retrieve the +logged user : + +.. code:: php + + $authenticationService = $services->get('Laminas\Authentication\AuthenticationService'); + $authenticatedUser = $authenticationService->getIdentity(); + +The authentication storage will automatically handle the conversion from +saved data to managed entity and the opposite. It will avoid serializing +entities since that is a strongly discouraged practice. + +View helper and controller helper +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may also need to know if there is an authenticated user within your +other controllers or in views. Laminas provides a controller plugin and +a view helper you may use. + +Here is how you use it in your controller : + +.. code:: php + + public function testAction() + { + if ($user = $this->identity()) { + // someone is logged ! + } else { + // not logged in + } + } + +And in your view : + +.. code:: php + + identity()) { + echo 'Logged in as ' . $this->escapeHtml($user->getUsername()); + } else { + echo 'Not logged in'; + } + ?> diff --git a/docs/en/caching.md b/docs/en/caching.md deleted file mode 100644 index d214273b1..000000000 --- a/docs/en/caching.md +++ /dev/null @@ -1,24 +0,0 @@ -# Caching - -DoctrineModule provides bridging between -[`Laminas\Cache`](https://github.com/laminas/laminas-cache) -and [`Doctrine\Common\Cache`](https://github.com/doctrine/common/tree/master/lib/Doctrine/Common/Cache). -This may be useful in case you want to share configured cache instances across doctrine, symfony -and laminas projects. - -You may use `Laminas\Cache` within your doctrine-related projects as following: - -```php -$laminasCache = new \Laminas\Cache\Storage\Adapter\Memory(); // any storage adapter is OK here -$doctrineCache = new \DoctrineModule\Cache\LaminasStorageCache($laminasCache); -// now use $doctrineCache as a normal Doctrine\Common\Cache\Cache instance -``` - -You may use `Doctrine\Common\Cache` within your Laminas projects as following: - -```php -$doctrineCache = new \Doctrine\Common\Cache\ArrayCache(); // any doctrine cache is OK here -$adapterOptions = new \Laminas\Cache\Storage\Adapter\AdapterOptions(); -$laminasCacheStorage = new \DoctrineModule\Cache\DoctrineCacheStorage($adapterOptions, $doctrineCache); -// now use $laminasCacheStorage as a normal Laminas\Cache\Storage\StorageInterface instance. -``` diff --git a/docs/en/caching.rst b/docs/en/caching.rst new file mode 100644 index 000000000..76d0a635f --- /dev/null +++ b/docs/en/caching.rst @@ -0,0 +1,27 @@ +Caching +======= + +DoctrineModule provides bridging between +```Laminas\Cache`` `__ and +```Doctrine\Common\Cache`` `__. +This may be useful in case you want to share configured cache instances +across doctrine, symfony and laminas projects. + +You may use ``Laminas\Cache`` within your doctrine-related projects as +following: + +.. code:: php + + $laminasCache = new \Laminas\Cache\Storage\Adapter\Memory(); // any storage adapter is OK here + $doctrineCache = new \DoctrineModule\Cache\LaminasStorageCache($laminasCache); + // now use $doctrineCache as a normal Doctrine\Common\Cache\Cache instance + +You may use ``Doctrine\Common\Cache`` within your Laminas projects as +following: + +.. code:: php + + $doctrineCache = new \Doctrine\Common\Cache\ArrayCache(); // any doctrine cache is OK here + $adapterOptions = new \Laminas\Cache\Storage\Adapter\AdapterOptions(); + $laminasCacheStorage = new \DoctrineModule\Cache\DoctrineCacheStorage($adapterOptions, $doctrineCache); + // now use $laminasCacheStorage as a normal Laminas\Cache\Storage\StorageInterface instance. diff --git a/docs/en/cli.md b/docs/en/cli.md deleted file mode 100644 index 506f35b4a..000000000 --- a/docs/en/cli.md +++ /dev/null @@ -1,42 +0,0 @@ -# Doctrine CLI -The Doctrine CLI has been pre-configured for you and works as is without any special configuration -required for MongoODM ODM and ORM. It will use your application's configuration for -entities or documents. - -Access the Doctrine command line through - -```sh -./vendor/bin/doctrine-module -``` - -Each command provides a description of itself if called with a `--help` argument. - -## Adding commands to the CLI - -You may add your own CLI commands by just creating new -[Symfony commands](http://symfony.com/doc/current/cookbook/console/console_command.html) -and attaching them to the provided CLI application as following: - - -```php -namespace My; - -use Laminas\EventManager\EventInterface; -use Laminas\ModuleManager\ModuleManagerInterface; - -class Module -{ - public function init(ModuleManagerInterface $manager) - { - $events = $manager->getEventManager()->getSharedManager(); - - // Attach to helper set event and load the entity manager helper. - $events->attach('doctrine', 'loadCli.post', function (EventInterface $e) { - /* @var $cli \Symfony\Component\Console\Application */ - $cli = $e->getTarget(); - - $cli->add(new \My\Own\Cli\Command()); - }); - } -} -``` diff --git a/docs/en/cli.rst b/docs/en/cli.rst new file mode 100644 index 000000000..43630c1ce --- /dev/null +++ b/docs/en/cli.rst @@ -0,0 +1,45 @@ +Doctrine CLI +============ + +The Doctrine CLI has been pre-configured for you and works as is without +any special configuration required for MongoODM ODM and ORM. It will use +your application’s configuration for entities or documents. + +Access the Doctrine command line through + +.. code:: sh + + ./vendor/bin/doctrine-module + +Each command provides a description of itself if called with a +``--help`` argument. + +Adding commands to the CLI +-------------------------- + +You may add your own CLI commands by just creating new `Symfony +commands `__ +and attaching them to the provided CLI application as following: + +.. code:: php + + namespace My; + + use Laminas\EventManager\EventInterface; + use Laminas\ModuleManager\ModuleManagerInterface; + + class Module + { + public function init(ModuleManagerInterface $manager) + { + $events = $manager->getEventManager()->getSharedManager(); + + // Attach to helper set event and load the entity manager helper. + $events->attach('doctrine', 'loadCli.post', function (EventInterface $e) { + /* @var $cli \Symfony\Component\Console\Application */ + $cli = $e->getTarget(); + + $cli->add(new \My\Own\Cli\Command()); + }); + } + } diff --git a/docs/en/form-element.md b/docs/en/form-element.md deleted file mode 100644 index 2dfed6642..000000000 --- a/docs/en/form-element.md +++ /dev/null @@ -1,331 +0,0 @@ -Form Elements -------------- - -DoctrineModule comes with functionality that can automatically fill the -`ValueOptions` of Select, MultiCheckbox or Radio Form Elements with data from a -`ObjectRepository`. - -### Usage - -Add a `DoctrineModule\Form\Element\ObjectSelect`, -`DoctrineModule\Form\Element\ObjectRadio` or -`DoctrineModule\Form\Element\ObjectMultiCheckbox` to your Form. For this to -work, you need to specify at least an `object_manager`, the `target_class` to -use and a `property` of the class to use as the Label. - -#### Example 1 : simple example - -```php -namespace Module\Form; - -use Laminas\Form\Form; -use DoctrineModule\Persistence\ObjectManagerAwareInterface; -use Doctrine\Persistence\ObjectManager; - -class MyForm extends Form implements ObjectManagerAwareInterface -{ - protected $objectManager; - - public function init() - { - $this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'property' => 'property', - ], - ]); - } - - public function setObjectManager(ObjectManager $objectManager) - { - $this->objectManager = $objectManager; - } - - public function getObjectManager() - { - return $this->objectManager; - } -} -``` - -When the Form gets rendered the `findAll` method of the `ObjectRepository` will -be executed by default. - -### Example 2 : modifying the label - -In times you want to change the display of the label you will need to use the -`label_generator` option. This option allows you to modify the label as much as -you like. In this simple example i will concatenate two properties with a dash. - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'label_generator' => function ($targetEntity) { - return $targetEntity->getId() . ' - ' . $targetEntity->getTitle(); - }, - ], -]); -``` - -The callable function will always receive the target entity as a parameter so -you will be able to use all functionalities your entities provide. Another -example would be to completely switch out the labels in case your website has -specific options to provide more accessible labels. - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'label_generator' => function ($targetEntity) use ($someSession) { - if ('accessible' === $someSession->getCurrentMode()) { - return $targetEntity->getAccessibleLabel(); - } - - return $targetEntity->getLabel(); - }, - ], -]); -``` - -### Example 3 : extended version - -If you don't need or want the entire repository you can specify a `find_method` -to use. This method must exist in the repository. The following example executes -the `findBy` method and passes in the specified parameters, but when using -custom repositories you can do even more advanced queries! Also you can specify -a method as a property by setting `is_method` to true. - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\User', - 'property' => 'ComposedOfSeveralProperties', - 'is_method' => true, - 'find_method' => [ - 'name' => 'findBy', - 'params' => [ - 'criteria' => ['active' => 1], - - // Use key 'orderBy' if using ORM - 'orderBy' => ['lastname' => 'ASC'], - - // Use key 'sort' if using ODM - 'sort' => ['lastname' => 'ASC'], - ], - ], - ], -]); -``` - -### Example 4 : including an empty option - -If you want to include an empty option at the top, set the `display_empty_item` -setting to true. You can also specify the `empty_item_label` setting, the -default is an empty string. - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'property' => 'property', - 'display_empty_item' => true, - 'empty_item_label' => '---', - ], -]); -``` - -### Example 5 : Add html attributes to the support - -Once lists become larger there's a big user-experience bonus when lists are groupt using the html attribute. -DoctrineModule provides this functionality with the `optgroup_identifier`. - -The assumption DoctrineModule does however is that your data structure has the optgroup-grouping in mind. See the -following example: - -**Add the Select list like this:** - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'property' => 'property', - 'optgroup_identifier' => 'category', - ], -]); -``` - -**With your data structure like this:** - -``` -id | property | category -1 | Football | sports -2 | Basketball | sports -3 | Spaghetti | food -``` - -**Will create a HTML Select list like this:** - -```html - -``` - -### Example 7: formatting on empty optgroups - -In case you define an `optgroup_identifier` and the data inside this column is empty or `null` you have two options of -rendering these cases. From a UX point of view you should group all "loose" entries inside a group that you call -"others" or the likes of that. But you're also able to render them without any grouping at all. Here's both examples: - -#### 7.1: Rendering without a default group - -To render without a default group you have to change nothing. This is the default behavior - -**Add the Select list like this:** - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'property' => 'property', - 'optgroup_identifier' => 'category', - ], -]); -``` - -**With your data structure like this:** - -``` -id | property | category -1 | Football | sports -2 | Basketball | -3 | Spaghetti | food -``` - -**Will create a HTML Select list like this:** - -```html - -``` - -Notice how the value for "Basketball" has not been wrapped with an `` element. - -#### 7.2: Rendering with a default group - -To group all loose values into a unified group, simply add the `optgroup_default` parameter to the options. - -**Add the Select list like this:** - -```php -$this->add([ - 'type' => 'DoctrineModule\Form\Element\ObjectSelect', - 'name' => 'name', - 'options' => [ - 'object_manager' => $this->getObjectManager(), - 'target_class' => 'Module\Entity\SomeEntity', - 'property' => 'property', - 'optgroup_identifier' => 'category', - 'optgroup_default' => 'Others', - ], -]); -``` - -**With your data structure like this:** - -``` -id | property | category -1 | Football | sports -2 | Basketball | -3 | Spaghetti | food -``` - -**Will create a HTML Select list like this:** - -```html - -``` diff --git a/docs/en/form-element.rst b/docs/en/form-element.rst new file mode 100644 index 000000000..f5ba295fb --- /dev/null +++ b/docs/en/form-element.rst @@ -0,0 +1,356 @@ +Form Elements +------------- + +DoctrineModule comes with functionality that can automatically fill the +``ValueOptions`` of Select, MultiCheckbox or Radio Form Elements with +data from a ``ObjectRepository``. + +Usage +~~~~~ + +Add a ``DoctrineModule\Form\Element\ObjectSelect``, +``DoctrineModule\Form\Element\ObjectRadio`` or +``DoctrineModule\Form\Element\ObjectMultiCheckbox`` to your Form. For +this to work, you need to specify at least an ``object_manager``, the +``target_class`` to use and a ``property`` of the class to use as the +Label. + +Example 1 : simple example +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: php + + namespace Module\Form; + + use Laminas\Form\Form; + use DoctrineModule\Persistence\ObjectManagerAwareInterface; + use Doctrine\Persistence\ObjectManager; + + class MyForm extends Form implements ObjectManagerAwareInterface + { + protected $objectManager; + + public function init() + { + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + ], + ]); + } + + public function setObjectManager(ObjectManager $objectManager) + { + $this->objectManager = $objectManager; + } + + public function getObjectManager() + { + return $this->objectManager; + } + } + +When the Form gets rendered the ``findAll`` method of the +``ObjectRepository`` will be executed by default. + +Example 2 : modifying the label +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In times you want to change the display of the label you will need to +use the ``label_generator`` option. This option allows you to modify the +label as much as you like. In this simple example i will concatenate two +properties with a dash. + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'label_generator' => function ($targetEntity) { + return $targetEntity->getId() . ' - ' . $targetEntity->getTitle(); + }, + ], + ]); + +The callable function will always receive the target entity as a +parameter so you will be able to use all functionalities your entities +provide. Another example would be to completely switch out the labels in +case your website has specific options to provide more accessible +labels. + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'label_generator' => function ($targetEntity) use ($someSession) { + if ('accessible' === $someSession->getCurrentMode()) { + return $targetEntity->getAccessibleLabel(); + } + + return $targetEntity->getLabel(); + }, + ], + ]); + +Example 3 : extended version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you don’t need or want the entire repository you can specify a +``find_method`` to use. This method must exist in the repository. The +following example executes the ``findBy`` method and passes in the +specified parameters, but when using custom repositories you can do even +more advanced queries! Also you can specify a method as a property by +setting ``is_method`` to true. + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\User', + 'property' => 'ComposedOfSeveralProperties', + 'is_method' => true, + 'find_method' => [ + 'name' => 'findBy', + 'params' => [ + 'criteria' => ['active' => 1], + + // Use key 'orderBy' if using ORM + 'orderBy' => ['lastname' => 'ASC'], + + // Use key 'sort' if using ODM + 'sort' => ['lastname' => 'ASC'], + ], + ], + ], + ]); + +Example 4 : including an empty option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to include an empty option at the top, set the +``display_empty_item`` setting to true. You can also specify the +``empty_item_label`` setting, the default is an empty string. + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + 'display_empty_item' => true, + 'empty_item_label' => '---', + ], + ]); + +Example 5 : Add html attributes to the elements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To set custom HTML attributes on each ``valueOption`` you can use the +``option_attributes`` setting to specify an array of key/value pairs +whereby the keys represent a valid HTML attribute (data-*, aria-*, +onEvent, etc.). + +The value needs to be of type ``string`` or ``callable`` (in which case +a ``string`` - or something able to be casted to string - needs to be +returned). Check the following example: + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'test', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + 'option_attributes' => [ + 'class' => 'styledOption', + 'data-id' => function (\Module\Entity\SomeEntity $entity) { + return $entity->getId(); + }, + ], + ], + ]); + +The above example will generate HTML options with a data-key attribute: + +.. code:: html + + + +It is noteworthy that, when working with an option_attribute value of +type ``callable``, you do **not** need to define the fully qualified +classname into the function. The object passed into the function will +always be identical to the type you define on the key ``target_class``. + +Example 6: Implementing support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once lists become larger there’s a big user-experience bonus when lists +are groupt using the html attribute. DoctrineModule provides this +functionality with the ``optgroup_identifier``. + +The assumption DoctrineModule does however is that your data structure +has the optgroup-grouping in mind. See the following example: + +**Add the Select list like this:** + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + 'optgroup_identifier' => 'category', + ], + ]); + +**With your data structure like this:** + +:: + + id | property | category + 1 | Football | sports + 2 | Basketball | sports + 3 | Spaghetti | food + +**Will create a HTML Select list like this:** + +.. code:: html + + + +Example 7: formatting on empty optgroups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In case you define an ``optgroup_identifier`` and the data inside this +column is empty or ``null`` you have two options of rendering these +cases. From a UX point of view you should group all “loose” entries +inside a group that you call “others” or the likes of that. But you’re +also able to render them without any grouping at all. Here’s both +examples: + +7.1: Rendering without a default group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To render without a default group you have to change nothing. This is +the default behavior + +**Add the Select list like this:** + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + 'optgroup_identifier' => 'category', + ], + ]); + +**With your data structure like this:** + +:: + + id | property | category + 1 | Football | sports + 2 | Basketball | + 3 | Spaghetti | food + +**Will create a HTML Select list like this:** + +.. code:: html + + + +Notice how the value for “Basketball” has not been wrapped with an +```` element. + +7.2: Rendering with a default group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To group all loose values into a unified group, simply add the +``optgroup_default`` parameter to the options. + +**Add the Select list like this:** + +.. code:: php + + $this->add([ + 'type' => 'DoctrineModule\Form\Element\ObjectSelect', + 'name' => 'name', + 'options' => [ + 'object_manager' => $this->getObjectManager(), + 'target_class' => 'Module\Entity\SomeEntity', + 'property' => 'property', + 'optgroup_identifier' => 'category', + 'optgroup_default' => 'Others', + ], + ]); + +**With your data structure like this:** + +:: + + id | property | category + 1 | Football | sports + 2 | Basketball | + 3 | Spaghetti | food + +**Will create a HTML Select list like this:** + +.. code:: html + + diff --git a/docs/en/index.md b/docs/en/index.md deleted file mode 100644 index 69c3ce538..000000000 --- a/docs/en/index.md +++ /dev/null @@ -1,19 +0,0 @@ -# DoctrineModule - -DoctrineModule provides a bridge between Laminas and Doctrine 2. -It gives you access to features that can be used across Doctrine 2 ORM as well as Doctrine 2 ODM. -It provides an abstraction layer on top of [`Doctrine\Common`](https://github.com/doctrine/common) -which allows the end user to build functionality being completely unaware if he's currently working -with Doctrine ORM or Doctrine MongoDB ODM. - -To use Doctrine ORM or ODM, you will need [DoctrineORMModule](https://github.com/doctrine/DoctrineORMModule) -or [DoctrineMongoODMModule](https://github.com/doctrine/DoctrineMongoODMModule) respectively. - -You can find more details about the features offered by DoctrineModule: - -* [Authentication documentation](https://github.com/doctrine/DoctrineModule/blob/master/docs/authentication.md): this explains how you can use the DoctrineModule authentication adapter and authentication storage adapter to provide a simple way to authenticate users using Doctrine. -* [Caching documentation](https://github.com/doctrine/DoctrineModule/blob/master/docs/caching.md): DoctrineModule provides simple classes to allow easier caching using Doctrine. -* [CLI documentation](https://github.com/doctrine/DoctrineModule/blob/master/docs/cli.md): learn how to use the Doctrine 2 command line tool, and how to add your own command. -* [Hydrator documentation](https://github.com/doctrine/doctrine-laminas-hydrator/blob/master/README.md): if you are using Laminas Forms (and I hope you are !), doctrine-laminas-hydrator provides a powerful hydrator that allows you to easily deal with OneToOne, OneToMany and ManyToOne relationships when using forms. -* [Paginator documentation](https://github.com/doctrine/DoctrineModule/blob/master/docs/paginator.md): discover how to use the DoctrineModule Paginator adapter. -* [Validator documentation](https://github.com/doctrine/DoctrineModule/blob/master/docs/validator.md): this chapter explains how to use ObjectExists and NoObjectExists validator, that allow you to easily validate if a given entity exists or not. diff --git a/docs/en/index.rst b/docs/en/index.rst new file mode 100644 index 000000000..3e5f01d15 --- /dev/null +++ b/docs/en/index.rst @@ -0,0 +1,44 @@ +DoctrineModule +============== + +DoctrineModule provides a bridge between Laminas and Doctrine 2. It +gives you access to features that can be used across Doctrine 2 ORM as +well as Doctrine 2 ODM. It provides an abstraction layer on top of +```Doctrine\Common`` `__ which +allows the end user to build functionality being completely unaware if +he’s currently working with Doctrine ORM or Doctrine MongoDB ODM. + +To use Doctrine ORM or ODM, you will need +`DoctrineORMModule `__ or +`DoctrineMongoODMModule `__ +respectively. + +You can find more details about the features offered by DoctrineModule: + +- `Authentication + documentation `__: + this explains how you can use the DoctrineModule authentication + adapter and authentication storage adapter to provide a simple way to + authenticate users using Doctrine. +- `Caching + documentation `__: + DoctrineModule provides simple classes to allow easier caching using + Doctrine. +- `CLI + documentation `__: + learn how to use the Doctrine 2 command line tool, and how to add + your own command. +- `Hydrator + documentation `__: + if you are using Laminas Forms (and I hope you are !), + doctrine-laminas-hydrator provides a powerful hydrator that allows + you to easily deal with OneToOne, OneToMany and ManyToOne + relationships when using forms. +- `Paginator + documentation `__: + discover how to use the DoctrineModule Paginator adapter. +- `Validator + documentation `__: + this chapter explains how to use ObjectExists and NoObjectExists + validator, that allow you to easily validate if a given entity exists + or not. diff --git a/docs/en/paginator.md b/docs/en/paginator.md deleted file mode 100644 index 85e32d60c..000000000 --- a/docs/en/paginator.md +++ /dev/null @@ -1,80 +0,0 @@ -## Paginator - -### Collection adapter - -DoctrineModule provides a simple Paginator adapter that can be used with DoctrineCollection. - -> Note : if you are using Doctrine 2 ORM, what you are looking for is probably a Paginator adapter that can be used with Doctrine 2 Paginators. Luckily, DoctrineORMModule provides such a paginator adapter. You can find the documentation here : - -#### Simple example - -Here is how you can use the DoctrineModule paginator adapter : - -```php -use Doctrine\Common\Collections\ArrayCollection; -use DoctrineModule\Paginator\Adapter\Collection as CollectionAdapter; -use Laminas\Paginator\Paginator; - -// Create a Doctrine 2 Collection -$doctrineCollection = new ArrayCollection(range(1, 101)); - -// Create the adapter -$adapter = new CollectionAdapter($doctrineCollection); - -// Create the paginator itself -$paginator = new Paginator($adapter); -$paginator->setCurrentPageNumber(1) - ->setItemCountPerPage(5); - -// Pass it to the view, and use it like a "standard" Laminas paginator -``` - -For more information about Laminas paginator, please read the [laminas-paginator documentation](https://docs.laminas.dev/laminas-paginator/). - -### Selectable adapter - -DoctrineModule also provides another paginator adapter that is based on new Selectable and Criteria interfaces from -Doctrine >= 2.3. It works with any Selectable objects (ObjectRepository for instance). - -#### Simple example - -You can use it without any existing Criteria object: - -```php -use DoctrineModule\Paginator\Adapter\Selectable as SelectableAdapter; -use Laminas\Paginator\Paginator; - -// Create the adapter -$adapter = new SelectableAdapter($objectRepository); // An object repository implements Selectable - -// Create the paginator itself -$paginator = new Paginator($adapter); -$paginator->setCurrentPageNumber(1) - ->setItemCountPerPage(5); - -// Pass it to the view, and use it like a "standard" Laminas paginator -``` - -If you want to further filter the results, you can optionally pass an existing Criteria object: - -```php -use Doctrine\Common\Collections\Criteria as DoctrineCriteria; -use DoctrineModule\Paginator\Adapter\Selectable as SelectableAdapter; -use Laminas\Paginator\Paginator; - -// Create the criteria -$expr = DoctrineCriteria::expr()->eq('foo', 'bar'); -$criteria = new DoctrineCriteria($expr); - -// Create the adapter -$adapter = new SelectableAdapter($objectRepository, $criteria); // An object repository implements Selectable - -// Create the paginator itself -$paginator = new Paginator($adapter); -$paginator->setCurrentPageNumber(1) - ->setItemCountPerPage(5); - -// Pass it to the view, and use it like a "standard" Laminas paginator -``` - -For more information about Laminas paginator, please read the [laminas-paginator documentation](https://docs.laminas.dev/laminas-paginator/). diff --git a/docs/en/paginator.rst b/docs/en/paginator.rst new file mode 100644 index 000000000..c6cef78f7 --- /dev/null +++ b/docs/en/paginator.rst @@ -0,0 +1,97 @@ +Paginator +--------- + +Collection adapter +~~~~~~~~~~~~~~~~~~ + +DoctrineModule provides a simple Paginator adapter that can be used with +DoctrineCollection. + + Note : if you are using Doctrine 2 ORM, what you are looking for is + probably a Paginator adapter that can be used with Doctrine 2 + Paginators. Luckily, DoctrineORMModule provides such a paginator + adapter. You can find the documentation here : + +Simple example +^^^^^^^^^^^^^^ + +Here is how you can use the DoctrineModule paginator adapter : + +.. code:: php + + use Doctrine\Common\Collections\ArrayCollection; + use DoctrineModule\Paginator\Adapter\Collection as CollectionAdapter; + use Laminas\Paginator\Paginator; + + // Create a Doctrine 2 Collection + $doctrineCollection = new ArrayCollection(range(1, 101)); + + // Create the adapter + $adapter = new CollectionAdapter($doctrineCollection); + + // Create the paginator itself + $paginator = new Paginator($adapter); + $paginator->setCurrentPageNumber(1) + ->setItemCountPerPage(5); + + // Pass it to the view, and use it like a "standard" Laminas paginator + +For more information about Laminas paginator, please read the +`laminas-paginator +documentation `__. + +Selectable adapter +~~~~~~~~~~~~~~~~~~ + +DoctrineModule also provides another paginator adapter that is based on +new Selectable and Criteria interfaces from Doctrine >= 2.3. It works +with any Selectable objects (ObjectRepository for instance). + +.. _simple-example-1: + +Simple example +^^^^^^^^^^^^^^ + +You can use it without any existing Criteria object: + +.. code:: php + + use DoctrineModule\Paginator\Adapter\Selectable as SelectableAdapter; + use Laminas\Paginator\Paginator; + + // Create the adapter + $adapter = new SelectableAdapter($objectRepository); // An object repository implements Selectable + + // Create the paginator itself + $paginator = new Paginator($adapter); + $paginator->setCurrentPageNumber(1) + ->setItemCountPerPage(5); + + // Pass it to the view, and use it like a "standard" Laminas paginator + +If you want to further filter the results, you can optionally pass an +existing Criteria object: + +.. code:: php + + use Doctrine\Common\Collections\Criteria as DoctrineCriteria; + use DoctrineModule\Paginator\Adapter\Selectable as SelectableAdapter; + use Laminas\Paginator\Paginator; + + // Create the criteria + $expr = DoctrineCriteria::expr()->eq('foo', 'bar'); + $criteria = new DoctrineCriteria($expr); + + // Create the adapter + $adapter = new SelectableAdapter($objectRepository, $criteria); // An object repository implements Selectable + + // Create the paginator itself + $paginator = new Paginator($adapter); + $paginator->setCurrentPageNumber(1) + ->setItemCountPerPage(5); + + // Pass it to the view, and use it like a "standard" Laminas paginator + +For more information about Laminas paginator, please read the +`laminas-paginator +documentation `__. diff --git a/docs/en/validator.md b/docs/en/validator.md deleted file mode 100644 index 26c5d9f28..000000000 --- a/docs/en/validator.md +++ /dev/null @@ -1,176 +0,0 @@ -Validator -========= - -DoctrineModule provides three validators that work out the box: `DoctrineModule\Validator\ObjectExists` and `DoctrineModule\Validator\NoObjectExists` which implements a check if an entity exists or does not exists in the database, respectively, and `DoctrineModule\Validator\UniqueObject` which implements a check if a value is only used in one object. They behave like any other standard Laminas validator. - -All three validators accept the following options : - -* `object_repository` : an instance of an object repository. -* `fields` : an array that contains all the fields that are used to check if the entity exists (or does not). - -The `DoctrineModule\Validator\UniqueObject` also needs the following option: - -* `object_manager` : an instance of an object manager. - -For the `use_context` option and other specifics to `DoctrineModule\Validator\UniqueObject` see [below](#uniqueobject). - -> Tip : to get an object repository from an object manager you call the `getRepository` function of any valid object manager instance, passing it the FQCN of the class. For instance, in the context of Doctrine 2 ORM, here is how you get the `object_repository` of the 'Application\Entity\User' entity: - -```php -$repository = $entityManager->getRepository('Application\Entity\User'); -``` - -### Simple usage - -You can directly instantiate a validator the following way: - -```php -$validator = new \DoctrineModule\Validator\ObjectExists([ - 'object_repository' => $objectManager->getRepository('Application\Entity\User'), - 'fields' => ['email'], -]); - -var_dump($validator->isValid('test@example.com')); // dumps 'true' if an entity matches -var_dump($validator->isValid(['email' => 'test@example.com'])); // dumps 'true' if an entity matches -``` - - -### Use together with Laminas forms - -Of course, validators are especially useful when paired with forms. To add a `NoObjectExists` validator to a Laminas form element: - -```php -namespace Application\Form; - -use DoctrineModule\Validator\NoObjectExists as NoObjectExistsValidator; -use Laminas\Form\Form; -use Laminas\ServiceManager\ServiceManager; -use Application\Entity; - -class User extends Form -{ - public function __construct(ServiceManager $serviceManager) - { - parent::__construct('my-form'); - - // Add an element - $this->add([ - 'type' => 'Laminas\Form\Element\Email', - 'name' => 'email', - 'options' => [ - 'label' => 'Email', - ], - 'attributes' => [ - 'required' => 'required', - ], - ]); - - // add other elements (submit, CSRF…) - - // Fetch any valid object manager from the Service manager - $entityManager = $serviceManager->get('doctrine.entitymanager.orm_default'); - - // Now get the input filter of the form, and add the validator to the email input - $emailInput = $this->getInputFilter()->get('email'); - - $noObjectExistsValidator = new NoObjectExistsValidator([ - 'object_repository' => $entityManager->getRepository(Entity\User::class), - 'fields' => 'email', - ]); - - $emailInput - ->getValidatorChain() - ->attach($noObjectExistsValidator); - } -} -``` - -If you are using fieldsets you can directly add the validator using the array notation. For instance in the `getInputFilterSpecification` function, as shown here: - -```php -namespace Application\Form; - -use Laminas\Form\Fieldset; -use Laminas\InputFilter\InputFilterProviderInterface; -use Laminas\ServiceManager\ServiceManager; -use Application\Entity; - -class UserFieldset extends Fieldset implements InputFilterProviderInterface -{ - protected $serviceManager; - - public function __construct(ServiceManager $serviceManager) - { - $this->serviceManager = $serviceManager; - - parent::__construct('my-fieldset'); - - // Add an element - $this->add([ - 'type' => 'Laminas\Form\Element\Email', - 'name' => 'email', - 'options' => [ - 'label' => 'Email', - ], - 'attributes' => [ - 'required' => 'required', - ], - ]); - } - - public function getInputFilterSpecification() - { - $entityManager = $this->serviceManager->get('doctrine.entitymanager.orm_default'); - - return [ - 'email' => [ - 'validators' => [ - [ - 'name' => 'DoctrineModule\Validator\NoObjectExists', - 'options' => [ - 'object_repository' => $entityManager->getRepository(Entity\User::class), - 'fields' => 'email', - ], - ], - ], - ], - ]; - } -} -``` - -You can change the default message of the validators like this: - -```php -// For NoObjectExists validator (using array notation) : -'validators' => [ - [ - 'name' => 'DoctrineModule\Validator\NoObjectExists', - 'options' => [ - 'object_repository' => $this->getEntityManager()->getRepository('Application\Entity\User'), - 'fields' => 'email', - 'messages' => [ - 'objectFound' => 'A user with this email already exists.', - ], - ], - ], -], - -// For ObjectExists validator (using object notation) : -$objectExistsValidator = new \DoctrineModule\Validator\ObjectExists([ - 'object_repository' => $entityManager->getRepository('Application\Entity\User'), - 'fields' => 'email', -]); - -**$objectExistsValidator->setMessage('noObjectFound', 'Email was not found.');** -``` - - -### UniqueObject - -There are two things you have to think about when using `DoctrineModule\Validator\UniqueObject`; As mentioned above you have to pass an ObjectManager as `object_manager` option and second you have to pass a value for every identifier your entity has. - -* If you leave out the `use_context` option or set it to `false` you have to pass an array containing the `fields`- and `identifier`-values into `isValid()`. When using `Laminas\Form` this behaviour is needed if you're using fieldsets. -* If you set the `use_context` option to `true` you have to pass the `fields`-values as first argument and an array containing the `identifier`-values as second argument into `isValid()`. When using `Laminas\Form` without fieldsets, this behaviour would be needed. - -__Important:__ Whatever you choose, please ensure that the `identifier`-values are named by the field-names, not by the database-column. diff --git a/docs/en/validator.rst b/docs/en/validator.rst new file mode 100644 index 000000000..e549b9356 --- /dev/null +++ b/docs/en/validator.rst @@ -0,0 +1,205 @@ +Validator +========= + +DoctrineModule provides three validators that work out the box: +``DoctrineModule\Validator\ObjectExists`` and +``DoctrineModule\Validator\NoObjectExists`` which implements a check if +an entity exists or does not exists in the database, respectively, and +``DoctrineModule\Validator\UniqueObject`` which implements a check if a +value is only used in one object. They behave like any other standard +Laminas validator. + +All three validators accept the following options : + +- ``object_repository`` : an instance of an object repository. +- ``fields`` : an array that contains all the fields that are used to + check if the entity exists (or does not). + +The ``DoctrineModule\Validator\UniqueObject`` also needs the following +option: + +- ``object_manager`` : an instance of an object manager. + +For the ``use_context`` option and other specifics to +``DoctrineModule\Validator\UniqueObject`` see `below <#uniqueobject>`__. + + Tip : to get an object repository from an object manager you call the + ``getRepository`` function of any valid object manager instance, + passing it the FQCN of the class. For instance, in the context of + Doctrine 2 ORM, here is how you get the ``object_repository`` of the + ‘Application:raw-latex:`\Entity`:raw-latex:`\User`’ entity: + +.. code:: php + + $repository = $entityManager->getRepository('Application\Entity\User'); + +Simple usage +~~~~~~~~~~~~ + +You can directly instantiate a validator the following way: + +.. code:: php + + $validator = new \DoctrineModule\Validator\ObjectExists([ + 'object_repository' => $objectManager->getRepository('Application\Entity\User'), + 'fields' => ['email'], + ]); + + var_dump($validator->isValid('test@example.com')); // dumps 'true' if an entity matches + var_dump($validator->isValid(['email' => 'test@example.com'])); // dumps 'true' if an entity matches + +Use together with Laminas forms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Of course, validators are especially useful when paired with forms. To +add a ``NoObjectExists`` validator to a Laminas form element: + +.. code:: php + + namespace Application\Form; + + use DoctrineModule\Validator\NoObjectExists as NoObjectExistsValidator; + use Laminas\Form\Form; + use Laminas\ServiceManager\ServiceManager; + use Application\Entity; + + class User extends Form + { + public function __construct(ServiceManager $serviceManager) + { + parent::__construct('my-form'); + + // Add an element + $this->add([ + 'type' => 'Laminas\Form\Element\Email', + 'name' => 'email', + 'options' => [ + 'label' => 'Email', + ], + 'attributes' => [ + 'required' => 'required', + ], + ]); + + // add other elements (submit, CSRF…) + + // Fetch any valid object manager from the Service manager + $entityManager = $serviceManager->get('doctrine.entitymanager.orm_default'); + + // Now get the input filter of the form, and add the validator to the email input + $emailInput = $this->getInputFilter()->get('email'); + + $noObjectExistsValidator = new NoObjectExistsValidator([ + 'object_repository' => $entityManager->getRepository(Entity\User::class), + 'fields' => 'email', + ]); + + $emailInput + ->getValidatorChain() + ->attach($noObjectExistsValidator); + } + } + +If you are using fieldsets you can directly add the validator using the +array notation. For instance in the ``getInputFilterSpecification`` +function, as shown here: + +.. code:: php + + namespace Application\Form; + + use Laminas\Form\Fieldset; + use Laminas\InputFilter\InputFilterProviderInterface; + use Laminas\ServiceManager\ServiceManager; + use Application\Entity; + + class UserFieldset extends Fieldset implements InputFilterProviderInterface + { + protected $serviceManager; + + public function __construct(ServiceManager $serviceManager) + { + $this->serviceManager = $serviceManager; + + parent::__construct('my-fieldset'); + + // Add an element + $this->add([ + 'type' => 'Laminas\Form\Element\Email', + 'name' => 'email', + 'options' => [ + 'label' => 'Email', + ], + 'attributes' => [ + 'required' => 'required', + ], + ]); + } + + public function getInputFilterSpecification() + { + $entityManager = $this->serviceManager->get('doctrine.entitymanager.orm_default'); + + return [ + 'email' => [ + 'validators' => [ + [ + 'name' => 'DoctrineModule\Validator\NoObjectExists', + 'options' => [ + 'object_repository' => $entityManager->getRepository(Entity\User::class), + 'fields' => 'email', + ], + ], + ], + ], + ]; + } + } + +You can change the default message of the validators like this: + +.. code:: php + + // For NoObjectExists validator (using array notation) : + 'validators' => [ + [ + 'name' => 'DoctrineModule\Validator\NoObjectExists', + 'options' => [ + 'object_repository' => $this->getEntityManager()->getRepository('Application\Entity\User'), + 'fields' => 'email', + 'messages' => [ + 'objectFound' => 'A user with this email already exists.', + ], + ], + ], + ], + + // For ObjectExists validator (using object notation) : + $objectExistsValidator = new \DoctrineModule\Validator\ObjectExists([ + 'object_repository' => $entityManager->getRepository('Application\Entity\User'), + 'fields' => 'email', + ]); + + **$objectExistsValidator->setMessage('noObjectFound', 'Email was not found.');** + +UniqueObject +~~~~~~~~~~~~ + +There are two things you have to think about when using +``DoctrineModule\Validator\UniqueObject``; As mentioned above you have +to pass an ObjectManager as ``object_manager`` option and second you +have to pass a value for every identifier your entity has. + +- If you leave out the ``use_context`` option or set it to ``false`` + you have to pass an array containing the ``fields``- and + ``identifier``-values into ``isValid()``. When using ``Laminas\Form`` + this behaviour is needed if you’re using fieldsets. +- If you set the ``use_context`` option to ``true`` you have to pass + the ``fields``-values as first argument and an array containing the + ``identifier``-values as second argument into ``isValid()``. When + using ``Laminas\Form`` without fieldsets, this behaviour would be + needed. + +**Important:** Whatever you choose, please ensure that the +``identifier``-values are named by the field-names, not by the +database-column. From 167f43ab16985854d5182ea24dc30eabc6820ede Mon Sep 17 00:00:00 2001 From: Dennis Riehle Date: Mon, 18 Oct 2021 11:02:48 +0200 Subject: [PATCH 3/5] added `.doctrine-project.json` --- .doctrine-project.json | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .doctrine-project.json diff --git a/.doctrine-project.json b/.doctrine-project.json new file mode 100644 index 000000000..d075bed51 --- /dev/null +++ b/.doctrine-project.json @@ -0,0 +1,31 @@ +{ + "active": true, + "name": "Doctrine Module for Laminas", + "slug": "DoctrineModule", + "docsSlug": "doctrine-module", + "versions": [ + { + "name": "4.2", + "branchName": "4.2.x", + "slug": "latest", + "upcoming": true + }, + { + "name": "4.1", + "branchName": "4.1.x", + "slug": "4.1", + "aliases": [ + "current", + "stable" + ], + "current": true, + "maintained": true + }, + { + "name": "4.0", + "branchName": "4.0.x", + "slug": "4.0", + "maintained": false + } + ] +} From 4cb0a561fa2fb1ee71694e5bc24b33ee899e7905 Mon Sep 17 00:00:00 2001 From: Dennis Riehle Date: Mon, 18 Oct 2021 14:34:53 +0200 Subject: [PATCH 4/5] updated README.md, remove Travis --- .travis.yml | 51 --------------------------------------------------- README.md | 6 +++--- 2 files changed, 3 insertions(+), 54 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 13dfc6b4f..000000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -sudo: false - -language: php - -cache: - directories: - - $HOME/.composer/cache - -env: - global: - - COMPOSER_ARGS="--no-interaction" - -matrix: - fast_finish: true - include: - - php: 7.2 - env: - - DEPS=lowest - - php: 7.2 - env: - - DEPS=latest - - TEST_COVERAGE=true - - php: 7.2 - env: - - DEPS=dev - - php: 7.3 - env: - - DEPS=latest - - php: 7.4 - env: - - DEPS=latest - - php: 8.0 - env: - - DEPS=latest - -before_install: - - travis_retry composer self-update - -install: - - if [[ $DEPS == 'dev' ]]; then travis_retry composer config minimum-stability dev ; fi - - if [[ $DEPS == 'latest' || $DEPS == 'dev' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - - travis_retry composer install $COMPOSER_ARGS - - composer show - -script: - - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi - - if [[ $TEST_COVERAGE == 'true' ]]; then php build/coverage-checker.php build/clover.xml 70 ; fi - -after_success: - - if [[ $TEST_COVERAGE == 'true' ]]; then bash <(curl -s https://codecov.io/bash) -f ./build/clover.xml; fi diff --git a/README.md b/README.md index c40543039..e5b224f46 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # DoctrineModule for Laminas -[![Master Branch Build Status](https://secure.travis-ci.org/doctrine/DoctrineModule.png?branch=master)](http://travis-ci.org/doctrine/DoctrineModule) +[![Build Status](https://github.com/doctrine/DoctrineModule/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/DoctrineModule/actions/workflows/continuous-integration.yml?query=branch%3A4.1.x+) [![Code Coverage](https://codecov.io/github/doctrine/DoctrineModule/coverage.svg?branch=4.1.x)](https://codecov.io/gh/doctrine/DoctrineModule/branch/4.1.x) DoctrineModule provides basic functionality consumed by [DoctrineORMModule](http://www.github.com/doctrine/DoctrineORMModule) -(if you want to use [Doctrine ORM](https://github.com/doctrine/doctrine2)) +(if you want to use [Doctrine ORM](https://github.com/doctrine/orm)) and [DoctrineMongoODMModule](https://github.com/doctrine/DoctrineMongoODMModule) -(if you want to use [MongoDB ODM](https://github.com/doctrine/mongodb-odm)) +(if you want to use [MongoDB ODM](https://github.com/doctrine/mongodb-odm)). ## Documentation From 6a20afc448a00931519beb80b4e73d595d47f2cd Mon Sep 17 00:00:00 2001 From: Dennis Riehle Date: Mon, 18 Oct 2021 14:55:13 +0200 Subject: [PATCH 5/5] fixed issues caused by RST conversion --- docs/en/authentication.rst | 2 +- docs/en/caching.rst | 4 ++-- docs/en/index.rst | 2 +- docs/en/validator.rst | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/authentication.rst b/docs/en/authentication.rst index 3b97ab3fc..ece8bc0c8 100644 --- a/docs/en/authentication.rst +++ b/docs/en/authentication.rst @@ -58,7 +58,7 @@ Here are some explanations about the keys: ``Doctrine\Persistence\ObjectManager`` or a single string that will fetched from the Service Manager in order to get a concrete instance. If you are using DoctrineORMModule, you can simply write - ‘Doctrine:raw-latex:`\ORM`:raw-latex:`\EntityManager`’ (as the + ``Doctrine\ORM\EntityManager`` (as the EntityManager implements the class ``Doctrine\Persistence\ObjectManager``). - the ``identity_class`` contains the FQCN of the entity that will be diff --git a/docs/en/caching.rst b/docs/en/caching.rst index 76d0a635f..cded6d45e 100644 --- a/docs/en/caching.rst +++ b/docs/en/caching.rst @@ -2,8 +2,8 @@ Caching ======= DoctrineModule provides bridging between -```Laminas\Cache`` `__ and -```Doctrine\Common\Cache`` `__. +`Laminas\Cache `__ and +`Doctrine\Common\Cache `__. This may be useful in case you want to share configured cache instances across doctrine, symfony and laminas projects. diff --git a/docs/en/index.rst b/docs/en/index.rst index 3e5f01d15..272ee011a 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -4,7 +4,7 @@ DoctrineModule DoctrineModule provides a bridge between Laminas and Doctrine 2. It gives you access to features that can be used across Doctrine 2 ORM as well as Doctrine 2 ODM. It provides an abstraction layer on top of -```Doctrine\Common`` `__ which +`Doctrine\Common `__ which allows the end user to build functionality being completely unaware if he’s currently working with Doctrine ORM or Doctrine MongoDB ODM. diff --git a/docs/en/validator.rst b/docs/en/validator.rst index e549b9356..d09ca0e53 100644 --- a/docs/en/validator.rst +++ b/docs/en/validator.rst @@ -27,7 +27,7 @@ For the ``use_context`` option and other specifics to ``getRepository`` function of any valid object manager instance, passing it the FQCN of the class. For instance, in the context of Doctrine 2 ORM, here is how you get the ``object_repository`` of the - ‘Application:raw-latex:`\Entity`:raw-latex:`\User`’ entity: + ``Application\Entity\User`` entity: .. code:: php