├── .gitignore ├── .php_cs.dist ├── .scrutinizer.yml ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── composer.json ├── docker-compose.yml ├── phpunit.xml.dist ├── quality-analysis └── phpstan │ ├── bootstrap.php │ └── phpstan.neon ├── src ├── Action │ ├── AbstractDisableDrupalCacheAction.php │ ├── AbstractFileBackendDependantOptions.php │ ├── AbstractOverrideConfigAction.php │ ├── AbstractOverrideTwigConfigAction.php │ ├── ActionInterface.php │ ├── ActionRegistrar.php │ ├── ActionWithOptionsInterface.php │ ├── CompilerPassActionInterface.php │ ├── DisableCSSAggregation │ │ └── DisableCSSAggregationAction.php │ ├── DisableDynamicPageCache │ │ └── DisableDynamicPageCacheAction.php │ ├── DisableInternalPageCache │ │ └── DisableInternalPageCacheAction.php │ ├── DisableJSAggregation │ │ └── DisableJSAggregationAction.php │ ├── DisableRenderCache │ │ └── DisableRenderCacheAction.php │ ├── DisableTwigCache │ │ └── DisableTwigCacheAction.php │ ├── DisplayDumpLocation │ │ └── DisplayDumpLocationAction.php │ ├── DisplayPrettyExceptions │ │ ├── DisplayPrettyExceptionsAction.php │ │ ├── DisplayPrettyExceptionsOptions.php │ │ └── ExceptionController.php │ ├── DisplayPrettyExceptionsASAP │ │ ├── DisplayPrettyExceptionsASAPAction.php │ │ └── DisplayPrettyExceptionsASAPOptions.php │ ├── EnableDebugClassLoader │ │ └── EnableDebugClassLoaderAction.php │ ├── EnableTwigDebug │ │ └── EnableTwigDebugAction.php │ ├── EnableTwigStrictVariables │ │ └── EnableTwigStrictVariablesAction.php │ ├── EventSubscriberActionInterface.php │ ├── ThrowErrorsAsExceptions │ │ ├── ThrowErrorsAsExceptionsAction.php │ │ └── ThrowErrorsAsExceptionsOptions.php │ ├── ValidateContainerDefinitionTrait.php │ ├── WatchContainerDefinitions │ │ ├── WatchContainerDefinitionsAction.php │ │ └── WatchContainerDefinitionsOptions.php │ ├── WatchModulesHooksImplementations │ │ ├── LoadNewModuleFile.php │ │ ├── WatchModulesHooksImplementationsAction.php │ │ └── WatchModulesHooksImplementationsOptions.php │ └── WatchRoutingDefinitions │ │ ├── WatchRoutingDefinitionsAction.php │ │ └── WatchRoutingDefinitionsOptions.php ├── ActionMetadata │ ├── ActionMetadataFactory.php │ ├── ActionMetadataManager.php │ └── Model │ │ ├── ActionMetadata.php │ │ └── ActionWithOptionsMetadata.php ├── Cache │ ├── Event │ │ ├── CacheNotFreshEvent.php │ │ └── FileBackendEvents.php │ ├── FileBackend.php │ └── FileCache.php ├── Composer │ ├── Command │ │ ├── CommandProvider.php │ │ ├── DisableOriginalDrupalKernelSubstitutionCommand.php │ │ ├── DumpReferenceConfigurationFileCommand.php │ │ └── EnableOriginalDrupalKernelSubstitutionCommand.php │ ├── Helper │ │ └── ManageConfigurationHelper.php │ └── Plugin │ │ ├── ManageConfigurationPlugin.php │ │ └── RegisterCommandsPlugin.php ├── Configuration │ ├── AbstractConfiguration.php │ ├── ActionsConfiguration.php │ ├── CacheDirectoryPathConfigurationTrait.php │ ├── CharsetConfigurationTrait.php │ ├── ConfigurationManager.php │ ├── DefaultsConfiguration.php │ ├── FileLinkFormatConfigurationTrait.php │ ├── LoggerConfigurationTrait.php │ ├── Model │ │ ├── AbstractConfiguration.php │ │ ├── ActionConfiguration.php │ │ ├── DefaultsConfiguration.php │ │ └── SubstituteOriginalDrupalKernelConfiguration.php │ └── SubstituteOriginalDrupalKernelConfiguration.php ├── Drupal │ └── Core │ │ └── OriginalDrupalKernel.php ├── Exception │ ├── NotImplementedException.php │ └── NotSupportedException.php ├── Extension │ ├── CustomExtensionDiscovery.php │ ├── Iterator │ │ ├── NullRecursiveIterator.php │ │ └── RecursiveCustomExtensionFilterIterator.php │ └── Model │ │ ├── AbstractCustomExtension.php │ │ ├── CustomExtensionInterface.php │ │ ├── CustomModule.php │ │ └── CustomTheme.php ├── Helper │ └── SettingsHelper.php ├── Kernel │ ├── DebugKernel.php │ ├── Event │ │ ├── AbstractBaseEvent.php │ │ ├── AbstractWithContainerAndEnabledExtensionsEvent.php │ │ ├── AbstractWithEnabledExtensionsEvent.php │ │ ├── AfterAttachSyntheticEvent.php │ │ ├── AfterContainerInitializationEvent.php │ │ ├── AfterRequestPreHandleEvent.php │ │ ├── AfterSettingsInitializationEvent.php │ │ └── DebugKernelEvents.php │ └── Helper │ │ └── OriginalDrupalKernelHelper.php ├── Logger │ └── LoggerStack.php ├── Option │ ├── OptionsInterface.php │ ├── OptionsStack.php │ └── OptionsStackBuilder.php ├── Resource │ ├── Model │ │ ├── CustomExtensionFileResource.php │ │ └── ResourcesCollection.php │ └── ResourcesFreshnessChecker.php └── initialize.php └── tests ├── Integration ├── AbstractTestCase.php ├── Action │ ├── AbstractActionTestCase.php │ ├── DisableCSSAggregation │ │ └── DisableCSSAggregationActionTest.php │ ├── DisableDynamicPageCache │ │ ├── DisableDynamicPageCacheActionTest.php │ │ └── fixtures │ │ │ ├── ControllerTemplate.php │ │ │ └── modules │ │ │ └── hit_dynamic_page_cache │ │ │ ├── hit_dynamic_page_cache.info.yml │ │ │ ├── hit_dynamic_page_cache.routing.yml │ │ │ └── src │ │ │ └── Controller │ │ │ └── .gitkeep │ ├── DisableInternalPageCache │ │ ├── DisableInternalPageCacheActionTest.php │ │ └── fixtures │ │ │ ├── ControllerTemplate.php │ │ │ └── modules │ │ │ └── hit_page_cache │ │ │ ├── hit_page_cache.info.yml │ │ │ ├── hit_page_cache.routing.yml │ │ │ └── src │ │ │ └── Controller │ │ │ └── .gitkeep │ ├── DisableJSAggregation │ │ ├── DisableJSAggregationActionTest.php │ │ └── fixtures │ │ │ └── modules │ │ │ └── add_js_scripts │ │ │ ├── add_js_scripts.info.yml │ │ │ ├── add_js_scripts.libraries.yml │ │ │ ├── add_js_scripts.module │ │ │ └── assets │ │ │ └── js │ │ │ ├── 1.js │ │ │ └── 2.js │ ├── DisableRenderCache │ │ ├── DisableRenderCacheActionTest.php │ │ └── fixtures │ │ │ ├── ControllerTemplate.php │ │ │ └── modules │ │ │ └── hit_render_cache │ │ │ ├── hit_render_cache.info.yml │ │ │ ├── hit_render_cache.routing.yml │ │ │ └── src │ │ │ └── Controller │ │ │ └── .gitkeep │ ├── DisableTwigCache │ │ ├── DisableTwigCacheActionTest.php │ │ └── fixtures │ │ │ └── modules │ │ │ └── use_twig_template │ │ │ ├── src │ │ │ └── Controller │ │ │ │ └── FooController.php │ │ │ ├── templates │ │ │ └── .gitkeep │ │ │ ├── use_twig_template.info.yml │ │ │ ├── use_twig_template.module │ │ │ └── use_twig_template.routing.yml │ ├── DisplayDumpLocation │ │ ├── DisplayDumpLocationActionTest.php │ │ └── fixtures │ │ │ └── modules │ │ │ └── add_dump_die │ │ │ ├── add_dump_die.info.yml │ │ │ └── add_dump_die.module │ ├── DisplayPrettyExceptions │ │ ├── DisplayPrettyExceptionsActionTest.php │ │ └── fixtures │ │ │ └── modules │ │ │ └── throw_uncaught_exception │ │ │ ├── throw_uncaught_exception.info.yml │ │ │ └── throw_uncaught_exception.module │ ├── DisplayPrettyExceptionsASAP │ │ ├── DisplayPrettyExceptionsASAPActionTest.php │ │ └── fixtures │ │ │ ├── index.php │ │ │ └── modules │ │ │ └── throw_uncaught_exception │ │ │ ├── throw_uncaught_exception.info.yml │ │ │ └── throw_uncaught_exception.module │ ├── EnableTwigDebug │ │ └── EnableTwigDebugActionTest.php │ ├── SetupListener.php │ ├── ThrowErrorsAsExceptions │ │ ├── ThrowErrorsAsExceptionsActionTest.php │ │ └── fixtures │ │ │ └── modules │ │ │ └── trigger_error │ │ │ ├── trigger_error.info.yml │ │ │ └── trigger_error.module │ ├── WatchContainerDefinitions │ │ ├── WatchContainerDefinitionsActionTest.php │ │ └── fixtures │ │ │ ├── ServiceProviderTemplate.php │ │ │ ├── modules │ │ │ └── use_custom_service │ │ │ │ ├── src │ │ │ │ └── Service │ │ │ │ │ └── FooService.php │ │ │ │ ├── use_custom_service.info.yml │ │ │ │ └── use_custom_service.module │ │ │ └── services_template.yml │ ├── WatchModulesHooksImplementations │ │ ├── WatchModulesHooksImplementationsTest.php │ │ └── fixtures │ │ │ ├── implement_hook.module │ │ │ ├── module_hook_to_add.php │ │ │ └── modules │ │ │ └── implement_hook │ │ │ └── implement_hook.info.yml │ ├── WatchRoutingDefinitions │ │ ├── WatchRoutingDefinitionsActionTest.php │ │ └── fixtures │ │ │ ├── modules │ │ │ └── use_custom_route │ │ │ │ ├── src │ │ │ │ └── Controller │ │ │ │ │ └── FooController.php │ │ │ │ └── use_custom_route.info.yml │ │ │ └── routing_template.yml │ └── reference │ │ └── .gitkeep ├── Drush │ └── DrushCacheRebuildTest.php ├── cache │ └── .gitkeep └── fixtures │ └── drupal-debug.yml ├── Traits └── FileHelperTrait.php └── Unit └── src ├── Action ├── AbstractDisableDrupalCacheActionTest.php ├── AbstractFileBackendDependantOptionsTest.php ├── AbstractOverrideConfigActionTest.php ├── AbstractOverrideTwigConfigActionTest.php ├── ActionRegistrarTest.php ├── DisableCSSAggregation │ └── DisableCSSAggregationActionTest.php ├── DisableJSAggregation │ └── DisableJSAggregationActionTest.php ├── DisplayDumpLocation │ └── DisplayDumpLocationActionTest.php ├── DisplayPrettyExceptions │ ├── DisplayPrettyExceptionsActionTest.php │ ├── DisplayPrettyExceptionsOptionsTest.php │ └── ExceptionControllerTest.php ├── DisplayPrettyExceptionsASAP │ ├── DisplayPrettyExceptionsASAPActionTest.php │ └── DisplayPrettyExceptionsASAPOptionsTest.php ├── EnableDebugClassLoader │ └── EnableDebugClassLoaderActionTest.php ├── ThrowErrorsAsExceptions │ ├── ThrowErrorsAsExceptionsActionTest.php │ └── ThrowErrorsAsExceptionsOptionsTest.php ├── WatchContainerDefinitions │ └── WatchContainerDefinitionsActionTest.php ├── WatchModulesHooksImplementations │ ├── LoadNewModuleFileTest.php │ └── WatchModulesHooksImplementationsActionTest.php ├── WatchRoutingDefinitions │ ├── WatchRoutingDefinitionsActionTest.php │ └── fixtures │ │ └── File1.php ├── cache │ └── .gitkeep ├── fixtures │ ├── custom_extensions │ │ ├── modules │ │ │ └── module_ccc │ │ │ │ ├── bar.xml │ │ │ │ ├── fcy.info.yml │ │ │ │ └── src │ │ │ │ ├── BarFcyFoo.php │ │ │ │ └── bar │ │ │ │ └── ccc_fcy.yml │ │ └── themes │ │ │ └── a_theme │ │ │ ├── foo.php │ │ │ ├── great_theme.info.yml │ │ │ └── src │ │ │ └── great_theme_bar.yml │ └── drupal-debug.yml └── test_classes │ ├── TestCompilerPassAction.php │ └── TestEventSubscriberAction.php ├── Cache ├── Event │ └── CacheNotFreshEventTest.php ├── FileBackendTest.php ├── FileCacheTest.php └── fixtures │ ├── data_key_does_not_exist.php │ ├── invalid.php │ ├── not_an_array.php │ └── valid.php ├── Composer ├── Command │ └── CommandProviderTest.php ├── Helper │ ├── ManageConfigurationHelperTest.php │ ├── fixtures │ │ ├── drupal-debug.yml │ │ ├── not_writeable │ │ │ └── drupal-debug.yml │ │ └── toggle_substitution_cases │ │ │ ├── level-1-is-not-set.yml │ │ │ └── unknown-root-key.yml │ └── helper │ │ └── BufferIO.php └── Plugin │ ├── ManageConfigurationPluginTest.php │ └── RegisterCommandsPluginTest.php ├── Configuration └── Model │ ├── DefaultsConfigurationTest.php │ ├── SubstituteOriginalDrupalKernelConfigurationTest.php │ ├── cache │ └── .gitkeep │ └── fixtures │ ├── invalid_autoload.php │ └── valid_autoload.php ├── Exception ├── NotImplementedExceptionTest.php └── NotSupportedExceptionTest.php ├── Extension ├── CustomExtensionDiscoveryTest.php ├── Iterator │ └── RecursiveCustomExtensionFilterIteratorTest.php ├── Model │ ├── AbstractCustomExtensionTest.php │ └── CustomModuleTest.php └── fixtures │ └── custom_extensions │ ├── modules │ ├── module.info.yml │ └── sub │ │ ├── sub.info.yml │ │ └── sub │ │ └── sub │ │ └── we │ │ └── need │ │ └── to_go_deeper │ │ └── my_module.info.yml │ ├── sites │ ├── all │ │ ├── modules │ │ │ ├── foo.info.yml │ │ │ ├── src │ │ │ │ └── should_not_match.info.yml │ │ │ └── sub │ │ │ │ ├── bar.info.yml │ │ │ │ └── sub │ │ │ │ └── sub │ │ │ │ └── fcy.info.yml │ │ └── unrelated │ │ │ └── unrelated.info.yml │ └── unrelated │ │ └── unrelated.info.yml │ ├── themes │ ├── ccc.info.yml │ └── sub │ │ ├── foo.info.yml │ │ └── sub │ │ ├── lib │ │ └── should_not_match.info.yml │ │ └── sub │ │ └── fcy.info.yml │ └── unrelated │ └── unrelated.info.yml ├── Helper └── SettingsHelperTest.php ├── Kernel ├── DebugKernelTest.php ├── Event │ ├── AbstractWithContainerAndEnabledExtensionsEventTest.php │ └── AbstractWithEnabledExtensionsEventTest.php ├── Helper │ ├── OriginalDrupalKernelHelperTest.php │ ├── cache │ │ └── .gitkeep │ ├── fixtures │ │ ├── OriginalDrupalKernel.php │ │ └── no_replacements.php │ └── test_classes │ │ └── TestOtherKernel.php └── test_classes │ ├── DebugKernelTest_TestDebugKernel.php │ ├── DebugKernelTest_TestDebugKernelInstantiation.php │ └── DebugKernelTest_TestOriginalDrupalKernel.php ├── Option ├── OptionsStackBuilderTest.php └── OptionsStackTest.php └── Resource ├── Model ├── CustomExtensionFileResourceTest.php ├── ResourcesCollectionTest.php └── fixtures │ ├── File1.php │ └── File2.php ├── ResourcesFreshnessCheckerTest.php └── fixtures ├── File1.php ├── File2.php ├── File3.php └── unexpected_content.meta /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /composer.lock 3 | /.php_cs.cache 4 | /tests/**/reference/** 5 | !/tests/**/reference/.gitkeep 6 | /tests/**/cache/** 7 | !/tests/**/cache/.gitkeep 8 | /tests/**/fixtures/**/__* 9 | /tests/**/fixtures/**/--* 10 | /cache/ 11 | /drupal-debug.yml 12 | -------------------------------------------------------------------------------- /.php_cs.dist: -------------------------------------------------------------------------------- 1 | setRules(array( 16 | '@Symfony' => true, 17 | '@Symfony:risky' => true, 18 | 'array_syntax' => array( 19 | 'syntax' => 'long' 20 | ), 21 | 'declare_strict_types' => true, 22 | 'header_comment' => array( 23 | 'header' => $header, 24 | ), 25 | 'native_function_invocation' => array( 26 | 'include' => array('@all'), 27 | ), 28 | 'no_useless_else' => true, 29 | 'no_useless_return' => true, 30 | 'ordered_imports' => true, 31 | 'phpdoc_types_order' => array( 32 | 'null_adjustment' => 'always_last', 33 | 'sort_algorithm' => 'none' 34 | ), 35 | 'psr4' => false, 36 | )) 37 | ->setRiskyAllowed(true) 38 | ->setFinder( 39 | PhpCsFixer\Finder::create() 40 | ->in(array( 41 | __DIR__.'/src', 42 | __DIR__.'/tests', 43 | )) 44 | ->notPath('Unit/src/Cache/fixtures/invalid.php') 45 | ); 46 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | build: 2 | nodes: 3 | analysis: 4 | tests: 5 | override: 6 | - php-scrutinizer-run 7 | filter: 8 | paths: 9 | - src/* 10 | checks: 11 | php: true 12 | tools: 13 | external_code_coverage: 14 | timeout: 600 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | branches: 4 | only: 5 | - master 6 | 7 | jobs: 8 | include: 9 | - 10 | php: "7.1" 11 | - 12 | php: "7.2" 13 | env: lint=1 14 | - 15 | php: "7.3" 16 | env: coverage=1 17 | - 18 | php: "7.3" 19 | env: deps=low 20 | 21 | cache: 22 | directories: 23 | - $HOME/.composer/cache 24 | 25 | before_script: 26 | - if [[ $coverage != '1' ]]; then 27 | phpenv config-rm xdebug.ini || echo "xdebug not available"; 28 | fi 29 | 30 | install: 31 | - if [[ $deps = 'low' ]]; then 32 | composer update --prefer-dist --no-progress --no-suggest --prefer-stable --prefer-lowest --ansi; 33 | if [[ $TRAVIS_EVENT_TYPE = 'cron' ]]; then 34 | composer require drupal/core:8.8.x-dev --update-with-all-dependencies --prefer-lowest --prefer-dist --no-progress --no-suggest --ansi; 35 | fi 36 | else 37 | composer update --prefer-dist --no-progress --no-suggest --ansi; 38 | if [[ $TRAVIS_EVENT_TYPE = 'cron' ]]; then 39 | composer require drupal/core:8.8.x-dev --update-with-all-dependencies --prefer-dist --no-progress --no-suggest --ansi; 40 | fi 41 | fi 42 | 43 | script: 44 | - if [[ $coverage = '1' ]]; then 45 | vendor/bin/phpunit --dump-xdebug-filter xdebug_filter.php; 46 | vendor/bin/phpunit --coverage-clover=coverage.clover --prepend=xdebug_filter.php; 47 | else 48 | vendor/bin/phpunit --no-coverage; 49 | fi 50 | - if [[ $coverage = '1' ]]; then 51 | wget https://scrutinizer-ci.com/ocular.phar; 52 | php ocular.phar code-coverage:upload --format=php-clover --revision=$TRAVIS_PULL_REQUEST_SHA coverage.clover; 53 | fi 54 | - if [[ $lint = '1' ]]; then 55 | vendor/bin/php-cs-fixer fix --dry-run --diff --no-ansi; 56 | fi 57 | - if [[ $lint = '1' ]]; then 58 | vendor/bin/phpstan analyse -c quality-analysis/phpstan/phpstan.neon; 59 | fi 60 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this project 2 | 3 | ## Running tests locally 4 | 5 | To run tests locally for a specific version of PHP: 6 | 7 | ```bash 8 | $ rm -rf vendor composer.lock 9 | $ docker-compose up 10 | $ docker-compose run --user www-data php-$WANTED_PHP_VERSION bash 11 | container$ composer install 12 | container$ vendor/bin/phpunit --no-coverage 13 | ``` 14 | 15 | ## Reporting Issues 16 | 17 | When reporting issues, please try to be as descriptive as possible, and include 18 | as much relevant information as you can. A step by step guide on how to 19 | reproduce the issue will greatly increase the chances of your issue being 20 | resolved in a timely manner. 21 | 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PHP_VERSION 2 | FROM php:$PHP_VERSION 3 | 4 | ENV TERM xterm 5 | 6 | RUN apk add --update --upgrade \ 7 | bash \ 8 | curl \ 9 | libxml2 \ 10 | git \ 11 | vim \ 12 | zip \ 13 | patch \ 14 | jpeg-dev libpng libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libzip-dev libxpm-dev freetype-dev 15 | 16 | RUN deluser www-data && adduser -D -g 'php user' -h /var/www -s /bin/false www-data \ 17 | && docker-php-ext-configure gd \ 18 | --with-jpeg-dir=/usr/include/ \ 19 | --with-freetype-dir=/usr/include/freetype2 \ 20 | && docker-php-ext-install -j "$(nproc)" \ 21 | gd \ 22 | opcache \ 23 | zip \ 24 | && docker-php-source delete \ 25 | && rm -rf /usr/share/vim/vim74/doc/* /usr/share/vim/vim74/tutor/* /usr/src/php.tar* /var/cache/apk/* 26 | 27 | RUN curl -sS https://getcomposer.org/installer | php && mv composer.phar /usr/local/bin/composer \ 28 | && composer global require hirak/prestissimo 29 | 30 | RUN { \ 31 | echo 'expose_php = 0'; \ 32 | echo 'post_max_size = 40M'; \ 33 | echo 'upload_max_filesize = 20M'; \ 34 | echo 'max_file_uploads = 10'; \ 35 | echo 'opcache.memory_consumption = 1024'; \ 36 | echo 'opcache.interned_strings_buffer=8'; \ 37 | echo 'opcache.max_accelerated_files = 10007'; \ 38 | echo 'opcache.revalidate_freq=60'; \ 39 | echo 'opcache.fast_shutdown=1'; \ 40 | echo 'opcache.enable_cli=1'; \ 41 | echo 'memory_limit=2048M'; \ 42 | echo 'realpath_cache_size = 64k'; \ 43 | echo 'realpath_cache_ttl = 3600'; \ 44 | echo 'error_reporting = E_ALL | E_STRICT'; \ 45 | } > /usr/local/etc/php/conf.d/php.ini 46 | 47 | WORKDIR /app 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) ekino 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 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | php-7.1: 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | args: 10 | PHP_VERSION: 7.1-cli-alpine 11 | volumes: 12 | - .:/app:delegated 13 | 14 | php-7.2: 15 | build: 16 | context: . 17 | dockerfile: Dockerfile 18 | args: 19 | PHP_VERSION: 7.2-cli-alpine 20 | volumes: 21 | - .:/app:delegated 22 | 23 | php-7.3: 24 | build: 25 | context: . 26 | dockerfile: Dockerfile 27 | args: 28 | PHP_VERSION: 7.3-cli-alpine 29 | volumes: 30 | - .:/app:delegated 31 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | tests/Unit 18 | 19 | 20 | tests/Integration/Action 21 | 22 | 23 | tests/Integration/Drush 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | src/ 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /quality-analysis/phpstan/bootstrap.php: -------------------------------------------------------------------------------- 1 | 'overrideSettings', 35 | DebugKernelEvents::AFTER_CONTAINER_INITIALIZATION => 'setNullBackend', 36 | ); 37 | } 38 | 39 | public function overrideSettings(): void 40 | { 41 | (new SettingsHelper())->override(\sprintf('[cache][bins][%s]', $this->getBin()), self::NULL_BACKEND_FACTORY_SERVICE_ID); 42 | } 43 | 44 | /** 45 | * @param AfterContainerInitializationEvent $event 46 | */ 47 | public function setNullBackend(AfterContainerInitializationEvent $event): void 48 | { 49 | $container = $event->getContainer(); 50 | if ($container->has(self::NULL_BACKEND_FACTORY_SERVICE_ID)) { 51 | return; 52 | } 53 | 54 | $container->set(self::NULL_BACKEND_FACTORY_SERVICE_ID, new NullBackendFactory()); 55 | } 56 | 57 | /** 58 | * @return string 59 | */ 60 | abstract protected function getBin(): string; 61 | } 62 | -------------------------------------------------------------------------------- /src/Action/AbstractOverrideConfigAction.php: -------------------------------------------------------------------------------- 1 | 'process', 28 | ); 29 | } 30 | 31 | public function process(): void 32 | { 33 | global $config; 34 | 35 | $propertyAccessor = PropertyAccess::createPropertyAccessor(); 36 | foreach ($this->getOverrides() as $propertyPath => $value) { 37 | $propertyAccessor->setValue($config, $propertyPath, $value); 38 | } 39 | } 40 | 41 | /** 42 | * @return array 43 | */ 44 | abstract protected function getOverrides(): array; 45 | } 46 | -------------------------------------------------------------------------------- /src/Action/AbstractOverrideTwigConfigAction.php: -------------------------------------------------------------------------------- 1 | hasParameter(self::TWIG_CONFIG_PARAMETER_NAME)) { 32 | throw new NotSupportedException(\sprintf('The "%s" parameter should already be set in the container builder.', self::TWIG_CONFIG_PARAMETER_NAME)); 33 | } 34 | 35 | $container->setParameter(self::TWIG_CONFIG_PARAMETER_NAME, \array_merge($container->getParameter(self::TWIG_CONFIG_PARAMETER_NAME), $this->getOverrides())); 36 | } 37 | 38 | /** 39 | * @return array 40 | */ 41 | abstract protected function getOverrides(): array; 42 | } 43 | -------------------------------------------------------------------------------- /src/Action/ActionInterface.php: -------------------------------------------------------------------------------- 1 | 'process', 28 | ); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | protected function getOverrides(): array 35 | { 36 | return array( 37 | '[system.performance][css][preprocess]' => false, 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Action/DisableDynamicPageCache/DisableDynamicPageCacheAction.php: -------------------------------------------------------------------------------- 1 | 'process', 28 | ); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | protected function getOverrides(): array 35 | { 36 | return array( 37 | '[system.performance][js][preprocess]' => false, 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Action/DisableRenderCache/DisableRenderCacheAction.php: -------------------------------------------------------------------------------- 1 | false, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Action/DisplayDumpLocation/DisplayDumpLocationAction.php: -------------------------------------------------------------------------------- 1 | 'process', 33 | ); 34 | } 35 | 36 | public function process(): void 37 | { 38 | if (!\class_exists(SourceContextProvider::class)) { 39 | return; 40 | } 41 | 42 | $cloner = new VarCloner(); 43 | $dumper = \in_array(\PHP_SAPI, array('cli', 'phpdbg'), true) ? new CliDumper() : new HtmlDumper(); 44 | 45 | VarDumper::setHandler(static function ($var) use ($cloner, $dumper): void { 46 | (function (): void { 47 | list('name' => $name, 'file' => $file, 'line' => $line) = (new SourceContextProvider())->getContext(); 48 | 49 | $attr = array(); 50 | if ($this instanceof HtmlDumper) { 51 | if (\is_string($file)) { 52 | $attr = array( 53 | 'file' => $file, 54 | 'line' => $line, 55 | 'title' => $file, 56 | ); 57 | } 58 | } else { 59 | $name = $file; 60 | } 61 | 62 | $this->line = \sprintf('%s on line %s:', $this->style('meta', $name, $attr), $this->style('meta', $line)); 63 | $this->dumpLine(0); 64 | })->bindTo($dumper, $dumper)(); 65 | 66 | $dumper->dump($cloner->cloneVar($var)); 67 | }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Action/DisplayPrettyExceptions/ExceptionController.php: -------------------------------------------------------------------------------- 1 | exceptionHandler = $exceptionHandler; 33 | } 34 | 35 | /** 36 | * @param FlattenException $exception 37 | * 38 | * @return Response 39 | */ 40 | public function __invoke(FlattenException $exception): Response 41 | { 42 | return new Response($this->exceptionHandler->getHtml($exception), $exception->getStatusCode()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Action/DisplayPrettyExceptionsASAP/DisplayPrettyExceptionsASAPAction.php: -------------------------------------------------------------------------------- 1 | 'process', 36 | ); 37 | } 38 | 39 | /** 40 | * @param DisplayPrettyExceptionsASAPOptions $options 41 | */ 42 | public function __construct(DisplayPrettyExceptionsASAPOptions $options) 43 | { 44 | $this->options = $options; 45 | } 46 | 47 | public function process(): void 48 | { 49 | // TODO: https://github.com/symfony/symfony/pull/28954 50 | \set_exception_handler(function (\Throwable $exception): void { 51 | if (!$exception instanceof \Exception) { 52 | $exception = new FatalThrowableError($exception); 53 | } 54 | 55 | $exceptionHandler = new ExceptionHandler(true, $this->options->getCharset(), $this->options->getFileLinkFormat()); 56 | $exceptionHandler->sendPhpResponse($exception); 57 | }); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public static function getOptionsClass(): string 64 | { 65 | return DisplayPrettyExceptionsASAPOptions::class; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Action/DisplayPrettyExceptionsASAP/DisplayPrettyExceptionsASAPOptions.php: -------------------------------------------------------------------------------- 1 | charset = $charset; 45 | $this->fileLinkFormat = $fileLinkFormat; 46 | } 47 | 48 | /** 49 | * @return string|null 50 | */ 51 | public function getCharset(): ?string 52 | { 53 | return $this->charset; 54 | } 55 | 56 | /** 57 | * @return string|null 58 | */ 59 | public function getFileLinkFormat(): ?string 60 | { 61 | return $this->fileLinkFormat; 62 | } 63 | 64 | public static function addConfiguration(NodeBuilder $nodeBuilder, DefaultsConfiguration $defaultsConfiguration): void 65 | { 66 | self::addCharsetConfigurationNodeFromDefaultsConfiguration($nodeBuilder, $defaultsConfiguration); 67 | self::addFileLinkFormatConfigurationNodeFromDefaultsConfiguration($nodeBuilder, $defaultsConfiguration); 68 | } 69 | 70 | public static function getOptions(string $appRoot, ActionConfiguration $actionConfiguration): OptionsInterface 71 | { 72 | return new self(self::getConfiguredCharset($actionConfiguration), self::getConfiguredFileLinkFormat($actionConfiguration)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Action/EnableDebugClassLoader/EnableDebugClassLoaderAction.php: -------------------------------------------------------------------------------- 1 | 'process', 29 | ); 30 | } 31 | 32 | public function process(): void 33 | { 34 | DebugClassLoader::enable(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Action/EnableTwigDebug/EnableTwigDebugAction.php: -------------------------------------------------------------------------------- 1 | true, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Action/EnableTwigStrictVariables/EnableTwigStrictVariablesAction.php: -------------------------------------------------------------------------------- 1 | true, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Action/EventSubscriberActionInterface.php: -------------------------------------------------------------------------------- 1 | 'process', 36 | ); 37 | } 38 | 39 | /** 40 | * @param ThrowErrorsAsExceptionsOptions $options 41 | */ 42 | public function __construct(ThrowErrorsAsExceptionsOptions $options) 43 | { 44 | $this->options = $options; 45 | } 46 | 47 | public function process(): void 48 | { 49 | $errorHandler = ErrorHandler::register(); 50 | 51 | $levels = $this->options->getLevels(); 52 | $errorHandler->throwAt($levels, true); 53 | 54 | $logger = $this->options->getLogger(); 55 | if ($logger instanceof LoggerInterface) { 56 | $errorHandler->setDefaultLogger($logger, $levels, true); 57 | } 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public static function getOptionsClass(): string 64 | { 65 | return ThrowErrorsAsExceptionsOptions::class; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Action/ThrowErrorsAsExceptions/ThrowErrorsAsExceptionsOptions.php: -------------------------------------------------------------------------------- 1 | levels = $levels; 44 | $this->logger = $logger; 45 | } 46 | 47 | /** 48 | * @return int 49 | */ 50 | public function getLevels(): int 51 | { 52 | return $this->levels; 53 | } 54 | 55 | /** 56 | * @return LoggerInterface|null 57 | */ 58 | public function getLogger(): ?LoggerInterface 59 | { 60 | return $this->logger; 61 | } 62 | 63 | public static function addConfiguration(NodeBuilder $nodeBuilder, DefaultsConfiguration $defaultsConfiguration): void 64 | { 65 | $nodeBuilder 66 | ->integerNode('levels') 67 | ->isRequired() 68 | ->defaultValue(E_ALL & ~E_WARNING & ~E_USER_WARNING) 69 | ->end(); 70 | 71 | self::addLoggerConfigurationNodeFromDefaultsConfiguration($nodeBuilder, $defaultsConfiguration); 72 | } 73 | 74 | public static function getOptions(string $appRoot, ActionConfiguration $actionConfiguration): OptionsInterface 75 | { 76 | $processedConfiguration = $actionConfiguration->getProcessedConfiguration(); 77 | 78 | //todo : evaluate les const E_* passé en string dans la conf ? 79 | 80 | return new self($processedConfiguration['levels'], self::getConfiguredLogger($actionConfiguration)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Action/ValidateContainerDefinitionTrait.php: -------------------------------------------------------------------------------- 1 | hasDefinition($name)) { 25 | throw new NotSupportedException(\sprintf('The "%s" service should already be set in the container.', $name)); 26 | } 27 | 28 | return $containerBuilder->getDefinition($name); 29 | } 30 | 31 | private function validateContainerDefinitionClassIs(ContainerBuilder $containerBuilder, string $name, string $expectedClass): Definition 32 | { 33 | $definition = $this->validateContainerDefinitionExists($containerBuilder, $name); 34 | if ($expectedClass !== $definition->getClass()) { 35 | throw new NotSupportedException(\sprintf('The "%s" service class should be "%s".', $name, $expectedClass)); 36 | } 37 | 38 | return $definition; 39 | } 40 | 41 | private function validateContainerDefinitionClassImplements(ContainerBuilder $containerBuilder, string $name, string $expectedClass): Definition 42 | { 43 | $definition = $this->validateContainerDefinitionExists($containerBuilder, $name); 44 | $definitionClass = $definition->getClass(); 45 | if (!\is_string($definitionClass)) { 46 | throw new NotSupportedException(\sprintf('The "%s" service class should be a string.', $name)); 47 | } 48 | 49 | if (!(new \ReflectionClass($definitionClass))->implementsInterface($expectedClass)) { 50 | throw new NotSupportedException(\sprintf('The "%s" service class should implement the "%s" interface.', $name, $expectedClass)); 51 | } 52 | 53 | return $definition; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Action/WatchContainerDefinitions/WatchContainerDefinitionsAction.php: -------------------------------------------------------------------------------- 1 | 'process', 38 | ); 39 | } 40 | 41 | /** 42 | * @param WatchContainerDefinitionsOptions $options 43 | */ 44 | public function __construct(WatchContainerDefinitionsOptions $options) 45 | { 46 | $this->options = $options; 47 | } 48 | 49 | public function process(AfterSettingsInitializationEvent $event): void 50 | { 51 | (new SettingsHelper())->override('[bootstrap_container_definition]', array( 52 | 'services' => array( 53 | 'cache.container' => array( 54 | 'class' => FileBackend::class, 55 | 'arguments' => array( 56 | $fileCache = new FileCache($this->options->getCacheFilePath(), $this->options->getFilteredResourcesCollection($event->getEnabledModules(), $event->getEnabledThemes())), 57 | ), 58 | ), 59 | ), 60 | )); 61 | 62 | if ($event->doesConfigurationChanged()) { 63 | $fileCache->invalidate(); 64 | } 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public static function getOptionsClass(): string 71 | { 72 | return WatchContainerDefinitionsOptions::class; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Action/WatchContainerDefinitions/WatchContainerDefinitionsOptions.php: -------------------------------------------------------------------------------- 1 | moduleHandler = $moduleHandler; 37 | $this->drupalKernel = $drupalKernel; 38 | } 39 | 40 | public function __invoke(CacheNotFreshEvent $event): void 41 | { 42 | foreach ($event->getFileCache()->getCurrentResourcesCollection()->all() as $resource) { 43 | if (!$resource instanceof CustomExtensionFileResource) { 44 | continue; 45 | } 46 | 47 | if (!$resource->isNew()) { 48 | continue; 49 | } 50 | 51 | $customExtension = $resource->getCustomExtension(); 52 | if (!$customExtension instanceof CustomModule) { 53 | continue; 54 | } 55 | 56 | $machineName = $customExtension->getMachineName(); 57 | $extensionFilename = \sprintf('%s.module', $machineName); 58 | if ($extensionFilename !== \substr($resource->getFilePath(), -\strlen($extensionFilename))) { 59 | continue; 60 | } 61 | 62 | $module = $this->moduleHandler->getModule($machineName); 63 | if (\is_string($module->getExtensionFilename())) { 64 | continue; 65 | } 66 | 67 | $name = $module->getName(); 68 | 69 | $this->moduleHandler->addModule($name, $module->getPath()); 70 | $this->moduleHandler->getModule($name)->load(); 71 | 72 | $this->drupalKernel->invalidateContainer(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Action/WatchModulesHooksImplementations/WatchModulesHooksImplementationsOptions.php: -------------------------------------------------------------------------------- 1 | 'process', 38 | ); 39 | } 40 | 41 | /** 42 | * @param WatchRoutingDefinitionsOptions $options 43 | */ 44 | public function __construct(WatchRoutingDefinitionsOptions $options) 45 | { 46 | $this->options = $options; 47 | } 48 | 49 | /** 50 | * @param AfterRequestPreHandleEvent $event 51 | */ 52 | public function process(AfterRequestPreHandleEvent $event): void 53 | { 54 | $resourcesFreshnessChecker = new ResourcesFreshnessChecker($this->options->getCacheFilePath(), $this->options->getFilteredResourcesCollection($event->getEnabledModules(), $event->getEnabledThemes())); 55 | if ($resourcesFreshnessChecker->isFresh()) { 56 | return; 57 | } 58 | 59 | $container = $event->getContainer(); 60 | if (!$container->has('router.builder')) { 61 | throw new NotSupportedException('The "router.builder" service should already be set in the container.'); 62 | } 63 | 64 | $routerBuilder = $container->get('router.builder'); 65 | if (!$routerBuilder instanceof RouteBuilderInterface) { 66 | throw new NotSupportedException(\sprintf('The "router.builder" service class should implement the "%s" interface.', RouteBuilderInterface::class)); 67 | } 68 | 69 | $routerBuilder->rebuild(); 70 | 71 | $resourcesFreshnessChecker->commit(); 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public static function getOptionsClass(): string 78 | { 79 | return WatchRoutingDefinitionsOptions::class; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Action/WatchRoutingDefinitions/WatchRoutingDefinitionsOptions.php: -------------------------------------------------------------------------------- 1 | implementsInterface(ActionInterface::class)) { 29 | throw new InvalidConfigurationException(\sprintf('The "%s" class should implement the "%s" interface.', $class, ActionInterface::class)); 30 | } 31 | 32 | return $refl->implementsInterface(ActionWithOptionsInterface::class) ? 33 | new ActionWithOptionsMetadata($refl, $class, $refl->getMethod('getOptionsClass')->invoke(null)) : 34 | new ActionMetadata($refl, $class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ActionMetadata/Model/ActionMetadata.php: -------------------------------------------------------------------------------- 1 | reflectionClass = $reflectionClass; 25 | $this->shortName = $shortName; 26 | } 27 | 28 | public function getReflectionClass(): \ReflectionClass 29 | { 30 | return $this->reflectionClass; 31 | } 32 | 33 | public function getShortName(): string 34 | { 35 | return $this->shortName; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ActionMetadata/Model/ActionWithOptionsMetadata.php: -------------------------------------------------------------------------------- 1 | optionsClass = $optionsClass; 25 | } 26 | 27 | public function getOptionsClass(): string 28 | { 29 | return $this->optionsClass; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Cache/Event/CacheNotFreshEvent.php: -------------------------------------------------------------------------------- 1 | fileCache = $fileCache; 32 | } 33 | 34 | /** 35 | * @return FileCache 36 | */ 37 | public function getFileCache(): FileCache 38 | { 39 | return $this->fileCache; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Cache/Event/FileBackendEvents.php: -------------------------------------------------------------------------------- 1 | setName(self::NAME) 40 | ->setAliases(self::ALIASES); 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | protected function execute(InputInterface $input, OutputInterface $output): ?int 47 | { 48 | return (new ManageConfigurationHelper($this->getComposer(), $this->getIO()))->toggleOriginalDrupalKernelSubstitution(false) ? 0 : 1; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Composer/Command/DumpReferenceConfigurationFileCommand.php: -------------------------------------------------------------------------------- 1 | setName(self::NAME); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | protected function execute(InputInterface $input, OutputInterface $output): ?int 40 | { 41 | return (new ManageConfigurationHelper($this->getComposer(), $this->getIO()))->dumpReferenceConfigurationFile() ? 0 : 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Composer/Command/EnableOriginalDrupalKernelSubstitutionCommand.php: -------------------------------------------------------------------------------- 1 | setName(self::NAME) 40 | ->setAliases(self::ALIASES); 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | protected function execute(InputInterface $input, OutputInterface $output): ?int 47 | { 48 | return (new ManageConfigurationHelper($this->getComposer(), $this->getIO()))->toggleOriginalDrupalKernelSubstitution(true) ? 0 : 1; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Composer/Plugin/RegisterCommandsPlugin.php: -------------------------------------------------------------------------------- 1 | CommandProvider::class, 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Configuration/AbstractConfiguration.php: -------------------------------------------------------------------------------- 1 | getArrayNodeDefinition($treeBuilder = new TreeBuilder()); 27 | 28 | return $treeBuilder; 29 | } 30 | 31 | abstract public function getArrayNodeDefinition(TreeBuilder $treeBuilder); 32 | } 33 | -------------------------------------------------------------------------------- /src/Configuration/ActionsConfiguration.php: -------------------------------------------------------------------------------- 1 | actionsMetadata = $actionsMetadata; 40 | $this->defaultsConfiguration = $defaultsConfiguration; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function getArrayNodeDefinition(TreeBuilder $treeBuilder): ArrayNodeDefinition 47 | { 48 | /** @var ArrayNodeDefinition $rootNode */ 49 | $rootNode = $treeBuilder->root(self::ROOT_KEY); 50 | $nodeBuilder = $rootNode 51 | ->addDefaultsIfNotSet() 52 | ->children(); 53 | 54 | foreach ($this->actionsMetadata as $actionMetadata) { 55 | $childrenNodeBuilder = $nodeBuilder 56 | ->arrayNode($actionMetadata->getShortName()) 57 | ->canBeDisabled() 58 | ->children(); 59 | 60 | if ($actionMetadata instanceof ActionWithOptionsMetadata) { 61 | $actionMetadata->getOptionsClass()::addConfiguration($childrenNodeBuilder, $this->defaultsConfiguration); 62 | } 63 | 64 | $childrenNodeBuilder 65 | ->end(); 66 | } 67 | 68 | $rootNode 69 | ->end(); 70 | 71 | return $rootNode; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Configuration/CacheDirectoryPathConfigurationTrait.php: -------------------------------------------------------------------------------- 1 | scalarNode('cache_directory_path') 26 | ->cannotBeEmpty() 27 | ->defaultValue($defaultCacheDirectoryPath) 28 | ->end(); 29 | } 30 | 31 | private static function addCacheDirectoryPathConfigurationNodeFromDefaultsConfiguration(NodeBuilder $nodeBuilder, DefaultsConfigurationModel $defaultsConfiguration): NodeBuilder 32 | { 33 | return self::addCacheDirectoryPathConfigurationNode($nodeBuilder, $defaultsConfiguration->getCacheDirectoryPath()); 34 | } 35 | 36 | private static function getConfiguredCacheDirectoryPath(ActionConfiguration $actionConfiguration): string 37 | { 38 | $processedConfiguration = $actionConfiguration->getProcessedConfiguration(); 39 | 40 | return $processedConfiguration['cache_directory_path']; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Configuration/CharsetConfigurationTrait.php: -------------------------------------------------------------------------------- 1 | scalarNode('charset') 26 | ->defaultValue($defaultCharset) 27 | ->end(); 28 | } 29 | 30 | private static function addCharsetConfigurationNodeFromDefaultsConfiguration(NodeBuilder $nodeBuilder, DefaultsConfigurationModel $defaultsConfiguration): NodeBuilder 31 | { 32 | return self::addCharsetConfigurationNode($nodeBuilder, $defaultsConfiguration->getCharset()); 33 | } 34 | 35 | private static function getConfiguredCharset(ActionConfiguration $actionConfiguration): ?string 36 | { 37 | $processedConfiguration = $actionConfiguration->getProcessedConfiguration(); 38 | 39 | return $processedConfiguration['charset']; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Configuration/DefaultsConfiguration.php: -------------------------------------------------------------------------------- 1 | root(self::ROOT_KEY); 38 | 39 | $nodeBuilder = $rootNode 40 | ->info('The defaults values are common values that are reused by different actions.') 41 | ->addDefaultsIfNotSet() 42 | ->children(); 43 | 44 | self::addCacheDirectoryPathConfigurationNode($nodeBuilder, 'cache'); 45 | self::addLoggerConfigurationNode($nodeBuilder, 'drupal-debug', 'logs/drupal-debug.log'); 46 | self::addCharsetConfigurationNode($nodeBuilder, null); 47 | self::addFileLinkFormatConfigurationNode($nodeBuilder, null); 48 | 49 | $nodeBuilder->end(); 50 | 51 | return $rootNode; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Configuration/FileLinkFormatConfigurationTrait.php: -------------------------------------------------------------------------------- 1 | scalarNode('file_link_format') 26 | ->defaultValue($defaultFileLinkFormat) 27 | ->end(); 28 | } 29 | 30 | private static function addFileLinkFormatConfigurationNodeFromDefaultsConfiguration(NodeBuilder $nodeBuilder, DefaultsConfigurationModel $defaultsConfiguration): NodeBuilder 31 | { 32 | return self::addFileLinkFormatConfigurationNode($nodeBuilder, $defaultsConfiguration->getFileLinkFormat()); 33 | } 34 | 35 | private static function getConfiguredFileLinkFormat(ActionConfiguration $actionConfiguration): ?string 36 | { 37 | $processedConfiguration = $actionConfiguration->getProcessedConfiguration(); 38 | 39 | return $processedConfiguration['file_link_format']; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Configuration/LoggerConfigurationTrait.php: -------------------------------------------------------------------------------- 1 | arrayNode('logger') 28 | ->canBeDisabled() 29 | ->children() 30 | ->scalarNode('channel') 31 | ->cannotBeEmpty() 32 | ->defaultValue($defaultChannel) 33 | ->end() 34 | ->scalarNode('file_path') 35 | ->cannotBeEmpty() 36 | ->defaultValue($defaultFilePath) 37 | ->end() 38 | ->end() 39 | ->end(); 40 | } 41 | 42 | private static function addLoggerConfigurationNodeFromDefaultsConfiguration(NodeBuilder $nodeBuilder, DefaultsConfigurationModel $defaultsConfiguration): NodeBuilder 43 | { 44 | $defaultLoggerConfiguration = $defaultsConfiguration->getLogger(); 45 | 46 | return self::addLoggerConfigurationNode($nodeBuilder, $defaultLoggerConfiguration['channel'], $defaultLoggerConfiguration['file_path']); 47 | } 48 | 49 | private static function getConfiguredLogger(ActionConfiguration $actionConfiguration): ?Logger 50 | { 51 | $processedConfiguration = $actionConfiguration->getProcessedConfiguration(); 52 | if (!$processedConfiguration['logger']['enabled']) { 53 | return null; 54 | } 55 | 56 | return LoggerStack::getInstance($processedConfiguration['logger']['channel'], $processedConfiguration['logger']['file_path']); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Configuration/Model/AbstractConfiguration.php: -------------------------------------------------------------------------------- 1 | processedConfiguration = $processedConfiguration; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Configuration/Model/ActionConfiguration.php: -------------------------------------------------------------------------------- 1 | enabled = $processedConfiguration['enabled']; 29 | 30 | unset($processedConfiguration['enabled']); 31 | 32 | parent::__construct($processedConfiguration); 33 | } 34 | 35 | public function isEnabled(): bool 36 | { 37 | return $this->enabled; 38 | } 39 | 40 | public function getProcessedConfiguration(): array 41 | { 42 | return $this->processedConfiguration; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function serialize(): ?string 49 | { 50 | return \serialize(array( 51 | $this->processedConfiguration, 52 | $this->enabled, 53 | )); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function unserialize($serialized): void 60 | { 61 | list($this->processedConfiguration, $this->enabled) = \unserialize($serialized); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Configuration/Model/DefaultsConfiguration.php: -------------------------------------------------------------------------------- 1 | processedConfiguration['cache_directory_path']; 24 | } 25 | 26 | public function getLogger(): array 27 | { 28 | return $this->processedConfiguration['logger']; 29 | } 30 | 31 | /** 32 | * @return string|null 33 | */ 34 | public function getCharset(): ?string 35 | { 36 | return $this->processedConfiguration['charset']; 37 | } 38 | 39 | /** 40 | * @return string|null 41 | */ 42 | public function getFileLinkFormat(): ?string 43 | { 44 | return $this->processedConfiguration['file_link_format']; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function serialize(): ?string 51 | { 52 | return \serialize(array( 53 | $this->processedConfiguration, 54 | )); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function unserialize($serialized): void 61 | { 62 | list($this->processedConfiguration) = \unserialize($serialized); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Configuration/Model/SubstituteOriginalDrupalKernelConfiguration.php: -------------------------------------------------------------------------------- 1 | classLoader = null; 33 | } 34 | 35 | /** 36 | * @return bool 37 | */ 38 | public function isEnabled(): bool 39 | { 40 | return $this->processedConfiguration['enabled']; 41 | } 42 | 43 | /** 44 | * @return ClassLoader 45 | */ 46 | public function getClassLoader(): ClassLoader 47 | { 48 | if (!$this->classLoader instanceof ClassLoader) { 49 | if (!$this->isEnabled()) { 50 | throw new \LogicException('The class loader getter should not be called if the original DrupalKernel substitution is disabled.'); 51 | } 52 | 53 | $classLoader = require $this->processedConfiguration['composer_autoload_file_path']; 54 | if (!$classLoader instanceof ClassLoader) { 55 | throw new \RuntimeException(\sprintf('The composer autoload.php file did not return a "%s" instance.', ClassLoader::class)); 56 | } 57 | 58 | $this->classLoader = $classLoader; 59 | } 60 | 61 | return $this->classLoader; 62 | } 63 | 64 | /** 65 | * @return string 66 | */ 67 | public function getCacheDirectoryPath(): string 68 | { 69 | if (!$this->isEnabled()) { 70 | throw new \LogicException('The cache directory getter should not be called if the original DrupalKernel substitution is disabled.'); 71 | } 72 | 73 | return $this->processedConfiguration['cache_directory_path']; 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | public function serialize(): ?string 80 | { 81 | return \serialize(array( 82 | $this->processedConfiguration, 83 | null, 84 | )); 85 | } 86 | 87 | /** 88 | * {@inheritdoc} 89 | */ 90 | public function unserialize($serialized): void 91 | { 92 | list($this->processedConfiguration, $this->classLoader) = \unserialize($serialized); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Configuration/SubstituteOriginalDrupalKernelConfiguration.php: -------------------------------------------------------------------------------- 1 | defaultsConfiguration = $defaultsConfiguration; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function getArrayNodeDefinition(TreeBuilder $treeBuilder): ArrayNodeDefinition 38 | { 39 | /** @var ArrayNodeDefinition $rootNode */ 40 | $rootNode = $treeBuilder->root(self::ROOT_KEY); 41 | 42 | $rootNode 43 | ->info("It is recommended to disable the original DrupalKernel substitution to run your tests.\nTo programmatically toggle it, use the two dedicated composer commands.") 44 | ->canBeDisabled() 45 | ->children() 46 | ->scalarNode('composer_autoload_file_path') 47 | ->cannotBeEmpty() 48 | ->defaultValue('vendor/autoload.php') 49 | ->end() 50 | ->scalarNode('cache_directory_path') 51 | ->info('If not specified, it fall backs to the default cache directory path.') 52 | ->defaultValue($this->defaultsConfiguration->getCacheDirectoryPath()) 53 | ->end() 54 | ->end(); 55 | 56 | return $rootNode; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Drupal/Core/OriginalDrupalKernel.php: -------------------------------------------------------------------------------- 1 | setAccessible(true); 37 | 38 | $this->blacklist = $refl->getValue($drupalRecursiveExtensionFilterIterator); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function accept(): bool 45 | { 46 | $current = $this->current(); 47 | if (null === $current) { 48 | return false; 49 | } 50 | 51 | $filename = $current->getFilename(); 52 | if ('.' === $filename[0]) { 53 | return false; 54 | } 55 | 56 | if (!$this->isDir()) { 57 | return '.info.yml' === \substr($filename, -9); 58 | } 59 | 60 | if ('config' === $filename) { 61 | return 'modules/config' === \substr($current->getPathname(), -14); 62 | } 63 | 64 | return !\in_array($filename, $this->blacklist, true); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Extension/Model/AbstractCustomExtension.php: -------------------------------------------------------------------------------- 1 | rootPath = $rootPath; 35 | $this->machineName = $machineName; 36 | } 37 | 38 | /** 39 | * @return string 40 | */ 41 | public function getRootPath(): string 42 | { 43 | return $this->rootPath; 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getMachineName(): string 50 | { 51 | return $this->machineName; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function serialize(): ?string 58 | { 59 | return \serialize(array( 60 | $this->rootPath, 61 | $this->machineName, 62 | )); 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function unserialize($serialized): void 69 | { 70 | list($this->rootPath, $this->machineName) = \unserialize($serialized); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Extension/Model/CustomExtensionInterface.php: -------------------------------------------------------------------------------- 1 | camelCaseMachineName = ContainerBuilder::camelize($machineName); 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getCamelCaseMachineName(): string 40 | { 41 | return $this->camelCaseMachineName; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function serialize(): ?string 48 | { 49 | return \serialize(array( 50 | $this->rootPath, 51 | $this->machineName, 52 | $this->camelCaseMachineName, 53 | )); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function unserialize($serialized): void 60 | { 61 | list($this->rootPath, $this->machineName, $this->camelCaseMachineName) = \unserialize($serialized); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Extension/Model/CustomTheme.php: -------------------------------------------------------------------------------- 1 | storage; 31 | })->bindTo($settings, $settings)(); 32 | 33 | PropertyAccess::createPropertyAccessor()->setValue($storage, $propertyPath, $value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Kernel/Event/AbstractBaseEvent.php: -------------------------------------------------------------------------------- 1 | configurationChanged = $configurationChanged; 25 | } 26 | 27 | public function doesConfigurationChanged(): bool 28 | { 29 | return $this->configurationChanged; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Kernel/Event/AbstractWithContainerAndEnabledExtensionsEvent.php: -------------------------------------------------------------------------------- 1 | container = $container; 35 | } 36 | 37 | /** 38 | * @return ContainerInterface 39 | */ 40 | public function getContainer(): ContainerInterface 41 | { 42 | return $this->container; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Kernel/Event/AbstractWithEnabledExtensionsEvent.php: -------------------------------------------------------------------------------- 1 | enabledModules = $enabledModules; 37 | $this->enabledThemes = $enabledThemes; 38 | } 39 | 40 | /** 41 | * @return array 42 | */ 43 | public function getEnabledModules(): array 44 | { 45 | return $this->enabledModules; 46 | } 47 | 48 | /** 49 | * @return array 50 | */ 51 | public function getEnabledThemes(): array 52 | { 53 | return $this->enabledThemes; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Kernel/Event/AfterAttachSyntheticEvent.php: -------------------------------------------------------------------------------- 1 | optionsStack = array(); 29 | 30 | foreach ($options as $option) { 31 | $this->set($option); 32 | } 33 | } 34 | 35 | /** 36 | * @param OptionsInterface[] $options 37 | * 38 | * @return OptionsStack 39 | */ 40 | public static function create(array $options = array()): self 41 | { 42 | return new self($options); 43 | } 44 | 45 | /** 46 | * @param string $class 47 | * 48 | * @return OptionsInterface|null 49 | */ 50 | public function get(string $class): ?OptionsInterface 51 | { 52 | if (!isset($this->optionsStack[$class])) { 53 | return null; 54 | } 55 | 56 | return $this->optionsStack[$class]; 57 | } 58 | 59 | /** 60 | * @param OptionsInterface $options 61 | */ 62 | public function set(OptionsInterface $options): void 63 | { 64 | $this->optionsStack[\get_class($options)] = $options; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Resource/Model/CustomExtensionFileResource.php: -------------------------------------------------------------------------------- 1 | filePath = $filePath; 43 | $this->customExtension = $customExtension; 44 | 45 | $this->existed = \is_file($filePath); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function __toString(): string 52 | { 53 | return $this->filePath; 54 | } 55 | 56 | /** 57 | * @return string 58 | */ 59 | public function getFilePath(): string 60 | { 61 | return $this->filePath; 62 | } 63 | 64 | /** 65 | * @return CustomExtensionInterface 66 | */ 67 | public function getCustomExtension(): CustomExtensionInterface 68 | { 69 | return $this->customExtension; 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function isFresh($timestamp): bool 76 | { 77 | if (!\is_file($this->filePath)) { 78 | return !$this->existed; 79 | } elseif (!$this->existed) { 80 | return false; 81 | } 82 | 83 | return false !== ($filemtime = @\filemtime($this->filePath)) && $filemtime <= $timestamp; 84 | } 85 | 86 | /** 87 | * @return bool 88 | */ 89 | public function isNew(): bool 90 | { 91 | return false === $this->existed && \is_file($this->filePath); 92 | } 93 | 94 | /** 95 | * {@inheritdoc} 96 | */ 97 | public function serialize(): ?string 98 | { 99 | return \serialize(array( 100 | $this->filePath, 101 | $this->customExtension, 102 | $this->existed, 103 | )); 104 | } 105 | 106 | /** 107 | * {@inheritdoc} 108 | */ 109 | public function unserialize($serialized): void 110 | { 111 | list($this->filePath, $this->customExtension, $this->existed) = \unserialize($serialized); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Resource/Model/ResourcesCollection.php: -------------------------------------------------------------------------------- 1 | resources = $resources; 31 | } 32 | 33 | /** 34 | * @return SelfCheckingResourceInterface[] 35 | */ 36 | public function all(): array 37 | { 38 | return $this->resources; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function count(): int 45 | { 46 | return \count($this->resources); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function serialize(): ?string 53 | { 54 | return \serialize($this->resources); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function unserialize($serialized): void 61 | { 62 | $this->resources = \unserialize($serialized); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/initialize.php: -------------------------------------------------------------------------------- 1 | getSubstituteOriginalDrupalKernelConfiguration(); 23 | if ($substituteOriginalDrupalKernelConfiguration->isEnabled()) { 24 | OriginalDrupalKernelHelper::substitute($substituteOriginalDrupalKernelConfiguration->getClassLoader(), $substituteOriginalDrupalKernelConfiguration->getCacheDirectoryPath()); 25 | } 26 | } 27 | } 28 | 29 | if (\defined('PHPUNIT_COMPOSER_INSTALL') || 30 | (false !== \getenv('DRUPAL_DEBUG_TESTS_ARE_RUNNING') && false === \getenv('DRUPAL_DEBUG_TESTS_FORCE_INITIALIZATION'))) { 31 | return; 32 | } 33 | 34 | \_drupal_debug_initialize(); 35 | -------------------------------------------------------------------------------- /tests/Integration/AbstractTestCase.php: -------------------------------------------------------------------------------- 1 | clearCache(); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | protected function tearDown(): void 60 | { 61 | $this->clearCache(); 62 | } 63 | 64 | protected function useDebugKernel(): void 65 | { 66 | $_ENV['DRUPAL_DEBUG_TESTS_FORCE_INITIALIZATION'] = '1'; 67 | $_ENV[ConfigurationManager::CONFIGURATION_CACHE_DIRECTORY_ENVIRONMENT_VARIABLE_NAME] = self::CACHE_DIRECTORY_PATH; 68 | $_ENV[ConfigurationManager::CONFIGURATION_FILE_PATH_ENVIRONMENT_VARIABLE_NAME] = self::CONFIGURATION_FILE_PATH; 69 | } 70 | 71 | protected function clearCache(): void 72 | { 73 | (new Filesystem())->remove(Finder::create()->in(self::CACHE_DIRECTORY_PATH)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableCSSAggregation/DisableCSSAggregationActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(1, $this->countStylesheetLinks($client)); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 33 | { 34 | $client->request('GET', '/'); 35 | 36 | $this->assertGreaterThan(10, $this->countStylesheetLinks($client)); 37 | } 38 | 39 | /** 40 | * @return int 41 | */ 42 | private function countStylesheetLinks(Client $client): int 43 | { 44 | return \iterator_count($client->request('GET', '/')->filterXPath('descendant-or-self::link[@rel="stylesheet"]')); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableDynamicPageCache/fixtures/ControllerTemplate.php: -------------------------------------------------------------------------------- 1 | '%markup%', 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableDynamicPageCache/fixtures/modules/hit_dynamic_page_cache/hit_dynamic_page_cache.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisableDynamicPageCache::hit_dynamic_page_cache 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableDynamicPageCache/fixtures/modules/hit_dynamic_page_cache/hit_dynamic_page_cache.routing.yml: -------------------------------------------------------------------------------- 1 | hit_dynamic_page_cache.foo: 2 | path: '/foo' 3 | defaults: 4 | _controller: '\Drupal\hit_dynamic_page_cache\Controller\__FooController::action' 5 | requirements: 6 | _access: 'TRUE' 7 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableDynamicPageCache/fixtures/modules/hit_dynamic_page_cache/src/Controller/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Integration/Action/DisableDynamicPageCache/fixtures/modules/hit_dynamic_page_cache/src/Controller/.gitkeep -------------------------------------------------------------------------------- /tests/Integration/Action/DisableInternalPageCache/fixtures/ControllerTemplate.php: -------------------------------------------------------------------------------- 1 | '%markup%', 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableInternalPageCache/fixtures/modules/hit_page_cache/hit_page_cache.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisableInternalPageCache::hit_page_cache 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableInternalPageCache/fixtures/modules/hit_page_cache/hit_page_cache.routing.yml: -------------------------------------------------------------------------------- 1 | hit_page_cache.foo: 2 | path: '/foo' 3 | defaults: 4 | _controller: '\Drupal\hit_page_cache\Controller\__FooController::action' 5 | requirements: 6 | _access: 'TRUE' 7 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableInternalPageCache/fixtures/modules/hit_page_cache/src/Controller/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Integration/Action/DisableInternalPageCache/fixtures/modules/hit_page_cache/src/Controller/.gitkeep -------------------------------------------------------------------------------- /tests/Integration/Action/DisableJSAggregation/DisableJSAggregationActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(1, $this->countScripts($client)); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 33 | { 34 | $this->assertSame(2, $this->countScripts($client)); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | private function countScripts(Client $client): int 41 | { 42 | return \iterator_count($client->request('GET', '/')->filterXPath('descendant-or-self::script')); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableJSAggregation/fixtures/modules/add_js_scripts/add_js_scripts.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisableJSAggregation::add_js_scripts 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableJSAggregation/fixtures/modules/add_js_scripts/add_js_scripts.libraries.yml: -------------------------------------------------------------------------------- 1 | foo: 2 | js: 3 | assets/js/1.js: {} 4 | assets/js/2.js: {} 5 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableJSAggregation/fixtures/modules/add_js_scripts/add_js_scripts.module: -------------------------------------------------------------------------------- 1 | '%markup%', 25 | '#cache' => array( 26 | 'keys' => array( 27 | 'foo', 28 | 'bar', 29 | ), 30 | 'max-age' => Cache::PERMANENT, 31 | ), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableRenderCache/fixtures/modules/hit_render_cache/hit_render_cache.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisableRenderCache::hit_render_cache 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableRenderCache/fixtures/modules/hit_render_cache/hit_render_cache.routing.yml: -------------------------------------------------------------------------------- 1 | hit_render_cache.foo: 2 | path: '/foo' 3 | defaults: 4 | _controller: '\Drupal\hit_render_cache\Controller\__FooController::action' 5 | requirements: 6 | _access: 'TRUE' 7 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableRenderCache/fixtures/modules/hit_render_cache/src/Controller/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Integration/Action/DisableRenderCache/fixtures/modules/hit_render_cache/src/Controller/.gitkeep -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/DisableTwigCacheActionTest.php: -------------------------------------------------------------------------------- 1 | deletePartialFile(true); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | protected function tearDown(): void 43 | { 44 | parent::tearDown(); 45 | 46 | $this->deletePartialFile(false); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | protected function doTestInitialBehaviorWithDrupalKernel(Client $client): void 53 | { 54 | $results = $this->executeScenario($client); 55 | 56 | $this->assertContains('I love to eat apples!', $results[0]); 57 | 58 | $this->assertContains('I love to eat apples!', $results[1]); 59 | $this->assertNotContains('I prefer pears.', $results[1]); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 66 | { 67 | $results = $this->executeScenario($client); 68 | 69 | $this->assertContains('I love to eat apples!', $results[0]); 70 | 71 | $this->assertContains('I prefer pears.', $results[1]); 72 | $this->assertNotContains('I love to eat apples!', $results[1]); 73 | } 74 | 75 | private function executeScenario(Client $client): array 76 | { 77 | $results = array(); 78 | 79 | foreach (array( 80 | '/bar' => 'I love to eat apples!', 81 | '/ccc' => 'I prefer pears.', 82 | ) as $uri => $content) { 83 | self::writeFile(self::MODULE_PARTIAL_FILE_PATH, $content); 84 | 85 | $results[] = $client->request('GET', $uri)->text(); 86 | } 87 | 88 | return $results; 89 | } 90 | 91 | private function deletePartialFile(bool $mandatory): void 92 | { 93 | self::deleteFile(self::MODULE_PARTIAL_FILE_PATH, $mandatory); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/src/Controller/FooController.php: -------------------------------------------------------------------------------- 1 | '__partial', 24 | ); 25 | } 26 | 27 | public function ccc(): array 28 | { 29 | return array( 30 | '#theme' => '__partial', 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/templates/.gitkeep -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/use_twig_template.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisableTwigCache::use_twig_template 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/use_twig_template.module: -------------------------------------------------------------------------------- 1 | [ 7 | 'variables' => [], 8 | ], 9 | ]; 10 | } 11 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisableTwigCache/fixtures/modules/use_twig_template/use_twig_template.routing.yml: -------------------------------------------------------------------------------- 1 | use_twig_template.bar: 2 | path: '/bar' 3 | defaults: 4 | _controller: '\Drupal\use_twig_template\Controller\FooController::bar' 5 | requirements: 6 | _access: 'TRUE' 7 | 8 | use_twig_template.ccc: 9 | path: '/ccc' 10 | defaults: 11 | _controller: '\Drupal\use_twig_template\Controller\FooController::ccc' 12 | requirements: 13 | _access: 'TRUE' 14 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayDumpLocation/DisplayDumpLocationActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame("\"fcy\"\n", $this->getDumpText($client)); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 33 | { 34 | $this->assertThat($this->getDumpText($client), $this->logicalOr( 35 | $this->identicalTo("add_dump_die.module on line 5:\n\"fcy\"\n"), 36 | $this->identicalTo("\"fcy\"\n") 37 | )); 38 | } 39 | 40 | /** 41 | * @param Client $client 42 | * 43 | * @return string 44 | */ 45 | private function getDumpText(Client $client): string 46 | { 47 | return $client->request('GET', '/')->filterXPath('descendant-or-self::pre[@class="sf-dump"]')->text(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayDumpLocation/fixtures/modules/add_dump_die/add_dump_die.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisplayDumpLocation::add_dump_die 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayDumpLocation/fixtures/modules/add_dump_die/add_dump_die.module: -------------------------------------------------------------------------------- 1 | request('GET', '/'); 28 | 29 | /** @var Response $response */ 30 | $response = $client->getResponse(); 31 | $this->assertSame('The website encountered an unexpected error. Please try again later.', $response->getContent()); 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 38 | { 39 | $text = $client->request('GET', '/')->text(); 40 | 41 | $this->assertContains('This is an useless exception message.', $text); 42 | $this->assertThat($text, $this->logicalOr( 43 | $this->stringContains('in throw_uncaught_exception.module line 5', false), 44 | $this->stringContains('in throw_uncaught_exception.module (line 5)', false) 45 | )); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayPrettyExceptions/fixtures/modules/throw_uncaught_exception/throw_uncaught_exception.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisplayPrettyExceptions::throw_uncaught_exception 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayPrettyExceptions/fixtures/modules/throw_uncaught_exception/throw_uncaught_exception.module: -------------------------------------------------------------------------------- 1 | request('GET', '/'); 74 | 75 | /** @var Response $response */ 76 | $response = $client->getResponse(); 77 | $this->assertSame('The website encountered an unexpected error. Please try again later.
', $response->getContent()); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 84 | { 85 | $text = $client->request('GET', '/')->text(); 86 | $this->assertContains('My custom exception message is great!', $text); 87 | $this->assertThat($text, $this->logicalOr( 88 | $this->stringContains('in throw_uncaught_exception.module line 5', false), 89 | $this->stringContains('in throw_uncaught_exception.module (line 5)', false) 90 | )); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayPrettyExceptionsASAP/fixtures/index.php: -------------------------------------------------------------------------------- 1 | handle(Request::createFromGlobals(), DrupalKernel::MASTER_REQUEST, false); 20 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayPrettyExceptionsASAP/fixtures/modules/throw_uncaught_exception/throw_uncaught_exception.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: DisplayPrettyExceptionASAP::throw_uncaught_exception 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/DisplayPrettyExceptionsASAP/fixtures/modules/throw_uncaught_exception/throw_uncaught_exception.module: -------------------------------------------------------------------------------- 1 | assertNotContains('', $this->executeScenario($client)); 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 34 | { 35 | $this->assertContains('', $this->executeScenario($client)); 36 | } 37 | 38 | private function executeScenario(Client $client): string 39 | { 40 | $client->request('GET', '/'); 41 | 42 | /** @var Response $response */ 43 | $response = $client->getResponse(); 44 | 45 | return $response->getContent(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Integration/Action/ThrowErrorsAsExceptions/ThrowErrorsAsExceptionsActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(200, $this->executeScenario($client)); 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | protected function doTestTargetedBehaviorWithDebugKernel(Client $client): void 34 | { 35 | $this->assertSame(500, $this->executeScenario($client)); 36 | } 37 | 38 | private function executeScenario(Client $client): int 39 | { 40 | $client->request('GET', '/'); 41 | 42 | /** @var Response $response */ 43 | $response = $client->getResponse(); 44 | 45 | return $response->getStatus(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Integration/Action/ThrowErrorsAsExceptions/fixtures/modules/trigger_error/trigger_error.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: ThrowErrorsAsException::trigger_error 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/ThrowErrorsAsExceptions/fixtures/modules/trigger_error/trigger_error.module: -------------------------------------------------------------------------------- 1 | hasDefinition('use_custom_service.service.foo') ? 27 | $container->getDefinition('use_custom_service.service.foo')->replaceArgument(0, '%message%') : 28 | $container->setParameter('use_custom_service.parameter.bar', '%message%'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchContainerDefinitions/fixtures/modules/use_custom_service/src/Service/FooService.php: -------------------------------------------------------------------------------- 1 | message = $message; 29 | } 30 | 31 | /** 32 | * @return string 33 | */ 34 | public function getMessage(): string 35 | { 36 | return $this->message; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchContainerDefinitions/fixtures/modules/use_custom_service/use_custom_service.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: WatchContainerDefinitions::use_custom_service 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchContainerDefinitions/fixtures/modules/use_custom_service/use_custom_service.module: -------------------------------------------------------------------------------- 1 | has('use_custom_service.service.foo')) { 13 | $message = $container->get('use_custom_service.service.foo')->getMessage(); 14 | } else { 15 | if ($container->hasParameter('use_custom_service.parameter.bar')) { 16 | $message = $container->getParameter('use_custom_service.parameter.bar'); 17 | } else { 18 | $message = 'No service message!!!'; 19 | } 20 | } 21 | 22 | $page_bottom[] = array( 23 | '#markup' => sprintf('Drupal debug ==> %s', $message), 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchContainerDefinitions/fixtures/services_template.yml: -------------------------------------------------------------------------------- 1 | services: 2 | use_custom_service.service.foo: 3 | class: Drupal\use_custom_service\Service\FooService 4 | arguments: 5 | - "%message%" 6 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchModulesHooksImplementations/fixtures/implement_hook.module: -------------------------------------------------------------------------------- 1 | 'Find a subtle way out', 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchModulesHooksImplementations/fixtures/module_hook_to_add.php: -------------------------------------------------------------------------------- 1 | 2 | function implement_hook_page_top(&$page_top): void 3 | { 4 | $page_top[] = array( 5 | '#markup' => "I've been trying to stay out", 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchModulesHooksImplementations/fixtures/modules/implement_hook/implement_hook.info.yml: -------------------------------------------------------------------------------- 1 | type: module 2 | core: 8.x 3 | name: WatchModulesHooksImplementations::implement_hook 4 | -------------------------------------------------------------------------------- /tests/Integration/Action/WatchRoutingDefinitions/fixtures/modules/use_custom_route/src/Controller/FooController.php: -------------------------------------------------------------------------------- 1 | useDebugKernel(); 24 | 25 | // cf DrupalFinder\DrupalFinder::isValidRoot() 26 | $_ENV['COMPOSER'] = 'index.php'; 27 | 28 | $this->assertSame(0, (new Process(\sprintf('%s/drush/drush/drush cr', self::VENDOR_DIRECTORY_PATH), self::DRUPAL_DIRECTORY_PATH))->run()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Integration/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Integration/cache/.gitkeep -------------------------------------------------------------------------------- /tests/Integration/fixtures/drupal-debug.yml: -------------------------------------------------------------------------------- 1 | drupal-debug: 2 | defaults: 3 | cache_directory_path: ../cache 4 | logger: 5 | file_path: ../cache/logs/drupal-debug.log 6 | substitute_original_drupal_kernel: 7 | composer_autoload_file_path: ../../../vendor/autoload.php 8 | -------------------------------------------------------------------------------- /tests/Traits/FileHelperTrait.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 24 | 'ekino.drupal.debug.debug_kernel.after_settings_initialization' => 'process', 25 | ), DisableCSSAggregationAction::getSubscribedEvents()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisableJSAggregation/DisableJSAggregationActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 24 | 'ekino.drupal.debug.debug_kernel.after_settings_initialization' => 'process', 25 | ), DisableJSAggregationAction::getSubscribedEvents()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisplayDumpLocation/DisplayDumpLocationActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 26 | 'ekino.drupal.debug.debug_kernel.on_kernel_instantiation' => 'process', 27 | ), DisplayDumpLocationAction::getSubscribedEvents()); 28 | } 29 | 30 | public function testProcess(): void 31 | { 32 | VarDumper::setHandler(null); 33 | 34 | (new DisplayDumpLocationAction())->process(); 35 | 36 | if (!\class_exists(SourceContextProvider::class)) { 37 | $this->assertAttributeInternalType('null', 'handler', VarDumper::class); 38 | } else { 39 | $this->assertAttributeInstanceOf(\Closure::class, 'handler', VarDumper::class); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisplayPrettyExceptions/DisplayPrettyExceptionsOptionsTest.php: -------------------------------------------------------------------------------- 1 | assertSame($charset, $displayPrettyExceptionsOptions->getCharset()); 30 | } 31 | 32 | public function getCharsetProvider(): array 33 | { 34 | return array( 35 | array(null), 36 | array('utf-8'), 37 | ); 38 | } 39 | 40 | /** 41 | * @dataProvider getFileLinkFormatProvider 42 | */ 43 | public function testGetFileLinkFormat(?string $fileLinkFormat): void 44 | { 45 | $displayPrettyExceptionsOptions = new DisplayPrettyExceptionsOptions(null, $fileLinkFormat, null); 46 | 47 | $this->assertSame($fileLinkFormat, $displayPrettyExceptionsOptions->getFileLinkFormat()); 48 | } 49 | 50 | public function getFileLinkFormatProvider(): array 51 | { 52 | return array( 53 | array(null), 54 | array('myide://open?url=file://%%f&line=%%l'), 55 | ); 56 | } 57 | 58 | /** 59 | * @dataProvider getLoggerProvider 60 | */ 61 | public function testGetLogger(?LoggerInterface $logger): void 62 | { 63 | $displayPrettyExceptionsOptions = new DisplayPrettyExceptionsOptions(null, null, $logger); 64 | 65 | $this->assertSame($logger, $displayPrettyExceptionsOptions->getLogger()); 66 | } 67 | 68 | public function getLoggerProvider(): array 69 | { 70 | return array( 71 | array(null), 72 | array($this->createMock(LoggerInterface::class)), 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisplayPrettyExceptions/ExceptionControllerTest.php: -------------------------------------------------------------------------------- 1 | createMock(ExceptionHandler::class); 29 | $exceptionHandler 30 | ->expects($this->atLeastOnce()) 31 | ->method('getHtml') 32 | ->with($exception) 33 | ->willReturn('foo'); 34 | 35 | $this->assertEquals(new Response('foo', 503), (new ExceptionController($exceptionHandler))->__invoke($exception)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisplayPrettyExceptionsASAP/DisplayPrettyExceptionsASAPActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 25 | 'ekino.drupal.debug.debug_kernel.after_environment_boot' => 'process', 26 | ), DisplayPrettyExceptionsASAPAction::getSubscribedEvents()); 27 | } 28 | 29 | public function testProcess(): void 30 | { 31 | \set_exception_handler(null); 32 | 33 | (new DisplayPrettyExceptionsASAPAction($this->createMock(DisplayPrettyExceptionsASAPOptions::class)))->process(); 34 | 35 | $this->assertInstanceOf(\Closure::class, \set_exception_handler(null)); 36 | } 37 | 38 | public function testGetOptionsClass(): void 39 | { 40 | $this->assertSame('Ekino\Drupal\Debug\Action\DisplayPrettyExceptionsASAP\DisplayPrettyExceptionsASAPOptions', DisplayPrettyExceptionsASAPAction::getOptionsClass()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/DisplayPrettyExceptionsASAP/DisplayPrettyExceptionsASAPOptionsTest.php: -------------------------------------------------------------------------------- 1 | assertSame($charset, $displayPrettyExceptionsOptions->getCharset()); 29 | } 30 | 31 | public function getCharsetProvider(): array 32 | { 33 | return array( 34 | array(null), 35 | array('utf-8'), 36 | ); 37 | } 38 | 39 | /** 40 | * @dataProvider getFileLinkFormatProvider 41 | */ 42 | public function testGetFileLinkFormat(?string $fileLinkFormat): void 43 | { 44 | $displayPrettyExceptionsOptions = new DisplayPrettyExceptionsASAPOptions(null, $fileLinkFormat); 45 | 46 | $this->assertSame($fileLinkFormat, $displayPrettyExceptionsOptions->getFileLinkFormat()); 47 | } 48 | 49 | public function getFileLinkFormatProvider(): array 50 | { 51 | return array( 52 | array(null), 53 | array('myide://open?url=file://%%f&line=%%l'), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/EnableDebugClassLoader/EnableDebugClassLoaderActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 25 | 'ekino.drupal.debug.debug_kernel.on_kernel_instantiation' => 'process', 26 | ), EnableDebugClassLoaderAction::getSubscribedEvents()); 27 | } 28 | 29 | public function testProcess(): void 30 | { 31 | (new EnableDebugClassLoaderAction())->process(); 32 | 33 | $splAutoloadFunctions = \spl_autoload_functions(); 34 | if (!\is_array($splAutoloadFunctions) || empty($splAutoloadFunctions)) { 35 | self::fail('There should be registered __autoload() functions.'); 36 | } 37 | 38 | foreach ($splAutoloadFunctions as $callable) { 39 | $instance = $callable[0]; 40 | $this->assertInstanceOf(DebugClassLoader::class, $instance); 41 | $this->assertTrue(\method_exists($instance, 'findFile')); 42 | } 43 | 44 | DebugClassLoader::disable(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/ThrowErrorsAsExceptions/ThrowErrorsAsExceptionsActionTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 27 | 'ekino.drupal.debug.debug_kernel.after_environment_boot' => 'process', 28 | ), ThrowErrorsAsExceptionsAction::getSubscribedEvents()); 29 | } 30 | 31 | /** 32 | * @dataProvider processProvider 33 | */ 34 | public function testProcess(int $levels, ?LoggerInterface $logger): void 35 | { 36 | $throwErrorsAsExceptionsAction = new ThrowErrorsAsExceptionsAction(new ThrowErrorsAsExceptionsOptions($levels, $logger)); 37 | 38 | \set_error_handler(null); 39 | 40 | $throwErrorsAsExceptionsAction->process(); 41 | 42 | $callableErrorHandler = \set_error_handler(null); 43 | $this->assertInternalType('array', $callableErrorHandler); 44 | 45 | $errorHandler = \reset($callableErrorHandler); 46 | $this->assertInstanceOf(ErrorHandler::class, $errorHandler); 47 | 48 | /* @var ErrorHandler $errorHandler */ 49 | // cf the throwAt method in the ErrorHandler class 50 | $this->assertAttributeSame(($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED, 'thrownErrors', $errorHandler); 51 | 52 | if ($logger instanceof LoggerInterface) { 53 | $this->assertAttributeSame($levels, 'loggedErrors', $errorHandler); 54 | } 55 | } 56 | 57 | public function processProvider(): array 58 | { 59 | return array( 60 | array(E_USER_ERROR, null), 61 | array(E_CORE_ERROR, $this->createMock(LoggerInterface::class)), 62 | ); 63 | } 64 | 65 | public function testGetOptionsClass(): void 66 | { 67 | $this->assertSame('Ekino\Drupal\Debug\Action\ThrowErrorsAsExceptions\ThrowErrorsAsExceptionsOptions', ThrowErrorsAsExceptionsAction::getOptionsClass()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/ThrowErrorsAsExceptions/ThrowErrorsAsExceptionsOptionsTest.php: -------------------------------------------------------------------------------- 1 | assertSame(42, $throwErrorsAsExceptionsOptions->getLevels()); 27 | } 28 | 29 | /** 30 | * @dataProvider getLoggerProvider 31 | */ 32 | public function testGetLogger(?LoggerInterface $logger): void 33 | { 34 | $throwErrorsAsExceptionsOptions = new ThrowErrorsAsExceptionsOptions(42, $logger); 35 | 36 | $this->assertSame($logger, $throwErrorsAsExceptionsOptions->getLogger()); 37 | } 38 | 39 | public function getLoggerProvider(): array 40 | { 41 | return array( 42 | array(null), 43 | array($this->createMock(LoggerInterface::class)), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/WatchRoutingDefinitions/fixtures/File1.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/WatchRoutingDefinitions/fixtures/File1.php -------------------------------------------------------------------------------- /tests/Unit/src/Action/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/cache/.gitkeep -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/bar.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/bar.xml -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/fcy.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/fcy.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/src/BarFcyFoo.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/src/BarFcyFoo.php -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/src/bar/ccc_fcy.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/modules/module_ccc/src/bar/ccc_fcy.yml -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/foo.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/foo.php -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/great_theme.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/great_theme.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/src/great_theme_bar.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Action/fixtures/custom_extensions/themes/a_theme/src/great_theme_bar.yml -------------------------------------------------------------------------------- /tests/Unit/src/Action/fixtures/drupal-debug.yml: -------------------------------------------------------------------------------- 1 | drupal-debug: ~ 2 | -------------------------------------------------------------------------------- /tests/Unit/src/Action/test_classes/TestCompilerPassAction.php: -------------------------------------------------------------------------------- 1 | fileCache = $this->createMock(FileCache::class); 39 | 40 | $this->cacheNotFreshEvent = new CacheNotFreshEvent($this->fileCache); 41 | } 42 | 43 | public function testGetFileCache(): void 44 | { 45 | $this->assertSame($this->fileCache, $this->cacheNotFreshEvent->getFileCache()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Unit/src/Cache/fixtures/data_key_does_not_exist.php: -------------------------------------------------------------------------------- 1 | '2018-11-09T10:00:43+00:00', 16 | 'data' => array( 17 | 'foo' => 'bar', 18 | 'ccc' => array( 19 | 'fcy', 20 | ), 21 | ), 22 | ); 23 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Command/CommandProviderTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(array( 27 | new DisableOriginalDrupalKernelSubstitutionCommand(), 28 | new DumpReferenceConfigurationFileCommand(), 29 | new EnableOriginalDrupalKernelSubstitutionCommand(), 30 | ), (new CommandProvider())->getCommands()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Helper/fixtures/drupal-debug.yml: -------------------------------------------------------------------------------- 1 | drupal-debug: 2 | defaults: 3 | cache_directory_path: cache 4 | logger: 5 | enabled: true 6 | channel: drupal-debug 7 | file_path: logs/drupal-debug.log 8 | charset: null 9 | file_link_format: null 10 | actions: 11 | disable_css_aggregation: 12 | enabled: true 13 | disable_dynamic_page_cache: 14 | enabled: true 15 | disable_internal_page_cache: 16 | enabled: true 17 | disable_js_aggregation: 18 | enabled: true 19 | disable_render_cache: 20 | enabled: true 21 | disable_twig_cache: 22 | enabled: true 23 | display_dump_location: 24 | enabled: true 25 | display_pretty_exceptions: 26 | enabled: true 27 | charset: null 28 | file_link_format: null 29 | logger: 30 | enabled: true 31 | channel: drupal-debug 32 | file_path: logs/drupal-debug.log 33 | display_pretty_exceptions_asap: 34 | enabled: true 35 | charset: null 36 | file_link_format: null 37 | enable_debug_class_loader: 38 | enabled: true 39 | enable_twig_debug: 40 | enabled: true 41 | enable_twig_strict_variables: 42 | enabled: true 43 | throw_errors_as_exceptions: 44 | enabled: true 45 | levels: 32253 46 | logger: 47 | enabled: true 48 | channel: drupal-debug 49 | file_path: logs/drupal-debug.log 50 | watch_container_definitions: 51 | enabled: true 52 | include_defaults: true 53 | custom_file_resource_masks: { } 54 | cache_directory_path: cache 55 | watch_modules_hooks_implementations: 56 | enabled: true 57 | include_defaults: true 58 | custom_file_resource_masks: { } 59 | cache_directory_path: cache 60 | watch_routing_definitions: 61 | enabled: true 62 | include_defaults: true 63 | custom_file_resource_masks: { } 64 | cache_directory_path: cache 65 | substitute_original_drupal_kernel: 66 | enabled: true 67 | composer_autoload_file_path: vendor/autoload.php 68 | cache_directory_path: cache 69 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Helper/fixtures/not_writeable/drupal-debug.yml: -------------------------------------------------------------------------------- 1 | drupal-debug: ~ 2 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Helper/fixtures/toggle_substitution_cases/level-1-is-not-set.yml: -------------------------------------------------------------------------------- 1 | drupal-debug: 2 | ccc: ~ 3 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Helper/fixtures/toggle_substitution_cases/unknown-root-key.yml: -------------------------------------------------------------------------------- 1 | ccc: ~ 2 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Helper/helper/BufferIO.php: -------------------------------------------------------------------------------- 1 | setStream($this->createStream($userInputs)); 34 | 35 | $stream = \fopen('php://memory', 'rw'); 36 | if (!\is_resource($stream)) { 37 | throw new \RuntimeException('The stream could not be opened.'); 38 | } 39 | 40 | parent::__construct($input, new StreamOutput($stream), new HelperSet(array( 41 | new QuestionHelper(), 42 | ))); 43 | } 44 | 45 | public function getOutput(): string 46 | { 47 | \fseek($this->output->getStream(), 0); 48 | 49 | $output = \stream_get_contents($this->output->getStream()); 50 | if (!\is_string($output)) { 51 | throw new \RuntimeException('The stream content could not be gotten.'); 52 | } 53 | 54 | $output = (string) \preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function (array $matches): string { 55 | $pre = \strip_tags($matches[1]); 56 | 57 | if (\strlen($pre) === \strlen($matches[2])) { 58 | return ''; 59 | } 60 | 61 | return \rtrim($matches[1])."\n"; 62 | }, $output); 63 | 64 | return $output; 65 | } 66 | 67 | /** 68 | * @param string[] $inputs 69 | * 70 | * @return resource 71 | */ 72 | private function createStream(array $inputs) 73 | { 74 | $stream = \fopen('php://memory', 'r+', false); 75 | if (!\is_resource($stream)) { 76 | throw new \RuntimeException('The stream could not be opened.'); 77 | } 78 | 79 | foreach ($inputs as $input) { 80 | \fwrite($stream, $input.PHP_EOL); 81 | } 82 | 83 | \rewind($stream); 84 | 85 | return $stream; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/Unit/src/Composer/Plugin/RegisterCommandsPluginTest.php: -------------------------------------------------------------------------------- 1 | assertSame(array( 24 | 'Composer\Plugin\Capability\CommandProvider' => 'Ekino\Drupal\Debug\Composer\Command\CommandProvider', 25 | ), (new RegisterCommandsPlugin())->getCapabilities()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Unit/src/Configuration/Model/DefaultsConfigurationTest.php: -------------------------------------------------------------------------------- 1 | assertSame('/foo/cache', (new DefaultsConfiguration(array( 24 | 'cache_directory_path' => '/foo/cache', 25 | )))->getCacheDirectoryPath()); 26 | } 27 | 28 | public function testGetLogger(): void 29 | { 30 | $this->assertSame(array('foo'), (new DefaultsConfiguration(array( 31 | 'logger' => array('foo'), 32 | )))->getLogger()); 33 | } 34 | 35 | /** 36 | * @dataProvider getCharsetProvider 37 | */ 38 | public function testGetCharset(?string $charset): void 39 | { 40 | $this->assertSame($charset, (new DefaultsConfiguration(array( 41 | 'charset' => $charset, 42 | )))->getCharset()); 43 | } 44 | 45 | public function getCharsetProvider(): array 46 | { 47 | return array( 48 | array(null), 49 | array('utf-8'), 50 | ); 51 | } 52 | 53 | /** 54 | * @dataProvider getFileLinkFormatProvider 55 | */ 56 | public function testGetFileLinkFormat(?string $fileLinkFormat): void 57 | { 58 | $this->assertSame($fileLinkFormat, (new DefaultsConfiguration(array( 59 | 'file_link_format' => $fileLinkFormat, 60 | )))->getFileLinkFormat()); 61 | } 62 | 63 | public function getFileLinkFormatProvider(): array 64 | { 65 | return array( 66 | array(null), 67 | array('myide://open?url=file://%%f&line=%%l'), 68 | ); 69 | } 70 | 71 | public function testSerialize(): void 72 | { 73 | $this->assertSame('a:1:{i:0;a:2:{s:3:"foo";s:3:"bar";s:4:"deep";a:1:{s:2:"is";s:2:"ok";}}}', (new DefaultsConfiguration(array( 74 | 'foo' => 'bar', 75 | 'deep' => array( 76 | 'is' => 'ok', 77 | ), 78 | )))->serialize()); 79 | } 80 | 81 | public function testUnserialize(): void 82 | { 83 | $defaultsConfiguration = new DefaultsConfiguration(array()); 84 | $defaultsConfiguration->unserialize('a:1:{i:0;a:2:{s:3:"ccc";s:3:"fcy";s:5:"array";a:1:{s:2:"is";b:0;}}}'); 85 | 86 | $this->assertAttributeSame(array( 87 | 'ccc' => 'fcy', 88 | 'array' => array( 89 | 'is' => false, 90 | ), 91 | ), 'processedConfiguration', $defaultsConfiguration); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tests/Unit/src/Configuration/Model/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Configuration/Model/cache/.gitkeep -------------------------------------------------------------------------------- /tests/Unit/src/Configuration/Model/fixtures/invalid_autoload.php: -------------------------------------------------------------------------------- 1 | notImplementedException = new NotImplementedException('foo'); 32 | } 33 | 34 | public function testInstanceOfException(): void 35 | { 36 | $this->assertInstanceOf(\Exception::class, $this->notImplementedException); 37 | } 38 | 39 | public function testGetMessage(): void 40 | { 41 | $this->assertSame('foo', $this->notImplementedException->getMessage()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/Unit/src/Exception/NotSupportedExceptionTest.php: -------------------------------------------------------------------------------- 1 | notSupportedException = new NotSupportedException('foo'); 32 | } 33 | 34 | public function testInstanceOfException(): void 35 | { 36 | $this->assertInstanceOf(\Exception::class, $this->notSupportedException); 37 | } 38 | 39 | public function testGetMessage(): void 40 | { 41 | $this->assertSame('foo', $this->notSupportedException->getMessage()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/Unit/src/Extension/Model/AbstractCustomExtensionTest.php: -------------------------------------------------------------------------------- 1 | customExtension = new AbstractCustomExtensionTestClass('/foo', 'machine_name'); 37 | } 38 | 39 | public function testGetRootPath(): void 40 | { 41 | $this->assertSame('/foo', $this->customExtension->getRootPath()); 42 | } 43 | 44 | public function testGetMachineName(): void 45 | { 46 | $this->assertSame('machine_name', $this->customExtension->getMachineName()); 47 | } 48 | 49 | public function testSerialize(): void 50 | { 51 | $this->assertSame(self::SERIALIZED_CUSTOM_EXTENSION, $this->customExtension->serialize()); 52 | } 53 | 54 | public function testUnserialize(): void 55 | { 56 | $customExtension = new AbstractCustomExtensionTestClass('/bar', 'ccc'); 57 | $customExtension->unserialize(self::SERIALIZED_CUSTOM_EXTENSION); 58 | 59 | $this->assertEquals($this->customExtension, $customExtension); 60 | } 61 | } 62 | 63 | class AbstractCustomExtensionTestClass extends AbstractCustomExtension 64 | { 65 | } 66 | -------------------------------------------------------------------------------- /tests/Unit/src/Extension/Model/CustomModuleTest.php: -------------------------------------------------------------------------------- 1 | customModule = new CustomModule('/foo', 'machine_name'); 37 | } 38 | 39 | public function testGetCamelCaseMachineName(): void 40 | { 41 | $this->assertSame('MachineName', $this->customModule->getCamelCaseMachineName()); 42 | } 43 | 44 | public function testSerialize(): void 45 | { 46 | $this->assertSame(self::SERIALIZED_CUSTOM_MODULE, $this->customModule->serialize()); 47 | } 48 | 49 | public function testUnserialize(): void 50 | { 51 | $customModule = new CustomModule('/bar', 'ccc'); 52 | $customModule->unserialize(self::SERIALIZED_CUSTOM_MODULE); 53 | 54 | $this->assertEquals($this->customModule, $customModule); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/modules/module.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/modules/module.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/modules/sub/sub.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/modules/sub/sub.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/modules/sub/sub/sub/we/need/to_go_deeper/my_module.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/modules/sub/sub/sub/we/need/to_go_deeper/my_module.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/foo.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/foo.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/src/should_not_match.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/src/should_not_match.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/sub/bar.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/sub/bar.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/sub/sub/sub/fcy.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/modules/sub/sub/sub/fcy.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/unrelated/unrelated.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/all/unrelated/unrelated.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/sites/unrelated/unrelated.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/sites/unrelated/unrelated.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/themes/ccc.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/themes/ccc.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/foo.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/foo.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/sub/lib/should_not_match.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/sub/lib/should_not_match.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/sub/sub/fcy.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/themes/sub/sub/sub/fcy.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Extension/fixtures/custom_extensions/unrelated/unrelated.info.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Extension/fixtures/custom_extensions/unrelated/unrelated.info.yml -------------------------------------------------------------------------------- /tests/Unit/src/Helper/SettingsHelperTest.php: -------------------------------------------------------------------------------- 1 | settingsHelper = new SettingsHelper(); 38 | } 39 | 40 | public function testOverrideOnExistingKey(): void 41 | { 42 | new Settings(array( 43 | 'foo' => 'bar', 44 | 'one' => array( 45 | 'two' => array( 46 | 'three' => 'val', 47 | ), 48 | 'must' => 'not change', 49 | ), 50 | )); 51 | 52 | $this->settingsHelper->override('[foo]', 'ccc'); 53 | $this->assertSame('ccc', Settings::get('foo')); 54 | 55 | $this->settingsHelper->override('[one][two][three]', 'php'); 56 | $this->assertSame(array( 57 | 'two' => array( 58 | 'three' => 'php', 59 | ), 60 | 'must' => 'not change', 61 | ), Settings::get('one')); 62 | } 63 | 64 | public function testOverrideOnNewKey(): void 65 | { 66 | new Settings(array()); 67 | 68 | $this->settingsHelper->override('[foo]', 'ccc'); 69 | $this->assertSame('ccc', Settings::get('foo')); 70 | 71 | $this->settingsHelper->override('[one][two]', array( 72 | 'foo' => 'php', 73 | )); 74 | $this->assertSame(array( 75 | 'two' => array( 76 | 'foo' => 'php', 77 | ), 78 | ), Settings::get('one')); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/Unit/src/Kernel/Event/AbstractWithContainerAndEnabledExtensionsEventTest.php: -------------------------------------------------------------------------------- 1 | container = $this->createMock(ContainerInterface::class); 39 | 40 | $this->abstractWithContainerAndEnabledExtensionsEvent = new TestAbstractWithContainerAndEnabledExtensionsEvent(false, $this->container, array(), array()); 41 | } 42 | 43 | public function testGetContainer(): void 44 | { 45 | $this->assertSame($this->container, $this->abstractWithContainerAndEnabledExtensionsEvent->getContainer()); 46 | } 47 | } 48 | 49 | class TestAbstractWithContainerAndEnabledExtensionsEvent extends AbstractWithContainerAndEnabledExtensionsEvent 50 | { 51 | } 52 | -------------------------------------------------------------------------------- /tests/Unit/src/Kernel/Event/AbstractWithEnabledExtensionsEventTest.php: -------------------------------------------------------------------------------- 1 | abstractWithEnabledExtensionsEvent = new TestAbstractWithEnabledExtensionsEvent(false, array('foo'), array('bar')); 32 | } 33 | 34 | public function testGetEnabledModules(): void 35 | { 36 | $this->assertSame(array('foo'), $this->abstractWithEnabledExtensionsEvent->getEnabledModules()); 37 | } 38 | 39 | public function testGetEnabledThemes(): void 40 | { 41 | $this->assertSame(array('bar'), $this->abstractWithEnabledExtensionsEvent->getEnabledThemes()); 42 | } 43 | } 44 | 45 | class TestAbstractWithEnabledExtensionsEvent extends AbstractWithEnabledExtensionsEvent 46 | { 47 | } 48 | -------------------------------------------------------------------------------- /tests/Unit/src/Kernel/Helper/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Kernel/Helper/cache/.gitkeep -------------------------------------------------------------------------------- /tests/Unit/src/Kernel/Helper/fixtures/OriginalDrupalKernel.php: -------------------------------------------------------------------------------- 1 | resources = array( 55 | new FileResource(self::RESOURCE_1_FILE_PATH), 56 | new FileResource(self::RESOURCE_2_FILE_PATH), 57 | ); 58 | 59 | $this->resourcesCollection = new ResourcesCollection($this->resources); 60 | $resource1FilePathLength = \mb_strlen(self::RESOURCE_1_FILE_PATH); 61 | $resource2FilePathLength = \mb_strlen(self::RESOURCE_2_FILE_PATH); 62 | $this->serializedResourcesCollection = \sprintf('a:2:{i:0;C:46:"Symfony\Component\Config\Resource\FileResource":%s:{s:%s:"%s";}i:1;C:46:"Symfony\Component\Config\Resource\FileResource":%s:{s:%s:"%s";}}', ($resource1FilePathLength + \mb_strlen((string) $resource1FilePathLength) + 6), $resource1FilePathLength, self::RESOURCE_1_FILE_PATH, ($resource2FilePathLength + \mb_strlen((string) $resource2FilePathLength) + 6), $resource2FilePathLength, self::RESOURCE_2_FILE_PATH); 63 | } 64 | 65 | public function testAll(): void 66 | { 67 | $this->assertSame($this->resources, $this->resourcesCollection->all()); 68 | } 69 | 70 | public function testCount(): void 71 | { 72 | $this->assertCount(2, $this->resourcesCollection); 73 | } 74 | 75 | public function testSerialize(): void 76 | { 77 | $this->assertSame($this->serializedResourcesCollection, $this->resourcesCollection->serialize()); 78 | } 79 | 80 | public function testUnserialize(): void 81 | { 82 | $resourcesCollection = new ResourcesCollection(array()); 83 | $resourcesCollection->unserialize($this->serializedResourcesCollection); 84 | 85 | $this->assertEquals($this->resourcesCollection, $resourcesCollection); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/Unit/src/Resource/Model/fixtures/File1.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Resource/Model/fixtures/File1.php -------------------------------------------------------------------------------- /tests/Unit/src/Resource/Model/fixtures/File2.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Resource/Model/fixtures/File2.php -------------------------------------------------------------------------------- /tests/Unit/src/Resource/fixtures/File1.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Resource/fixtures/File1.php -------------------------------------------------------------------------------- /tests/Unit/src/Resource/fixtures/File2.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Resource/fixtures/File2.php -------------------------------------------------------------------------------- /tests/Unit/src/Resource/fixtures/File3.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekino/drupal-debug/112fdc39409cdc2bfbc8f79388f04599f1c4ce8e/tests/Unit/src/Resource/fixtures/File3.php -------------------------------------------------------------------------------- /tests/Unit/src/Resource/fixtures/unexpected_content.meta: -------------------------------------------------------------------------------- 1 | s:3:"foo"; 2 | --------------------------------------------------------------------------------