├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── phpstan.neon └── src ├── DependencyInjection ├── Compiler │ ├── ReaderPass.php │ └── ValidateExtensionConfigurationPass.php ├── Configuration.php └── StofDoctrineExtensionsExtension.php ├── EventListener ├── BlameListener.php ├── LocaleListener.php └── LoggerListener.php ├── Resources └── config │ ├── blameable.xml │ ├── ip_traceable.xml │ ├── loggable.xml │ ├── reference_integrity.xml │ ├── sluggable.xml │ ├── softdeleteable.xml │ ├── sortable.xml │ ├── timestampable.xml │ ├── tool.xml │ ├── translatable.xml │ ├── tree.xml │ └── uploadable.xml ├── StofDoctrineExtensionsBundle.php ├── Tool ├── LocaleSynchronizer.php ├── RequestStackIpAddressProvider.php └── TokenStorageActorProvider.php └── Uploadable ├── MimeTypeGuesserAdapter.php ├── UploadableManager.php ├── UploadedFileInfo.php └── ValidatorConfigurator.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.7.0 (2021-11-22) 2 | 3 | Features: 4 | 5 | * Added support for Symfony 6 6 | 7 | Misc: 8 | 9 | * Added a CI job running on PHP 8.1 10 | * Renamed the main branch to `main`. Requiring `dev-master` explicitly will fail. Constraints `^1.7@dev` should be used to use the dev version matching a semver range instead, when necessary. 11 | 12 | ## 1.6.0 (2021-03-05) 13 | 14 | Features: 15 | 16 | * Added support for PHP 8 17 | 18 | Removed: 19 | 20 | * Dropped support for unmaintained versions of Symfony. The minimum Symfony versions are now 4.4 and 5.2. 21 | 22 | ## 1.5.0 (2020-09-30) 23 | 24 | Features: 25 | 26 | * Added support for `gedmo/doctrine-extensions` 3 27 | 28 | ## 1.4.0 (2020-03-30) 29 | 30 | Features: 31 | 32 | * Added support for Symfony 5 33 | 34 | Removed: 35 | 36 | * Dropped support for unmaintained versions of Symfony, and for Symfony 3.4. The minimum Symfony version is now 4.3 37 | * Dropped support for unmaintained PHP versions. 38 | 39 | ## 1.3.0 (2017-12-24) 40 | 41 | Features: 42 | 43 | * Added support for Symfony 4 44 | * Added autowiring support for `Stof\DoctrineExtensionsBundle\Uploadable\UploadableManager` 45 | 46 | Bugfixes: 47 | 48 | * Fixed usage of loggable and soft-deleteable together to ensure soft-deletions are logged 49 | * Removed the logic running on bundle boot to avoid overhead 50 | 51 | Removed: 52 | 53 | * Dropped support for unmaintained versions of Symfony 54 | 55 | ## 1.2.2 (2016-01-27) 56 | 57 | * Added support for Symfony 3 58 | 59 | ## 1.2.1 (2015-08-12) 60 | 61 | * Fixed the BlameListener 62 | 63 | ## 1.2.0 (2015-08-12) 64 | 65 | Bugfixes: 66 | 67 | * Fixed the handling of the directory validation of the uploadable extension 68 | * Removed usage of APIs deprecated in Symfony 2.6+ 69 | 70 | Features: 71 | 72 | * Marked the Gedmo extensions 2.4.0 release as supported (as well as any future 2.x release thanks to semver) 73 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StofDoctrineExtensionsBundle 2 | 3 | This bundle provides integration for 4 | [DoctrineExtensions](https://github.com/doctrine-extensions/DoctrineExtensions) in 5 | your Symfony Project. 6 | 7 | [![Total Downloads](https://poser.pugx.org/stof/doctrine-extensions-bundle/downloads.png)](https://packagist.org/packages/stof/doctrine-extensions-bundle) 8 | [![Latest Stable Version](https://poser.pugx.org/stof/doctrine-extensions-bundle/v/stable.png)](https://packagist.org/packages/stof/doctrine-extensions-bundle) 9 | 10 | For documentation, see it [online](https://symfony.com/bundles/StofDoctrineExtensionsBundle/current/index.html) 11 | 12 | License: [MIT](LICENSE) 13 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stof/doctrine-extensions-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Integration of the gedmo/doctrine-extensions with Symfony", 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": "^8.1", 16 | "gedmo/doctrine-extensions": "^3.20.0", 17 | "symfony/cache": "^6.4 || ^7.0", 18 | "symfony/config": "^6.4 || ^7.0", 19 | "symfony/dependency-injection": "^6.4 || ^7.0", 20 | "symfony/event-dispatcher": "^6.4 || ^7.0", 21 | "symfony/http-kernel": "^6.4 || ^7.0", 22 | "symfony/translation-contracts": "^2.5 || ^3.5" 23 | }, 24 | "require-dev": { 25 | "phpstan/phpstan": "^2.1", 26 | "phpstan/phpstan-deprecation-rules": "^2.0", 27 | "phpstan/phpstan-phpunit": "^2.0", 28 | "phpstan/phpstan-strict-rules": "^2.0", 29 | "phpstan/phpstan-symfony": "^2.0", 30 | "symfony/mime": "^6.4 || ^7.0", 31 | "symfony/phpunit-bridge": "^v6.4.1 || ^7.0.1", 32 | "symfony/security-core": "^6.4 || ^7.0" 33 | }, 34 | "suggest": { 35 | "doctrine/doctrine-bundle": "to use the ORM extensions", 36 | "doctrine/mongodb-odm-bundle": "to use the MongoDB ODM extensions", 37 | "symfony/mime": "To use the Mime component integration for Uploadable" 38 | }, 39 | "autoload": { 40 | "psr-4": { "Stof\\DoctrineExtensionsBundle\\": "src" } 41 | }, 42 | "autoload-dev": { 43 | "psr-4": { "Stof\\DoctrineExtensionsBundle\\Tests\\": "tests" } 44 | }, 45 | "extra": { 46 | "branch-alias": { 47 | "dev-main": "1.x-dev" 48 | } 49 | }, 50 | "config": { 51 | "sort-packages": true 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 8 3 | paths: 4 | - src/ 5 | - tests/ 6 | 7 | includes: 8 | - vendor/phpstan/phpstan-deprecation-rules/rules.neon 9 | - vendor/phpstan/phpstan-phpunit/extension.neon 10 | - vendor/phpstan/phpstan-phpunit/rules.neon 11 | - vendor/phpstan/phpstan-strict-rules/rules.neon 12 | - vendor/phpstan/phpstan-symfony/extension.neon 13 | - vendor/phpstan/phpstan-symfony/rules.neon 14 | -------------------------------------------------------------------------------- /src/DependencyInjection/Compiler/ReaderPass.php: -------------------------------------------------------------------------------- 1 | has('annotation_reader')) { 18 | $container->setAlias('.stof_doctrine_extensions.reader', new Alias('annotation_reader', false)); 19 | 20 | return; 21 | } 22 | 23 | $container->register('.stof_doctrine_extensions.reader', AttributeReader::class); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/DependencyInjection/Compiler/ValidateExtensionConfigurationPass.php: -------------------------------------------------------------------------------- 1 | getExtension('stof_doctrine_extensions'); 28 | \assert($extension instanceof StofDoctrineExtensionsExtension); 29 | 30 | $extension->configValidate($container); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | getRootNode(); 18 | 19 | $rootNode 20 | ->append($this->getVendorNode('orm')) 21 | ->append($this->getVendorNode('mongodb')) 22 | ->append($this->getClassNode()) 23 | ->append($this->getUploadableNode()) 24 | ->children() 25 | ->scalarNode('default_locale') 26 | ->cannotBeEmpty() 27 | ->defaultValue('en') 28 | ->end() 29 | ->booleanNode('translation_fallback')->defaultFalse()->end() 30 | ->booleanNode('persist_default_translation')->defaultFalse()->end() 31 | ->booleanNode('skip_translation_on_load')->defaultFalse()->end() 32 | ->scalarNode('metadata_cache_pool')->defaultNull()->end() 33 | ->end() 34 | ; 35 | 36 | return $treeBuilder; 37 | } 38 | 39 | private function getVendorNode(string $name): ArrayNodeDefinition 40 | { 41 | $treeBuilder = new TreeBuilder($name); 42 | $node = $treeBuilder->getRootNode(); 43 | 44 | $node 45 | ->useAttributeAsKey('id') 46 | ->prototype('array') 47 | ->children() 48 | ->scalarNode('translatable')->defaultFalse()->end() 49 | ->scalarNode('timestampable')->defaultFalse()->end() 50 | ->scalarNode('blameable')->defaultFalse()->end() 51 | ->scalarNode('sluggable')->defaultFalse()->end() 52 | ->scalarNode('tree')->defaultFalse()->end() 53 | ->scalarNode('loggable')->defaultFalse()->end() 54 | ->scalarNode('ip_traceable')->defaultFalse()->end() 55 | ->scalarNode('sortable')->defaultFalse()->end() 56 | ->scalarNode('softdeleteable')->defaultFalse()->end() 57 | ->scalarNode('uploadable')->defaultFalse()->end() 58 | ->scalarNode('reference_integrity')->defaultFalse()->end() 59 | ->end() 60 | ->end() 61 | ; 62 | 63 | return $node; 64 | } 65 | 66 | private function getClassNode(): ArrayNodeDefinition 67 | { 68 | $treeBuilder = new TreeBuilder('class'); 69 | $node = $treeBuilder->getRootNode(); 70 | 71 | $node 72 | ->addDefaultsIfNotSet() 73 | ->children() 74 | ->scalarNode('translatable') 75 | ->cannotBeEmpty() 76 | ->defaultValue('Gedmo\Translatable\TranslatableListener') 77 | ->end() 78 | ->scalarNode('timestampable') 79 | ->cannotBeEmpty() 80 | ->defaultValue('Gedmo\\Timestampable\\TimestampableListener') 81 | ->end() 82 | ->scalarNode('blameable') 83 | ->cannotBeEmpty() 84 | ->defaultValue('Gedmo\\Blameable\\BlameableListener') 85 | ->end() 86 | ->scalarNode('sluggable') 87 | ->cannotBeEmpty() 88 | ->defaultValue('Gedmo\\Sluggable\\SluggableListener') 89 | ->end() 90 | ->scalarNode('tree') 91 | ->cannotBeEmpty() 92 | ->defaultValue('Gedmo\\Tree\\TreeListener') 93 | ->end() 94 | ->scalarNode('loggable') 95 | ->cannotBeEmpty() 96 | ->defaultValue('Gedmo\Loggable\LoggableListener') 97 | ->end() 98 | ->scalarNode('sortable') 99 | ->cannotBeEmpty() 100 | ->defaultValue('Gedmo\\Sortable\\SortableListener') 101 | ->end() 102 | ->scalarNode('softdeleteable') 103 | ->cannotBeEmpty() 104 | ->defaultValue('Gedmo\\SoftDeleteable\\SoftDeleteableListener') 105 | ->end() 106 | ->scalarNode('uploadable') 107 | ->cannotBeEmpty() 108 | ->defaultValue('Gedmo\\Uploadable\\UploadableListener') 109 | ->end() 110 | ->scalarNode('reference_integrity') 111 | ->cannotBeEmpty() 112 | ->defaultValue('Gedmo\\ReferenceIntegrity\\ReferenceIntegrityListener') 113 | ->end() 114 | ->end() 115 | ; 116 | 117 | return $node; 118 | } 119 | 120 | private function getUploadableNode(): ArrayNodeDefinition 121 | { 122 | $treeBuilder = new TreeBuilder('uploadable'); 123 | $node = $treeBuilder->getRootNode(); 124 | 125 | $node 126 | ->addDefaultsIfNotSet() 127 | ->children() 128 | ->scalarNode('default_file_path') 129 | ->cannotBeEmpty() 130 | ->defaultNull() 131 | ->end() 132 | ->scalarNode('mime_type_guesser_class') 133 | ->cannotBeEmpty() 134 | ->defaultValue('Stof\\DoctrineExtensionsBundle\\Uploadable\\MimeTypeGuesserAdapter') 135 | ->end() 136 | ->scalarNode('default_file_info_class') 137 | ->cannotBeEmpty() 138 | ->defaultValue('Stof\\DoctrineExtensionsBundle\\Uploadable\\UploadedFileInfo') 139 | ->end() 140 | ->booleanNode('validate_writable_directory')->defaultTrue()->end() 141 | ->end() 142 | ; 143 | 144 | return $node; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/DependencyInjection/StofDoctrineExtensionsExtension.php: -------------------------------------------------------------------------------- 1 | array( 21 | 'prePersist', 22 | 'onFlush', 23 | 'loadClassMetadata', 24 | ), 25 | 'ip_traceable' => array( 26 | 'prePersist', 27 | 'onFlush', 28 | 'loadClassMetadata', 29 | ), 30 | 'loggable' => array( 31 | 'loadClassMetadata', 32 | 'onFlush', 33 | 'postPersist', 34 | ), 35 | 'reference_integrity' => array( 36 | 'loadClassMetadata', 37 | 'preRemove', 38 | ), 39 | 'sluggable' => array( 40 | 'prePersist', 41 | 'onFlush', 42 | 'loadClassMetadata', 43 | ), 44 | 'softdeleteable' => array( 45 | 'loadClassMetadata', 46 | 'onFlush', 47 | 'postFlush', 48 | ), 49 | 'sortable' => array( 50 | 'onFlush', 51 | 'loadClassMetadata', 52 | 'prePersist', 53 | 'postPersist', 54 | 'preUpdate', 55 | 'postRemove', 56 | 'postFlush', 57 | ), 58 | 'timestampable' => array( 59 | 'prePersist', 60 | 'onFlush', 61 | 'loadClassMetadata', 62 | ), 63 | 'translatable' => array( 64 | 'postLoad', 65 | 'postPersist', 66 | 'preFlush', 67 | 'onFlush', 68 | 'loadClassMetadata', 69 | ), 70 | 'tree' => array( 71 | 'prePersist', 72 | 'preRemove', 73 | 'preUpdate', 74 | 'onFlush', 75 | 'loadClassMetadata', 76 | 'postPersist', 77 | 'postUpdate', 78 | 'postRemove', 79 | ), 80 | 'uploadable' => array( 81 | 'loadClassMetadata', 82 | 'preFlush', 83 | 'onFlush', 84 | 'postFlush', 85 | ), 86 | ); 87 | 88 | /** @var list */ 89 | private array $entityManagers = array(); 90 | /** @var list */ 91 | private array $documentManagers = array(); 92 | 93 | /** 94 | * @return void 95 | */ 96 | public function load(array $configs, ContainerBuilder $container) 97 | { 98 | $processor = new Processor(); 99 | $configuration = new Configuration(); 100 | 101 | $config = $processor->processConfiguration($configuration, $configs); 102 | 103 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 104 | $loader->load('tool.xml'); 105 | 106 | $loaded = array(); 107 | 108 | $this->entityManagers = $this->processObjectManagerConfigurations($config['orm'], $container, $loader, $loaded, 'doctrine.event_listener'); 109 | $this->documentManagers = $this->processObjectManagerConfigurations($config['mongodb'], $container, $loader, $loaded, 'doctrine_mongodb.odm.event_listener'); 110 | 111 | $container->setParameter('stof_doctrine_extensions.default_locale', $config['default_locale']); 112 | $container->setParameter('stof_doctrine_extensions.translation_fallback', $config['translation_fallback']); 113 | $container->setParameter('stof_doctrine_extensions.persist_default_translation', $config['persist_default_translation']); 114 | $container->setParameter('stof_doctrine_extensions.skip_translation_on_load', $config['skip_translation_on_load']); 115 | 116 | // Register the uploadable configuration if the listener is used 117 | if (isset($loaded['uploadable'])) { 118 | $uploadableConfig = $config['uploadable']; 119 | 120 | $container->setParameter('stof_doctrine_extensions.default_file_path', $uploadableConfig['default_file_path']); 121 | $container->setParameter('stof_doctrine_extensions.uploadable.default_file_info.class', $uploadableConfig['default_file_info_class']); 122 | $container->setParameter( 123 | 'stof_doctrine_extensions.uploadable.validate_writable_directory', 124 | $uploadableConfig['validate_writable_directory'] 125 | ); 126 | 127 | if ($uploadableConfig['default_file_path']) { 128 | $container->getDefinition('stof_doctrine_extensions.listener.uploadable') 129 | ->addMethodCall('setDefaultPath', array($uploadableConfig['default_file_path'])); 130 | } 131 | 132 | if ($uploadableConfig['mime_type_guesser_class']) { 133 | if (!class_exists($uploadableConfig['mime_type_guesser_class'])) { 134 | $msg = 'Class "%s" configured to use as the mime type guesser in the Uploadable extension does not exist.'; 135 | 136 | throw new \InvalidArgumentException(sprintf($msg, $uploadableConfig['mime_type_guesser_class'])); 137 | } 138 | 139 | $container->setParameter( 140 | 'stof_doctrine_extensions.uploadable.mime_type_guesser.class', 141 | $uploadableConfig['mime_type_guesser_class'] 142 | ); 143 | } 144 | } 145 | 146 | if (isset($config['metadata_cache_pool'])) { 147 | $container->setAlias('stof_doctrine_extensions.metadata_cache', new Alias($config['metadata_cache_pool'], false)); 148 | } else { 149 | $container->register('stof_doctrine_extensions.metadata_cache', ArrayAdapter::class)->setPublic(false); 150 | } 151 | 152 | foreach ($config['class'] as $listener => $class) { 153 | $container->setParameter(sprintf('stof_doctrine_extensions.listener.%s.class', $listener), $class); 154 | } 155 | } 156 | 157 | /** 158 | * @internal 159 | */ 160 | public function configValidate(ContainerBuilder $container): void 161 | { 162 | foreach ($this->entityManagers as $name) { 163 | if (!$container->hasDefinition(sprintf('doctrine.dbal.%s_connection', $name))) { 164 | throw new \InvalidArgumentException(sprintf('Invalid %s config: DBAL connection "%s" not found', $this->getAlias(), $name)); 165 | } 166 | } 167 | 168 | foreach ($this->documentManagers as $name) { 169 | if (!$container->hasDefinition(sprintf('doctrine_mongodb.odm.%s_document_manager', $name))) { 170 | throw new \InvalidArgumentException(sprintf('Invalid %s config: document manager "%s" not found', $this->getAlias(), $name)); 171 | } 172 | } 173 | } 174 | 175 | /** 176 | * @param array> $configs 177 | * @param ContainerBuilder $container 178 | * @param LoaderInterface $loader 179 | * @param array $loaded 180 | * @param string $doctrineListenerTag 181 | * 182 | * @return list 183 | */ 184 | private function processObjectManagerConfigurations(array $configs, ContainerBuilder $container, LoaderInterface $loader, array &$loaded, string $doctrineListenerTag) 185 | { 186 | $usedManagers = array(); 187 | 188 | $listenerPriorities = array( 189 | 'translatable' => -10, 190 | 'loggable' => 5, 191 | 'uploadable' => -5, 192 | ); 193 | 194 | foreach ($configs as $name => $listeners) { 195 | foreach ($listeners as $ext => $enabled) { 196 | if (!$enabled) { 197 | continue; 198 | } 199 | 200 | if (!isset($loaded[$ext])) { 201 | $loader->load($ext.'.xml'); 202 | $loaded[$ext] = true; 203 | } 204 | 205 | $attributes = array('connection' => $name); 206 | 207 | if (isset($listenerPriorities[$ext])) { 208 | $attributes['priority'] = $listenerPriorities[$ext]; 209 | } 210 | 211 | $definition = $container->getDefinition(sprintf('stof_doctrine_extensions.listener.%s', $ext)); 212 | 213 | foreach (self::LISTENER_EVENTS[$ext] as $event) { 214 | $attributes['event'] = $event; 215 | $definition->addTag($doctrineListenerTag, $attributes); 216 | } 217 | 218 | $usedManagers[$name] = true; 219 | } 220 | } 221 | 222 | return array_keys($usedManagers); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/EventListener/BlameListener.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @deprecated to be removed in 2.0, use the actor provider instead 19 | */ 20 | class BlameListener implements EventSubscriberInterface 21 | { 22 | private ?AuthorizationCheckerInterface $authorizationChecker; 23 | private ?TokenStorageInterface $tokenStorage; 24 | private BlameableListener $blameableListener; 25 | 26 | public function __construct(BlameableListener $blameableListener, ?TokenStorageInterface $tokenStorage = null, ?AuthorizationCheckerInterface $authorizationChecker = null) 27 | { 28 | $this->blameableListener = $blameableListener; 29 | $this->tokenStorage = $tokenStorage; 30 | $this->authorizationChecker = $authorizationChecker; 31 | } 32 | 33 | /** 34 | * @internal 35 | */ 36 | public function onKernelRequest(RequestEvent $event): void 37 | { 38 | if (!$event->isMainRequest()) { 39 | return; 40 | } 41 | 42 | if (null === $this->tokenStorage || null === $this->authorizationChecker) { 43 | return; 44 | } 45 | 46 | $token = $this->tokenStorage->getToken(); 47 | if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) { 48 | $this->blameableListener->setUserValue($token->getUser()); 49 | } 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public static function getSubscribedEvents() 56 | { 57 | return array( 58 | KernelEvents::REQUEST => 'onKernelRequest', 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/EventListener/LocaleListener.php: -------------------------------------------------------------------------------- 1 | translatableListener = $translatableListener; 24 | } 25 | 26 | /** 27 | * @internal 28 | */ 29 | public function onKernelRequest(RequestEvent $event): void 30 | { 31 | $this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale()); 32 | } 33 | 34 | /** 35 | * @return array 36 | */ 37 | public static function getSubscribedEvents() 38 | { 39 | return array( 40 | KernelEvents::REQUEST => 'onKernelRequest', 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/EventListener/LoggerListener.php: -------------------------------------------------------------------------------- 1 | 18 | * 19 | * @deprecated to be removed in 2.0, use the actor provider instead 20 | * 21 | * @phpstan-template T of Loggable|object 22 | */ 23 | class LoggerListener implements EventSubscriberInterface 24 | { 25 | private ?AuthorizationCheckerInterface $authorizationChecker; 26 | private ?TokenStorageInterface $tokenStorage; 27 | /** @var LoggableListener */ 28 | private LoggableListener $loggableListener; 29 | 30 | /** 31 | * @param LoggableListener $loggableListener 32 | */ 33 | public function __construct(LoggableListener $loggableListener, ?TokenStorageInterface $tokenStorage = null, ?AuthorizationCheckerInterface $authorizationChecker = null) 34 | { 35 | $this->loggableListener = $loggableListener; 36 | $this->tokenStorage = $tokenStorage; 37 | $this->authorizationChecker = $authorizationChecker; 38 | } 39 | 40 | /** 41 | * @internal 42 | */ 43 | public function onKernelRequest(RequestEvent $event): void 44 | { 45 | if (!$event->isMainRequest()) { 46 | return; 47 | } 48 | 49 | if (null === $this->tokenStorage || null === $this->authorizationChecker) { 50 | return; 51 | } 52 | 53 | $token = $this->tokenStorage->getToken(); 54 | 55 | if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) { 56 | $this->loggableListener->setUsername($token); 57 | } 58 | } 59 | 60 | /** 61 | * @return array 62 | */ 63 | public static function getSubscribedEvents() 64 | { 65 | return array( 66 | KernelEvents::REQUEST => 'onKernelRequest', 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/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 | The "%service_id%" service is deprecated and will be removed in 2.0. The "stof_doctrine_extensions.tool.actor_provider" service should be used to provide the user instead. 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Resources/config/ip_traceable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/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 | The "%service_id%" service is deprecated and will be removed in 2.0. The "stof_doctrine_extensions.tool.actor_provider" service should be used to provide the user instead. 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Resources/config/reference_integrity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\ReferenceIntegrity\ReferenceIntegrityListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Resources/config/sluggable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\Sluggable\SluggableListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Resources/config/softdeleteable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\SoftDeleteable\SoftDeleteableListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Resources/config/sortable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\Sortable\SortableListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Resources/config/timestampable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\Timestampable\TimestampableListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Resources/config/tool.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/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 | 18 | 19 | 20 | %stof_doctrine_extensions.default_locale% 21 | 22 | 23 | %stof_doctrine_extensions.default_locale% 24 | 25 | 26 | %stof_doctrine_extensions.translation_fallback% 27 | 28 | 29 | %stof_doctrine_extensions.persist_default_translation% 30 | 31 | 32 | %stof_doctrine_extensions.skip_translation_on_load% 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | The "%service_id%" service is deprecated and will be removed in 2.0. The "stof_doctrine_extensions.tool.locale_synchronizer" service should be used to provide the user instead. 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/Resources/config/tree.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Gedmo\Tree\TreeListener 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/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 | 24 | 25 | 26 | %stof_doctrine_extensions.uploadable.default_file_info.class% 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | %stof_doctrine_extensions.uploadable.default_file_info.class% 35 | 36 | 37 | 38 | 39 | 40 | %stof_doctrine_extensions.uploadable.validate_writable_directory% 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/StofDoctrineExtensionsBundle.php: -------------------------------------------------------------------------------- 1 | addCompilerPass(new ValidateExtensionConfigurationPass()); 20 | $container->addCompilerPass(new ReaderPass()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Tool/LocaleSynchronizer.php: -------------------------------------------------------------------------------- 1 | listener = $listener; 18 | } 19 | 20 | public function setLocale(string $locale): void 21 | { 22 | $this->listener->setTranslatableLocale($locale); 23 | } 24 | 25 | public function getLocale(): string 26 | { 27 | return $this->listener->getListenerLocale(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Tool/RequestStackIpAddressProvider.php: -------------------------------------------------------------------------------- 1 | requestStack = $requestStack; 20 | } 21 | 22 | public function getAddress(): ?string 23 | { 24 | if (null === $this->requestStack) { 25 | return null; 26 | } 27 | 28 | $request = $this->requestStack->getCurrentRequest(); 29 | 30 | if (null === $request) { 31 | return null; 32 | } 33 | 34 | return $request->getClientIp(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Tool/TokenStorageActorProvider.php: -------------------------------------------------------------------------------- 1 | tokenStorage = $tokenStorage; 23 | $this->authorizationChecker = $authorizationChecker; 24 | } 25 | 26 | public function getActor(): ?UserInterface 27 | { 28 | if (null === $this->tokenStorage || null === $this->authorizationChecker) { 29 | return null; 30 | } 31 | 32 | $token = $this->tokenStorage->getToken(); 33 | 34 | if (null === $token || !$this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) { 35 | return null; 36 | } 37 | 38 | return $token->getUser(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Uploadable/MimeTypeGuesserAdapter.php: -------------------------------------------------------------------------------- 1 | guessMimeType($filePath); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/Uploadable/UploadableManager.php: -------------------------------------------------------------------------------- 1 | */ 13 | private string $fileInfoClass; 14 | 15 | /** 16 | * @param class-string $fileInfoClass 17 | */ 18 | public function __construct(UploadableListener $listener, string $fileInfoClass) 19 | { 20 | $this->listener = $listener; 21 | $this->fileInfoClass = $fileInfoClass; 22 | } 23 | 24 | /** 25 | * This method marks an entity to be uploaded as soon as the "flush" method of your object manager is called. 26 | * After calling this method, the file info you passed is set for this entity in the listener. This is all it takes 27 | * to upload a file for an entity in the Uploadable extension. 28 | * 29 | * @param object $entity - The entity you are marking to "Upload" as soon as you call "flush". 30 | * @param mixed $fileInfo - The file info object or array. In Symfony, this will be typically an UploadedFile instance. 31 | * 32 | * @return void 33 | */ 34 | public function markEntityToUpload($entity, $fileInfo) 35 | { 36 | if (is_object($fileInfo) && $fileInfo instanceof UploadedFile) { 37 | $fileInfoClass = $this->fileInfoClass; 38 | 39 | $fileInfo = new $fileInfoClass($fileInfo); 40 | } 41 | 42 | $this->listener->addEntityFileInfo($entity, $fileInfo); 43 | } 44 | 45 | /** 46 | * @return \Gedmo\Uploadable\UploadableListener 47 | */ 48 | public function getUploadableListener() 49 | { 50 | return $this->listener; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Uploadable/UploadedFileInfo.php: -------------------------------------------------------------------------------- 1 | uploadedFile = $uploadedFile; 15 | } 16 | 17 | /** 18 | * @return ?string 19 | */ 20 | public function getTmpName() 21 | { 22 | return $this->uploadedFile->getPathname(); 23 | } 24 | 25 | /** 26 | * @return ?string 27 | */ 28 | public function getName() 29 | { 30 | return $this->uploadedFile->getClientOriginalName(); 31 | } 32 | 33 | /** 34 | * @return int|null 35 | */ 36 | public function getSize() 37 | { 38 | $size = $this->uploadedFile->getSize(); 39 | 40 | return $size !== false ? $size : null; 41 | } 42 | 43 | /** 44 | * @return ?string 45 | */ 46 | public function getType() 47 | { 48 | return $this->uploadedFile->getMimeType(); 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getError() 55 | { 56 | return $this->uploadedFile->getError(); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * 62 | * @return bool 63 | */ 64 | public function isUploadedFile() 65 | { 66 | return is_uploaded_file($this->uploadedFile->getPathname()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Uploadable/ValidatorConfigurator.php: -------------------------------------------------------------------------------- 1 | validateWritableDirectory = $validateWritableDirectory; 17 | } 18 | 19 | public function configure(): void 20 | { 21 | Validator::$validateWritableDirectory = $this->validateWritableDirectory; 22 | } 23 | } 24 | --------------------------------------------------------------------------------