Chris@0: finder = new ClassFinder(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, BaseStaticReflectionParser $parser = NULL) { Chris@0: if (!($annotation instanceof MultipleProviderAnnotationInterface)) { Chris@0: throw new \LogicException('AnnotatedClassDiscoveryAutomatedProviders annotations must implement \Drupal\migrate\Annotation\MultipleProviderAnnotationInterface'); Chris@0: } Chris@0: $annotation->setClass($class); Chris@0: $providers = $annotation->getProviders(); Chris@0: // Loop through all the parent classes and add their providers (which we Chris@0: // infer by parsing their namespaces) to the $providers array. Chris@0: do { Chris@0: $providers[] = $this->getProviderFromNamespace($parser->getNamespaceName()); Chris@0: } while ($parser = StaticReflectionParser::getParentParser($parser, $this->finder)); Chris@0: $providers = array_unique(array_filter($providers, function ($provider) { Chris@0: return $provider && $provider !== 'component'; Chris@0: })); Chris@0: $annotation->setProviders($providers); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getDefinitions() { Chris@0: $definitions = []; Chris@0: Chris@0: $reader = $this->getAnnotationReader(); Chris@0: Chris@0: // Clear the annotation loaders of any previous annotation classes. Chris@0: AnnotationRegistry::reset(); Chris@0: // Register the namespaces of classes that can be used for annotations. Chris@0: AnnotationRegistry::registerLoader('class_exists'); Chris@0: Chris@0: // Search for classes within all PSR-0 namespace locations. Chris@0: foreach ($this->getPluginNamespaces() as $namespace => $dirs) { Chris@0: foreach ($dirs as $dir) { Chris@0: if (file_exists($dir)) { Chris@0: $iterator = new \RecursiveIteratorIterator( Chris@0: new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS) Chris@0: ); Chris@0: foreach ($iterator as $fileinfo) { Chris@0: if ($fileinfo->getExtension() == 'php') { Chris@0: if ($cached = $this->fileCache->get($fileinfo->getPathName())) { Chris@0: if (isset($cached['id'])) { Chris@0: // Explicitly unserialize this to create a new object instance. Chris@0: $definitions[$cached['id']] = unserialize($cached['content']); Chris@0: } Chris@0: continue; Chris@0: } Chris@0: Chris@0: $sub_path = $iterator->getSubIterator()->getSubPath(); Chris@0: $sub_path = $sub_path ? str_replace(DIRECTORY_SEPARATOR, '\\', $sub_path) . '\\' : ''; Chris@0: $class = $namespace . '\\' . $sub_path . $fileinfo->getBasename('.php'); Chris@0: Chris@0: // The filename is already known, so there is no need to find the Chris@0: // file. However, StaticReflectionParser needs a finder, so use a Chris@0: // mock version. Chris@0: $finder = MockFileFinder::create($fileinfo->getPathName()); Chris@0: $parser = new BaseStaticReflectionParser($class, $finder, FALSE); Chris@0: Chris@0: /** @var $annotation \Drupal\Component\Annotation\AnnotationInterface */ Chris@0: if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), $this->pluginDefinitionAnnotationName)) { Chris@0: $this->prepareAnnotationDefinition($annotation, $class, $parser); Chris@0: Chris@0: $id = $annotation->getId(); Chris@0: $content = $annotation->get(); Chris@0: $definitions[$id] = $content; Chris@0: // Explicitly serialize this to create a new object instance. Chris@0: $this->fileCache->set($fileinfo->getPathName(), ['id' => $id, 'content' => serialize($content)]); Chris@0: } Chris@0: else { Chris@0: // Store a NULL object, so the file is not reparsed again. Chris@0: $this->fileCache->set($fileinfo->getPathName(), [NULL]); Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: // Don't let annotation loaders pile up. Chris@0: AnnotationRegistry::reset(); Chris@0: Chris@0: return $definitions; Chris@0: } Chris@0: Chris@0: }