├── Uploadable
├── MimeTypeGuesserAdapter.php
├── ValidatorConfigurator.php
├── UploadedFileInfo.php
└── UploadableManager.php
├── StofDoctrineExtensionsBundle.php
├── README.markdown
├── Upgrade_to_1_1.md
├── Resources
├── config
│ ├── tree.xml
│ ├── sortable.xml
│ ├── sluggable.xml
│ ├── timestampable.xml
│ ├── softdeleteable.xml
│ ├── reference_integrity.xml
│ ├── loggable.xml
│ ├── blameable.xml
│ ├── translatable.xml
│ └── uploadable.xml
└── doc
│ ├── softdeleteable-filter.rst
│ ├── uploadable-extension.rst
│ ├── advanced.rst
│ ├── installation.rst
│ ├── index.rst
│ └── configuration.rst
├── DependencyInjection
├── Compiler
│ └── ValidateExtensionConfigurationPass.php
├── StofDoctrineExtensionsExtension.php
└── Configuration.php
├── LICENSE
├── EventListener
├── LocaleListener.php
├── LoggerListener.php
└── BlameListener.php
├── CHANGELOG.md
└── composer.json
/Uploadable/MimeTypeGuesserAdapter.php:
--------------------------------------------------------------------------------
1 | guessMimeType($filePath);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/StofDoctrineExtensionsBundle.php:
--------------------------------------------------------------------------------
1 | addCompilerPass(new ValidateExtensionConfigurationPass());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | # StofDoctrineExtensionsBundle
2 |
3 | This bundle provides integration for
4 | [DoctrineExtensions](https://github.com/Atlantic18/DoctrineExtensions) in
5 | your Symfony Project.
6 |
7 | [](https://packagist.org/packages/stof/doctrine-extensions-bundle)
8 | [](https://packagist.org/packages/stof/doctrine-extensions-bundle)
9 |
10 | For documentation, see it [online](https://symfony.com/doc/master/bundles/StofDoctrineExtensionsBundle/index.html)
11 |
12 | License: [MIT](LICENSE)
13 |
--------------------------------------------------------------------------------
/Uploadable/ValidatorConfigurator.php:
--------------------------------------------------------------------------------
1 | validateWritableDirectory = $validateWritableDirectory;
20 | }
21 |
22 | public function configure()
23 | {
24 | Validator::$validateWritableDirectory = $this->validateWritableDirectory;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Upgrade_to_1_1.md:
--------------------------------------------------------------------------------
1 | Upgrading from 1.0 to 1.1
2 | =========================
3 |
4 | This file describes the needed changes when upgrading from 1.0 to 1.1
5 |
6 | ### Bumped the requirements
7 |
8 | The bundle now requires Symfony 2.1 and the 2.3 version of the Gedmo extensions
9 | (which is the master branch at the time of this writing)
10 |
11 | ### Removed the duplicated entities.
12 |
13 | The bundle no longer duplicates the entities provided by the extensions
14 | to make the maintenance easier. You need to configure the mapping explicitly
15 | for the extensions as DoctrineBundle cannot guess it.
16 | See the updated documentation about registering the mapping for the way to
17 | register them.
18 |
--------------------------------------------------------------------------------
/Resources/config/tree.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Tree\TreeListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/config/sortable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Sortable\SortableListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/config/sluggable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Sluggable\SluggableListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/config/timestampable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Timestampable\TimestampableListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/config/softdeleteable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\SoftDeleteable\SoftDeleteableListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/config/reference_integrity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\ReferenceIntegrity\ReferenceIntegrityListener
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/DependencyInjection/Compiler/ValidateExtensionConfigurationPass.php:
--------------------------------------------------------------------------------
1 | getExtension('stof_doctrine_extensions')->configValidate($container);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Resources/doc/softdeleteable-filter.rst:
--------------------------------------------------------------------------------
1 | SoftDeleteable Filter
2 | =====================
3 |
4 | If you want to use the SoftDeleteable behavior, you have to enable the
5 | Doctrine filter.
6 |
7 | .. code-block:: yaml
8 |
9 | # app/config/config.yml
10 | # (or config/packages/doctrine.yaml if you use Flex)
11 | doctrine:
12 | orm:
13 | entity_managers:
14 | default:
15 | filters:
16 | softdeleteable:
17 | class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
18 | enabled: true
19 |
20 | .. note::
21 |
22 | If you are using the short syntax for the ORM configuration, the ``filters``
23 | key is directly under ``orm:``
24 |
25 | .. note::
26 |
27 | If you are using several entity managers, take care to register the filter
28 | for the right ones.
29 |
30 | To disable the behavior, e.g. for admin users who may see deleted items,
31 | disable the filter. Here is an example::
32 |
33 | $filters = $em->getFilters();
34 | $filters->disable('softdeleteable');
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Christophe Coevoet
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/EventListener/LocaleListener.php:
--------------------------------------------------------------------------------
1 | translatableListener = $translatableListener;
22 | }
23 |
24 | /**
25 | * @internal
26 | */
27 | public function onKernelRequest(RequestEvent $event)
28 | {
29 | $this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale());
30 | }
31 |
32 | public static function getSubscribedEvents()
33 | {
34 | return array(
35 | KernelEvents::REQUEST => 'onKernelRequest',
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.4.0 (2020-03-30)
2 |
3 | Features:
4 |
5 | * Added support for Symfony 5
6 |
7 | Removed:
8 |
9 | * Dropped support for unmaintained versions of Symfony, and for Symfony 3.4. The minimum Symfony version is now 4.3
10 | * Dropped support for unmaintained PHP versions.
11 |
12 | ## 1.3.0 (2017-12-24)
13 |
14 | Features:
15 |
16 | * Added support for Symfony 4
17 | * Added autowiring support for `Stof\DoctrineExtensionsBundle\Uploadable\UploadableManager`
18 |
19 | Bugfixes:
20 |
21 | * Fixed usage of loggable and soft-deleteable together to ensure soft-deletions are logged
22 | * Removed the logic running on bundle boot to avoid overhead
23 |
24 | Removed:
25 |
26 | * Dropped support for unmaintained versions of Symfony
27 |
28 | ## 1.2.2 (2016-01-27)
29 |
30 | * Added support for Symfony 3
31 |
32 | ## 1.2.1 (2015-08-12)
33 |
34 | * Fixed the BlameListener
35 |
36 | ## 1.2.0 (2015-08-12)
37 |
38 | Bugfixes:
39 |
40 | * Fixed the handling of the directory validation of the uploadable extension
41 | * Removed usage of APIs deprecated in Symfony 2.6+
42 |
43 | Features:
44 |
45 | * Marked the Gedmo extensions 2.4.0 release as supported (as well as any future 2.x release thanks to semver)
46 |
--------------------------------------------------------------------------------
/Uploadable/UploadedFileInfo.php:
--------------------------------------------------------------------------------
1 | uploadedFile = $uploadedFile;
15 | }
16 |
17 | public function getTmpName()
18 | {
19 | return $this->uploadedFile->getPathname();
20 | }
21 |
22 | public function getName()
23 | {
24 | return $this->uploadedFile->getClientOriginalName();
25 | }
26 |
27 | public function getSize()
28 | {
29 | return $this->uploadedFile->getSize();
30 | }
31 |
32 | public function getType()
33 | {
34 | return $this->uploadedFile->getMimeType();
35 | }
36 |
37 | public function getError()
38 | {
39 | return $this->uploadedFile->getError();
40 | }
41 |
42 | /**
43 | * {@inheritDoc}
44 | */
45 | public function isUploadedFile()
46 | {
47 | return is_uploaded_file($this->uploadedFile->getPathname());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Resources/doc/uploadable-extension.rst:
--------------------------------------------------------------------------------
1 | Uploadable extension
2 | ====================
3 |
4 | Before using this extension, read the `official Uploadable documentation`_. Once
5 | everything is ready, use the Form component as usual. Then, after you verify the
6 | form is valid, do the following::
7 |
8 | $document = new Document();
9 | $form = $this->createFormBuilder($document)
10 | ->add('name')
11 | ->add('myFile')
12 | ->getForm()
13 | ;
14 |
15 | $form->handleRequest($request);
16 |
17 | if ($form->isSubmitted() && $form->isValid()) {
18 | $em = $this->getDoctrine()->getManager();
19 | $em->persist($document);
20 |
21 | $uploadableManager = $this->get('stof_doctrine_extensions.uploadable.manager');
22 |
23 | // Here, "getMyFile" returns the "UploadedFile" instance that the form bound in your $myFile property
24 | $uploadableManager->markEntityToUpload($document, $document->getMyFile());
25 |
26 | $em->flush();
27 |
28 | return $this->redirect($this->generateUrl('...'));
29 | }
30 |
31 | return $this->render('...', array('form' => $form->createView()));
32 |
33 | And that's it. The Uploadable extension handles the rest of the stuff. Remember
34 | to read its documentation!
35 |
36 | .. _`official Uploadable documentation`: https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/uploadable.md
37 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tracker2k/doctrine-extensions-bundle",
3 | "type": "symfony-bundle",
4 | "description": "Integration of the gedmo/doctrine-extensions with Symfony2",
5 | "keywords": ["tree", "behaviors", "doctrine2", "extensions", "gedmo", "sluggable","loggable", "translatable", "nestedset", "sortable", "timestampable"],
6 | "homepage": "https://github.com/stof/StofDoctrineExtensionsBundle",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Christophe Coevoet",
11 | "email": "stof@notk.org"
12 | }
13 | ],
14 | "require": {
15 | "php": "^7.4.1",
16 | "symfony/framework-bundle": "^4.3 || ^5.0 || ^5.1",
17 | "gedmo/doctrine-extensions": "^3.0.0-beta2"
18 | },
19 | "require-dev": {
20 | "symfony/phpunit-bridge": "^4.4 || ^5.0 || ^5.1",
21 | "symfony/security-bundle": "^4.3 || ^5.0 || ^5.1"
22 | },
23 | "suggest": {
24 | "doctrine/doctrine-bundle": "to use the ORM extensions",
25 | "doctrine/mongodb-odm-bundle": "to use the MongoDB ODM extensions",
26 | "symfony/mime": "To use the Mime component integration for Uploadable"
27 | },
28 | "autoload": {
29 | "psr-4": { "Stof\\DoctrineExtensionsBundle\\": "" }
30 | },
31 | "extra": {
32 | "branch-alias": {
33 | "dev-master": "1.5.x-dev"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Resources/config/loggable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Loggable\LoggableListener
9 | Stof\DoctrineExtensionsBundle\EventListener\LoggerListener
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Resources/config/blameable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Blameable\BlameableListener
9 | Stof\DoctrineExtensionsBundle\EventListener\BlameListener
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Resources/doc/advanced.rst:
--------------------------------------------------------------------------------
1 | Advanced Usage
2 | ==============
3 |
4 | Overriding the listeners
5 | ------------------------
6 |
7 | You can change the listeners used by extending the Gedmo listeners (or the
8 | listeners of the bundle for translations) and giving the class name in the
9 | configuration.
10 |
11 | .. configuration-block::
12 |
13 | .. code-block:: yaml
14 |
15 | # app/config/config.yml
16 | # (or config/packages/stof_doctrine_extensions.yaml if you use Flex)
17 | stof_doctrine_extensions:
18 | class:
19 | tree: MyBundle\TreeListener
20 | timestampable: MyBundle\TimestampableListener
21 | blameable: ~
22 | sluggable: ~
23 | translatable: ~
24 | loggable: ~
25 | softdeleteable: ~
26 | uploadable: ~
27 |
28 | .. code-block:: xml
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Uploadable/UploadableManager.php:
--------------------------------------------------------------------------------
1 | listener = $listener;
17 | $this->fileInfoClass = $fileInfoClass;
18 | }
19 |
20 | /**
21 | * This method marks an entity to be uploaded as soon as the "flush" method of your object manager is called.
22 | * After calling this method, the file info you passed is set for this entity in the listener. This is all it takes
23 | * to upload a file for an entity in the Uploadable extension.
24 | *
25 | * @param object $entity - The entity you are marking to "Upload" as soon as you call "flush".
26 | * @param mixed $fileInfo - The file info object or array. In Symfony, this will be typically an UploadedFile instance.
27 | */
28 | public function markEntityToUpload($entity, $fileInfo)
29 | {
30 | if (is_object($fileInfo) && $fileInfo instanceof UploadedFile) {
31 | $fileInfoClass = $this->fileInfoClass;
32 |
33 | $fileInfo = new $fileInfoClass($fileInfo);
34 | }
35 |
36 | $this->listener->addEntityFileInfo($entity, $fileInfo);
37 | }
38 |
39 | /**
40 | * @return \Gedmo\Uploadable\UploadableListener
41 | */
42 | public function getUploadableListener()
43 | {
44 | return $this->listener;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Resources/doc/installation.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | Installation Using Symfony Flex
5 | -------------------------------
6 |
7 | `Symfony Flex`_ is the new way to manage dependencies on Symfony 3.4 and higher
8 | applications. If your project already uses Symfony Flex, execute this command to
9 | download, register and configure the bundle automatically:
10 |
11 | .. code-block:: terminal
12 |
13 | $ composer require stof/doctrine-extensions-bundle
14 |
15 | That's all! You can skip the rest of this article.
16 |
17 | Installation without Symfony Flex
18 | ---------------------------------
19 |
20 | Step 1: Download the Bundle
21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 |
23 | Open a command console, enter your project directory and execute the
24 | following command to download the latest stable version of this bundle:
25 |
26 | .. code-block:: bash
27 |
28 | $ composer require stof/doctrine-extensions-bundle
29 |
30 | This command requires you to have Composer installed globally, as explained
31 | in the `installation chapter`_ of the Composer documentation.
32 |
33 | Step 2: Enable the Bundle
34 | ~~~~~~~~~~~~~~~~~~~~~~~~~
35 |
36 | Then, enable the bundle by adding the following line in the ``app/AppKernel.php``
37 | file of your project:
38 |
39 | .. code-block:: php
40 |
41 | // app/AppKernel.php
42 |
43 | class AppKernel extends Kernel
44 | {
45 | public function registerBundles()
46 | {
47 | $bundles = array(
48 | // ...
49 |
50 | new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
51 | );
52 |
53 | // ...
54 | }
55 |
56 | // ...
57 | }
58 |
59 | .. _`Symfony Flex`: https://symfony.com/doc/current/setup/flex.html
60 | .. _`installation chapter`: https://getcomposer.org/doc/00-intro.md
61 |
--------------------------------------------------------------------------------
/Resources/doc/index.rst:
--------------------------------------------------------------------------------
1 | StofDoctrineExtensionsBundle
2 | ============================
3 |
4 | This bundle provides integration for `DoctrineExtensions`_ in your Symfony
5 | projects.
6 |
7 | Features
8 | --------
9 |
10 | * **Tree** - this extension automates the tree handling process and adds some
11 | tree specific functions on repository. (``closure``, ``nestedset`` or ``materialized path``).
12 | * **Translatable** - gives you a very handy solution for translating records
13 | into different languages. Easy to setup, easier to use.
14 | * **Sluggable** - urlizes your specified fields into single unique slug
15 | * **Timestampable** - updates date fields on create, update and even property change.
16 | * **Blameable** - updates string or association fields on create, update and even
17 | property change with a user name resp. reference.
18 | * **Loggable** - helps tracking changes and history of objects, also supports
19 | version management.
20 | * **Sortable** - makes any document or entity sortable
21 | * **Translator** - explicit way to handle translations
22 | * **Softdeleteable** - allows to implicitly remove records
23 | * **Uploadable** - provides file upload handling in entity fields
24 | * **Reference Integrity** - provides reference integrity for MongoDB, supports
25 | ``nullify`` and ``restrict``.
26 |
27 | All these extensions can be nested together. And most already use only
28 | annotations without interface requirement to not to aggregate the entity itself
29 | and has implemented proper caching for metadata.
30 |
31 | See the official `official DoctrineExtensions documentation`_ for more details.
32 |
33 | .. toctree::
34 | :maxdepth: 2
35 |
36 | installation
37 | configuration
38 | softdeletable-filter
39 | uploadable-extension
40 | advanced
41 |
42 | .. _`DoctrineExtensions`: https://github.com/Atlantic18/DoctrineExtensions
43 | .. _`official DoctrineExtensions documentation`: https://github.com/Atlantic18/DoctrineExtensions/tree/v2.4.x/doc
44 |
--------------------------------------------------------------------------------
/EventListener/LoggerListener.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | class LoggerListener implements EventSubscriberInterface
19 | {
20 | private $authorizationChecker;
21 | private $tokenStorage;
22 | private $loggableListener;
23 |
24 | public function __construct(LoggableListener $loggableListener, TokenStorageInterface $tokenStorage = null, AuthorizationCheckerInterface $authorizationChecker = null)
25 | {
26 | $this->loggableListener = $loggableListener;
27 | $this->tokenStorage = $tokenStorage;
28 | $this->authorizationChecker = $authorizationChecker;
29 | }
30 |
31 | /**
32 | * @internal
33 | */
34 | public function onKernelRequest(RequestEvent $event)
35 | {
36 | if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
37 | return;
38 | }
39 |
40 | if (null === $this->tokenStorage || null === $this->authorizationChecker) {
41 | return;
42 | }
43 |
44 | $token = $this->tokenStorage->getToken();
45 |
46 | if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
47 | $this->loggableListener->setUsername($token);
48 | }
49 | }
50 |
51 | public static function getSubscribedEvents()
52 | {
53 | return array(
54 | KernelEvents::REQUEST => 'onKernelRequest',
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/EventListener/BlameListener.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | class BlameListener implements EventSubscriberInterface
20 | {
21 | private $authorizationChecker;
22 | private $tokenStorage;
23 | private $blameableListener;
24 |
25 | public function __construct(BlameableListener $blameableListener, TokenStorageInterface $tokenStorage = null, AuthorizationCheckerInterface $authorizationChecker = null)
26 | {
27 | $this->blameableListener = $blameableListener;
28 | $this->tokenStorage = $tokenStorage;
29 | $this->authorizationChecker = $authorizationChecker;
30 | }
31 |
32 | /**
33 | * @internal
34 | */
35 | public function onKernelRequest(RequestEvent $event)
36 | {
37 | if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
38 | return;
39 | }
40 |
41 | if (null === $this->tokenStorage || null === $this->authorizationChecker) {
42 | return;
43 | }
44 |
45 | $token = $this->tokenStorage->getToken();
46 | if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
47 | $this->blameableListener->setUserValue($token->getUser());
48 | }
49 | }
50 |
51 | public static function getSubscribedEvents()
52 | {
53 | return array(
54 | KernelEvents::REQUEST => 'onKernelRequest',
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Resources/config/translatable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Translatable\TranslatableListener
9 | Stof\DoctrineExtensionsBundle\EventListener\LocaleListener
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | %stof_doctrine_extensions.default_locale%
18 |
19 |
20 | %stof_doctrine_extensions.default_locale%
21 |
22 |
23 | %stof_doctrine_extensions.translation_fallback%
24 |
25 |
26 | %stof_doctrine_extensions.persist_default_translation%
27 |
28 |
29 | %stof_doctrine_extensions.skip_translation_on_load%
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Resources/config/uploadable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Gedmo\Uploadable\UploadableListener
9 | Stof\DoctrineExtensionsBundle\Uploadable\UploadableManager
10 | Stof\DoctrineExtensionsBundle\Uploadable\MimeTypeGuesserAdapter
11 | Stof\DoctrineExtensionsBundle\Uploadable\UploadedFileInfo
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | %stof_doctrine_extensions.uploadable.default_file_info.class%
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | %stof_doctrine_extensions.uploadable.default_file_info.class%
32 |
33 |
34 |
35 |
36 |
37 | %stof_doctrine_extensions.uploadable.validate_writable_directory%
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/DependencyInjection/StofDoctrineExtensionsExtension.php:
--------------------------------------------------------------------------------
1 | processConfiguration($configuration, $configs);
23 |
24 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
25 |
26 | $loaded = array();
27 |
28 | $this->entityManagers = $this->processObjectManagerConfigurations($config['orm'], $container, $loader, $loaded, 'doctrine.event_subscriber');
29 | $this->documentManagers = $this->processObjectManagerConfigurations($config['mongodb'], $container, $loader, $loaded, 'doctrine_mongodb.odm.event_subscriber');
30 |
31 | $container->setParameter('stof_doctrine_extensions.default_locale', $config['default_locale']);
32 | $container->setParameter('stof_doctrine_extensions.translation_fallback', $config['translation_fallback']);
33 | $container->setParameter('stof_doctrine_extensions.persist_default_translation', $config['persist_default_translation']);
34 | $container->setParameter('stof_doctrine_extensions.skip_translation_on_load', $config['skip_translation_on_load']);
35 |
36 | // Register the uploadable configuration if the listener is used
37 | if (isset($loaded['uploadable'])) {
38 | $uploadableConfig = $config['uploadable'];
39 |
40 | $container->setParameter('stof_doctrine_extensions.default_file_path', $uploadableConfig['default_file_path']);
41 | $container->setParameter('stof_doctrine_extensions.uploadable.default_file_info.class', $uploadableConfig['default_file_info_class']);
42 | $container->setParameter(
43 | 'stof_doctrine_extensions.uploadable.validate_writable_directory',
44 | $uploadableConfig['validate_writable_directory']
45 | );
46 |
47 | if ($uploadableConfig['default_file_path']) {
48 | $container->getDefinition('stof_doctrine_extensions.listener.uploadable')
49 | ->addMethodCall('setDefaultPath', array($uploadableConfig['default_file_path']));
50 | }
51 |
52 | if ($uploadableConfig['mime_type_guesser_class']) {
53 | if (!class_exists($uploadableConfig['mime_type_guesser_class'])) {
54 | $msg = 'Class "%s" configured to use as the mime type guesser in the Uploadable extension does not exist.';
55 |
56 | throw new \InvalidArgumentException(sprintf($msg, $uploadableConfig['mime_type_guesser_class']));
57 | }
58 |
59 | $container->setParameter(
60 | 'stof_doctrine_extensions.uploadable.mime_type_guesser.class',
61 | $uploadableConfig['mime_type_guesser_class']
62 | );
63 | }
64 | }
65 |
66 | foreach ($config['class'] as $listener => $class) {
67 | $container->setParameter(sprintf('stof_doctrine_extensions.listener.%s.class', $listener), $class);
68 | }
69 | }
70 |
71 | /**
72 | * @internal
73 | */
74 | public function configValidate(ContainerBuilder $container)
75 | {
76 | foreach ($this->entityManagers as $name) {
77 | if (!$container->hasDefinition(sprintf('doctrine.dbal.%s_connection', $name))) {
78 | throw new \InvalidArgumentException(sprintf('Invalid %s config: DBAL connection "%s" not found', $this->getAlias(), $name));
79 | }
80 | }
81 |
82 | foreach ($this->documentManagers as $name) {
83 | if (!$container->hasDefinition(sprintf('doctrine_mongodb.odm.%s_document_manager', $name))) {
84 | throw new \InvalidArgumentException(sprintf('Invalid %s config: document manager "%s" not found', $this->getAlias(), $name));
85 | }
86 | }
87 | }
88 |
89 | /**
90 | * @param array $configs
91 | * @param ContainerBuilder $container
92 | * @param LoaderInterface $loader
93 | * @param array $loaded
94 | * @param string $doctrineSubscriberTag
95 | *
96 | * @return array
97 | */
98 | private function processObjectManagerConfigurations(array $configs, ContainerBuilder $container, LoaderInterface $loader, array &$loaded, $doctrineSubscriberTag)
99 | {
100 | $usedManagers = array();
101 |
102 | $listenerPriorities = array(
103 | 'translatable' => -10,
104 | 'loggable' => 5,
105 | 'uploadable' => -5,
106 | );
107 |
108 | foreach ($configs as $name => $listeners) {
109 | foreach ($listeners as $ext => $enabled) {
110 | if (!$enabled) {
111 | continue;
112 | }
113 |
114 | if (!isset($loaded[$ext])) {
115 | $loader->load($ext.'.xml');
116 | $loaded[$ext] = true;
117 | }
118 |
119 | $attributes = array('connection' => $name);
120 |
121 | if (isset($listenerPriorities[$ext])) {
122 | $attributes['priority'] = $listenerPriorities[$ext];
123 | }
124 |
125 | $definition = $container->getDefinition(sprintf('stof_doctrine_extensions.listener.%s', $ext));
126 | $definition->addTag($doctrineSubscriberTag, $attributes);
127 |
128 | $usedManagers[$name] = true;
129 | }
130 | }
131 |
132 | return array_keys($usedManagers);
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 | getRootNode();
20 | } else {
21 | // BC layer for symfony/config 4.1 and older
22 | $rootNode = $treeBuilder->root('stof_doctrine_extensions');
23 | }
24 |
25 | $rootNode
26 | ->append($this->getVendorNode('orm'))
27 | ->append($this->getVendorNode('mongodb'))
28 | ->append($this->getClassNode())
29 | ->append($this->getUploadableNode())
30 | ->children()
31 | ->scalarNode('default_locale')
32 | ->cannotBeEmpty()
33 | ->defaultValue('en')
34 | ->end()
35 | ->booleanNode('translation_fallback')->defaultFalse()->end()
36 | ->booleanNode('persist_default_translation')->defaultFalse()->end()
37 | ->booleanNode('skip_translation_on_load')->defaultFalse()->end()
38 | ->end()
39 | ;
40 |
41 | return $treeBuilder;
42 | }
43 |
44 | /**
45 | * @param string $name
46 | */
47 | private function getVendorNode($name)
48 | {
49 | $treeBuilder = new TreeBuilder($name);
50 | if (\method_exists($treeBuilder, 'getRootNode')) {
51 | $node = $treeBuilder->getRootNode();
52 | } else {
53 | // BC layer for symfony/config 4.1 and older
54 | $node = $treeBuilder->root($name);
55 | }
56 |
57 | $node
58 | ->useAttributeAsKey('id')
59 | ->prototype('array')
60 | ->children()
61 | ->scalarNode('translatable')->defaultFalse()->end()
62 | ->scalarNode('timestampable')->defaultFalse()->end()
63 | ->scalarNode('blameable')->defaultFalse()->end()
64 | ->scalarNode('sluggable')->defaultFalse()->end()
65 | ->scalarNode('tree')->defaultFalse()->end()
66 | ->scalarNode('loggable')->defaultFalse()->end()
67 | ->scalarNode('sortable')->defaultFalse()->end()
68 | ->scalarNode('softdeleteable')->defaultFalse()->end()
69 | ->scalarNode('uploadable')->defaultFalse()->end()
70 | ->scalarNode('reference_integrity')->defaultFalse()->end()
71 | ->end()
72 | ->end()
73 | ;
74 |
75 | return $node;
76 | }
77 |
78 | private function getClassNode()
79 | {
80 | $treeBuilder = new TreeBuilder('class');
81 | if (\method_exists($treeBuilder, 'getRootNode')) {
82 | $node = $treeBuilder->getRootNode();
83 | } else {
84 | // BC layer for symfony/config 4.1 and older
85 | $node = $treeBuilder->root('class');
86 | }
87 |
88 | $node
89 | ->addDefaultsIfNotSet()
90 | ->children()
91 | ->scalarNode('translatable')
92 | ->cannotBeEmpty()
93 | ->defaultValue('Gedmo\Translatable\TranslatableListener')
94 | ->end()
95 | ->scalarNode('timestampable')
96 | ->cannotBeEmpty()
97 | ->defaultValue('Gedmo\\Timestampable\\TimestampableListener')
98 | ->end()
99 | ->scalarNode('blameable')
100 | ->cannotBeEmpty()
101 | ->defaultValue('Gedmo\\Blameable\\BlameableListener')
102 | ->end()
103 | ->scalarNode('sluggable')
104 | ->cannotBeEmpty()
105 | ->defaultValue('Gedmo\\Sluggable\\SluggableListener')
106 | ->end()
107 | ->scalarNode('tree')
108 | ->cannotBeEmpty()
109 | ->defaultValue('Gedmo\\Tree\\TreeListener')
110 | ->end()
111 | ->scalarNode('loggable')
112 | ->cannotBeEmpty()
113 | ->defaultValue('Gedmo\Loggable\LoggableListener')
114 | ->end()
115 | ->scalarNode('sortable')
116 | ->cannotBeEmpty()
117 | ->defaultValue('Gedmo\\Sortable\\SortableListener')
118 | ->end()
119 | ->scalarNode('softdeleteable')
120 | ->cannotBeEmpty()
121 | ->defaultValue('Gedmo\\SoftDeleteable\\SoftDeleteableListener')
122 | ->end()
123 | ->scalarNode('uploadable')
124 | ->cannotBeEmpty()
125 | ->defaultValue('Gedmo\\Uploadable\\UploadableListener')
126 | ->end()
127 | ->scalarNode('reference_integrity')
128 | ->cannotBeEmpty()
129 | ->defaultValue('Gedmo\\ReferenceIntegrity\\ReferenceIntegrityListener')
130 | ->end()
131 | ->end()
132 | ;
133 |
134 | return $node;
135 | }
136 |
137 | private function getUploadableNode()
138 | {
139 | $treeBuilder = new TreeBuilder('uploadable');
140 | if (\method_exists($treeBuilder, 'getRootNode')) {
141 | $node = $treeBuilder->getRootNode();
142 | } else {
143 | // BC layer for symfony/config 4.1 and older
144 | $node = $treeBuilder->root('uploadable');
145 | }
146 |
147 | $node
148 | ->addDefaultsIfNotSet()
149 | ->children()
150 | ->scalarNode('default_file_path')
151 | ->cannotBeEmpty()
152 | ->defaultNull()
153 | ->end()
154 | ->scalarNode('mime_type_guesser_class')
155 | ->cannotBeEmpty()
156 | ->defaultValue('Stof\\DoctrineExtensionsBundle\\Uploadable\\MimeTypeGuesserAdapter')
157 | ->end()
158 | ->scalarNode('default_file_info_class')
159 | ->cannotBeEmpty()
160 | ->defaultValue('Stof\\DoctrineExtensionsBundle\\Uploadable\\UploadedFileInfo')
161 | ->end()
162 | ->booleanNode('validate_writable_directory')->defaultTrue()->end()
163 | ->end()
164 | ;
165 |
166 | return $node;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/Resources/doc/configuration.rst:
--------------------------------------------------------------------------------
1 | Configuration
2 | =============
3 |
4 | Add the extensions to your mapping
5 | ----------------------------------
6 |
7 | Some of the extensions use their own entities to do their work. You need
8 | to register their mapping in Doctrine when you want to use them.
9 |
10 | .. code-block:: yaml
11 |
12 | # app/config/config.yml
13 | # (or config/packages/doctrine.yaml if you use Flex)
14 | doctrine:
15 | orm:
16 | entity_managers:
17 | default:
18 | mappings:
19 | gedmo_translatable:
20 | type: annotation
21 | prefix: Gedmo\Translatable\Entity
22 | dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
23 | alias: GedmoTranslatable # (optional) it will default to the name set for the mapping
24 | is_bundle: false
25 | gedmo_translator:
26 | type: annotation
27 | prefix: Gedmo\Translator\Entity
28 | dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translator/Entity"
29 | alias: GedmoTranslator # (optional) it will default to the name set for the mapping
30 | is_bundle: false
31 | gedmo_loggable:
32 | type: annotation
33 | prefix: Gedmo\Loggable\Entity
34 | dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity"
35 | alias: GedmoLoggable # (optional) it will default to the name set for the mapping
36 | is_bundle: false
37 | gedmo_tree:
38 | type: annotation
39 | prefix: Gedmo\Tree\Entity
40 | dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
41 | alias: GedmoTree # (optional) it will default to the name set for the mapping
42 | is_bundle: false
43 |
44 | .. note::
45 |
46 | If you are using the short syntax for the ORM configuration, the ``mappings``
47 | key is directly under ``orm:``
48 |
49 | .. note::
50 |
51 | If you are using several entity managers, take care to register the entities
52 | for the right ones.
53 |
54 | .. note::
55 |
56 | The mapping for MongoDB is similar. The ODM documents are in the ``Document``
57 | subnamespace of each extension instead of ``Entity``.
58 |
59 | Configure the entity managers
60 | -----------------------------
61 |
62 | You have to activate the extensions for each entity manager for which you want
63 | to enable the extensions. The id is the id of the DBAL connection when using the
64 | ORM behaviors. It is the id of the document manager when using mongoDB.
65 |
66 | This bundle needs a default locale used if the translation does not exists in
67 | the asked language. If you don't provide it explicitly, it will default to
68 | ``en``.
69 |
70 | .. configuration-block::
71 |
72 | .. code-block:: yaml
73 |
74 | # app/config/config.yml
75 | # (or config/packages/stof_doctrine_extensions.yaml if you use Flex)
76 | stof_doctrine_extensions:
77 | default_locale: en_US
78 |
79 | # Only used if you activated the Uploadable extension
80 | uploadable:
81 | # Default file path: This is one of the three ways you can configure the path for the Uploadable extension
82 | default_file_path: "%kernel.project_dir%/public/uploads"
83 |
84 | # Mime type guesser class: Optional. By default, we provide an adapter for the one present in the Mime component of Symfony
85 | mime_type_guesser_class: Stof\DoctrineExtensionsBundle\Uploadable\MimeTypeGuesserAdapter
86 |
87 | # Default file info class implementing FileInfoInterface: Optional. By default we provide a class which is prepared to receive an UploadedFile instance.
88 | default_file_info_class: Stof\DoctrineExtensionsBundle\Uploadable\UploadedFileInfo
89 | orm:
90 | default: ~
91 | mongodb:
92 | default: ~
93 |
94 | .. code-block:: xml
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | Activate the extensions you want
110 | --------------------------------
111 |
112 | By default the bundle does not attach any listener. For each of your entity
113 | manager, declare the extensions you want to enable:
114 |
115 | .. configuration-block::
116 |
117 | .. code-block:: yaml
118 |
119 | # app/config/config.yml
120 | # (or config/packages/stof_doctrine_extensions.yaml if you use Flex)
121 | stof_doctrine_extensions:
122 | default_locale: en_US
123 | orm:
124 | default:
125 | tree: true
126 | timestampable: false # not needed: listeners are not enabled by default
127 | other:
128 | timestampable: true
129 |
130 | .. code-block:: xml
131 |
132 |
133 |
134 |
135 |
136 |
137 |
142 |
146 |
147 |
148 |
149 |
150 | Same is available for MongoDB using ``document-manager`` in the XML files
151 | instead of ``entity-manager``.
152 |
153 | .. caution::
154 |
155 | If you configure the listeners of an entity manager in several configuration
156 | files, the last one will be used. So you have to list all the listeners you
157 | want to detach.
158 |
159 | Use the DoctrineExtensions library
160 | ----------------------------------
161 |
162 | All explanations about this library are available on the official
163 | `DoctrineExtensions documentation`_.
164 |
165 | .. _`DoctrineExtensions documentation`: https://github.com/Atlantic18/DoctrineExtensions/tree/v2.4.x/doc
166 |
--------------------------------------------------------------------------------