#!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (\in_array('-h', $argv) || \in_array('--help', $argv)) { echo implode(PHP_EOL, [ ' Patches type declarations based on "@return" PHPDoc and triggers deprecations for', ' incompatible method declarations.', '', ' This assists you to make your package compatible with Symfony 6, but it can be used', ' for any class/package.', '', ' Available configuration via environment variables:', ' SYMFONY_PATCH_TYPE_DECLARATIONS', ' An url-encoded string to change the behavior of the script. Available parameters:', ' - "force": any value enables deprecation notices - can be any of:', ' - "phpdoc" to patch only docblock annotations', ' - "2" to add all possible return types', ' - "1" to add return types but only to tests/final/internal/private methods', ' - "php": the target version of PHP - e.g. "7.1" doesn\'t generate "object" types', ' - "deprecations": "1" to trigger a deprecation notice when a child class misses a', ' return type while the parent declares an "@return" annotation', '', ' SYMFONY_PATCH_TYPE_EXCLUDE', ' A regex matched against the full path to the class - any match will be excluded', '', ' Example: "SYMFONY_PATCH_TYPE_DECLARATIONS=php=7.4 ./patch-type-declarations"', ]); exit; } if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=2'); echo 'No SYMFONY_PATCH_TYPE_DECLARATIONS env var set, patching type declarations in all methods (run the command with "-h" for more information).'.PHP_EOL; } if (is_file($autoload = __DIR__.'/../../../../autoload.php')) { // noop } elseif (is_file($autoload = __DIR__.'/../../../../../../../autoload.php')) { // noop } else { echo PHP_EOL.' /!\ Cannot find the Composer autoloader, did you forget to run "composer install"?'.PHP_EOL; exit(1); } if (is_file($phpunitAutoload = dirname($autoload).'/bin/.phpunit/phpunit/vendor/autoload.php')) { require $phpunitAutoload; } $loader = require $autoload; Symfony\Component\ErrorHandler\DebugClassLoader::enable(); $deprecations = []; set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations) { if (\E_USER_DEPRECATED !== $type) { return; } [,,,,, $class,] = explode('"', $msg); $deprecations[$class][] = $msg; }); $exclude = getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null; foreach ($loader->getClassMap() as $class => $file) { if (false !== strpos($file = realpath($file), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { continue; } if ($exclude && preg_match($exclude, $file)) { continue; } class_exists($class); } Symfony\Component\ErrorHandler\DebugClassLoader::checkClasses(); foreach ($deprecations as $class => $classDeprecations) { echo $class.' ('.\count($classDeprecations).')'.PHP_EOL; echo implode(PHP_EOL, $classDeprecations).PHP_EOL.PHP_EOL; } if ($deprecations && false !== strpos(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) { echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.'.PHP_EOL; }