Preloader.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\DependencyInjection\Dumper;
  11. /**
  12. * @author Nicolas Grekas <p@tchwork.com>
  13. *
  14. * @internal
  15. */
  16. class Preloader
  17. {
  18. public static function preload(array $classes)
  19. {
  20. set_error_handler(function ($t, $m, $f, $l) {
  21. if (error_reporting() & $t) {
  22. if (__FILE__ !== $f) {
  23. throw new \ErrorException($m, 0, $t, $f, $l);
  24. }
  25. throw new \ReflectionException($m);
  26. }
  27. });
  28. $prev = [];
  29. $preloaded = [];
  30. try {
  31. while ($prev !== $classes) {
  32. $prev = $classes;
  33. foreach ($classes as $c) {
  34. if (!isset($preloaded[$c])) {
  35. self::doPreload($c, $preloaded);
  36. }
  37. }
  38. $classes = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits());
  39. }
  40. } finally {
  41. restore_error_handler();
  42. }
  43. }
  44. private static function doPreload(string $class, array &$preloaded)
  45. {
  46. if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], true)) {
  47. return;
  48. }
  49. $preloaded[$class] = true;
  50. try {
  51. $r = new \ReflectionClass($class);
  52. if ($r->isInternal()) {
  53. return;
  54. }
  55. $r->getConstants();
  56. $r->getDefaultProperties();
  57. if (\PHP_VERSION_ID >= 70400) {
  58. foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) {
  59. if (($t = $p->getType()) && !$t->isBuiltin()) {
  60. self::doPreload($t->getName(), $preloaded);
  61. }
  62. }
  63. }
  64. foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) {
  65. foreach ($m->getParameters() as $p) {
  66. if ($p->isDefaultValueAvailable() && $p->isDefaultValueConstant()) {
  67. $c = $p->getDefaultValueConstantName();
  68. if ($i = strpos($c, '::')) {
  69. self::doPreload(substr($c, 0, $i), $preloaded);
  70. }
  71. }
  72. if (($t = $p->getType()) && !$t->isBuiltin()) {
  73. self::doPreload($t->getName(), $preloaded);
  74. }
  75. }
  76. if (($t = $m->getReturnType()) && !$t->isBuiltin()) {
  77. self::doPreload($t->getName(), $preloaded);
  78. }
  79. }
  80. } catch (\ReflectionException $e) {
  81. // ignore missing classes
  82. }
  83. }
  84. }