vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/AnnotationDriver.php line 191

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Persistence\Mapping\Driver;
  3. use Doctrine\Common\Annotations\Reader;
  4. use Doctrine\Persistence\Mapping\MappingException;
  5. use FilesystemIterator;
  6. use RecursiveDirectoryIterator;
  7. use RecursiveIteratorIterator;
  8. use RecursiveRegexIterator;
  9. use ReflectionClass;
  10. use RegexIterator;
  11. use function array_merge;
  12. use function array_unique;
  13. use function class_exists;
  14. use function get_class;
  15. use function get_declared_classes;
  16. use function in_array;
  17. use function is_dir;
  18. use function preg_match;
  19. use function preg_quote;
  20. use function realpath;
  21. use function str_replace;
  22. use function strpos;
  23. /**
  24.  * The AnnotationDriver reads the mapping metadata from docblock annotations.
  25.  */
  26. abstract class AnnotationDriver implements MappingDriver
  27. {
  28.     /**
  29.      * The annotation reader.
  30.      *
  31.      * @var Reader
  32.      */
  33.     protected $reader;
  34.     /**
  35.      * The paths where to look for mapping files.
  36.      *
  37.      * @var string[]
  38.      */
  39.     protected $paths = [];
  40.     /**
  41.      * The paths excluded from path where to look for mapping files.
  42.      *
  43.      * @var string[]
  44.      */
  45.     protected $excludePaths = [];
  46.     /**
  47.      * The file extension of mapping documents.
  48.      *
  49.      * @var string
  50.      */
  51.     protected $fileExtension '.php';
  52.     /**
  53.      * Cache for AnnotationDriver#getAllClassNames().
  54.      *
  55.      * @var string[]|null
  56.      */
  57.     protected $classNames;
  58.     /**
  59.      * Name of the entity annotations as keys.
  60.      *
  61.      * @var string[]
  62.      */
  63.     protected $entityAnnotationClasses = [];
  64.     /**
  65.      * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
  66.      * docblock annotations.
  67.      *
  68.      * @param Reader               $reader The AnnotationReader to use, duck-typed.
  69.      * @param string|string[]|null $paths  One or multiple paths where mapping classes can be found.
  70.      */
  71.     public function __construct($reader$paths null)
  72.     {
  73.         $this->reader $reader;
  74.         if (! $paths) {
  75.             return;
  76.         }
  77.         $this->addPaths((array) $paths);
  78.     }
  79.     /**
  80.      * Appends lookup paths to metadata driver.
  81.      *
  82.      * @param string[] $paths
  83.      *
  84.      * @return void
  85.      */
  86.     public function addPaths(array $paths)
  87.     {
  88.         $this->paths array_unique(array_merge($this->paths$paths));
  89.     }
  90.     /**
  91.      * Retrieves the defined metadata lookup paths.
  92.      *
  93.      * @return string[]
  94.      */
  95.     public function getPaths()
  96.     {
  97.         return $this->paths;
  98.     }
  99.     /**
  100.      * Append exclude lookup paths to metadata driver.
  101.      *
  102.      * @param string[] $paths
  103.      */
  104.     public function addExcludePaths(array $paths)
  105.     {
  106.         $this->excludePaths array_unique(array_merge($this->excludePaths$paths));
  107.     }
  108.     /**
  109.      * Retrieve the defined metadata lookup exclude paths.
  110.      *
  111.      * @return string[]
  112.      */
  113.     public function getExcludePaths()
  114.     {
  115.         return $this->excludePaths;
  116.     }
  117.     /**
  118.      * Retrieve the current annotation reader
  119.      *
  120.      * @return Reader
  121.      */
  122.     public function getReader()
  123.     {
  124.         return $this->reader;
  125.     }
  126.     /**
  127.      * Gets the file extension used to look for mapping files under.
  128.      *
  129.      * @return string
  130.      */
  131.     public function getFileExtension()
  132.     {
  133.         return $this->fileExtension;
  134.     }
  135.     /**
  136.      * Sets the file extension used to look for mapping files under.
  137.      *
  138.      * @param string $fileExtension The file extension to set.
  139.      *
  140.      * @return void
  141.      */
  142.     public function setFileExtension($fileExtension)
  143.     {
  144.         $this->fileExtension $fileExtension;
  145.     }
  146.     /**
  147.      * Returns whether the class with the specified name is transient. Only non-transient
  148.      * classes, that is entities and mapped superclasses, should have their metadata loaded.
  149.      *
  150.      * A class is non-transient if it is annotated with an annotation
  151.      * from the {@see AnnotationDriver::entityAnnotationClasses}.
  152.      *
  153.      * @param string $className
  154.      *
  155.      * @return bool
  156.      */
  157.     public function isTransient($className)
  158.     {
  159.         $classAnnotations $this->reader->getClassAnnotations(new ReflectionClass($className));
  160.         foreach ($classAnnotations as $annot) {
  161.             if (isset($this->entityAnnotationClasses[get_class($annot)])) {
  162.                 return false;
  163.             }
  164.         }
  165.         return true;
  166.     }
  167.     /**
  168.      * {@inheritDoc}
  169.      */
  170.     public function getAllClassNames()
  171.     {
  172.         if ($this->classNames !== null) {
  173.             return $this->classNames;
  174.         }
  175.         if (! $this->paths) {
  176.             throw MappingException::pathRequired();
  177.         }
  178.         $classes       = [];
  179.         $includedFiles = [];
  180.         foreach ($this->paths as $path) {
  181.             if (! is_dir($path)) {
  182.                 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
  183.             }
  184.             $iterator = new RegexIterator(
  185.                 new RecursiveIteratorIterator(
  186.                     new RecursiveDirectoryIterator($pathFilesystemIterator::SKIP_DOTS),
  187.                     RecursiveIteratorIterator::LEAVES_ONLY
  188.                 ),
  189.                 '/^.+' preg_quote($this->fileExtension) . '$/i',
  190.                 RecursiveRegexIterator::GET_MATCH
  191.             );
  192.             foreach ($iterator as $file) {
  193.                 $sourceFile $file[0];
  194.                 if (! preg_match('(^phar:)i'$sourceFile)) {
  195.                     $sourceFile realpath($sourceFile);
  196.                 }
  197.                 foreach ($this->excludePaths as $excludePath) {
  198.                     $exclude str_replace('\\''/'realpath($excludePath));
  199.                     $current str_replace('\\''/'$sourceFile);
  200.                     if (strpos($current$exclude) !== false) {
  201.                         continue 2;
  202.                     }
  203.                 }
  204.                 require_once $sourceFile;
  205.                 $includedFiles[] = $sourceFile;
  206.             }
  207.         }
  208.         $declared get_declared_classes();
  209.         foreach ($declared as $className) {
  210.             $rc         = new ReflectionClass($className);
  211.             $sourceFile $rc->getFileName();
  212.             if (! in_array($sourceFile$includedFiles) || $this->isTransient($className)) {
  213.                 continue;
  214.             }
  215.             $classes[] = $className;
  216.         }
  217.         $this->classNames $classes;
  218.         return $classes;
  219.     }
  220. }
  221. class_exists(\Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver::class);