Source of file AbstractTagGenerator.php
Size: 6,760 Bytes - Last Modified: 2021-12-23T10:24:49+00:00
/var/www/docs.ssmods.com/process/src/src/Generators/AbstractTagGenerator.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 | <?php namespace SilverLeague\IDEAnnotator\Generators; use Generator; use phpDocumentor\Reflection\DocBlock\Tag; use ReflectionClass; use ReflectionException; use SilverLeague\IDEAnnotator\DataObjectAnnotator; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; use SilverStripe\Core\Extension; use SilverStripe\Core\Injector\Injector; /** * AbstractTagGenerator * * @package IDEAnnotator/Generators */ abstract class AbstractTagGenerator { /** * The current class we are working with * @var string */ protected $className = ''; /** * The existing tags of the class we are working with * @var Tag[] */ protected $existingTags = []; /** * @var ReflectionClass */ protected $reflector; /** * List all the generated tags form the various generateSomeORMProperies methods * @see $this->getSupportedTagTypes(); * @var Tag[] */ protected $tags = []; /** * DocBlockTagGenerator constructor. * * @param string $className * @param $existingTags * @throws ReflectionException */ public function __construct($className, $existingTags) { $this->className = $className; $this->existingTags = (array)$existingTags; $this->reflector = new ReflectionClass($className); $this->tags = $this->getSupportedTagTypes(); $this->generateTags(); } /** * List of supported tags. * * Each tag type can hold many tags, so we keep them grouped. * Also used to reset the tag list after each run * * @return array */ public function getSupportedTagTypes() { return [ 'properties' => [], 'methods' => [], 'mixins' => [], 'other' => [] ]; } /** * @return void */ abstract protected function generateTags(); /** * @return Tag[] */ public function getTags() { return (array)call_user_func_array('array_merge', $this->tags); } /** * Generate the mixins for DataExtensions. */ protected function generateExtensionsTags() { if ($fields = (array)$this->getClassConfig('extensions')) { foreach ($fields as $fieldName) { $mixinName = $this->getAnnotationClassName($fieldName); $this->pushMixinTag($mixinName); } } } /** * @param $key * @return mixed */ protected function getClassConfig($key) { return Config::inst()->get($this->className, $key, CONFIG::UNINHERITED); } /** * Check if we need to use the short name for a class * * @param string $class * @return string */ protected function getAnnotationClassName($class) { if (DataObjectAnnotator::config()->get('use_short_name')) { return ClassInfo::shortName($class); } return "\\$class"; } /** * @param $tagString */ protected function pushMixinTag($tagString) { $this->tags['mixins'][$tagString] = $this->pushTagWithExistingComment('mixin', $tagString); } /** * @param $type * @param $tagString * @return Tag */ protected function pushTagWithExistingComment($type, $tagString) { $tagString .= $this->getExistingTagCommentByTagString($tagString); return new Tag($type, $tagString); } /** * @param string $tagString * @return string */ public function getExistingTagCommentByTagString($tagString) { foreach ($this->getExistingTags() as $tag) { $content = $tag->getContent(); // A tag should be followed by a space before it's description // This is to prevent `TestThing` and `Test` to be seen as the same, when the shorter // is after the longer name if (strpos($content, $tagString . ' ') !== false) { return str_replace($tagString, '', $content); } } return ''; } /** * @return Tag[] */ public function getExistingTags() { return $this->existingTags; } /** * Generate the Owner-properties for extensions. * * @throws ReflectionException */ protected function generateOwnerTags() { $className = $this->className; // If className is abstract, Injector will fail to instantiate it $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { return; } if (Injector::inst()->get($this->className) instanceof Extension) { $owners = iterator_to_array($this->getOwnerClasses($className)); $owners[] = $this->className; $tagString = '\\' . implode("|\\", array_values($owners)) . ' $owner'; if (DataObjectAnnotator::config()->get('use_short_name')) { foreach ($owners as $key => $owner) { $owners[$key] = $this->getAnnotationClassName($owner); } $tagString = implode("|", array_values($owners)) . ' $owner'; } $this->pushPropertyTag($tagString); } } /** * Get all owner classes of the given extension class * * @param string $extensionClass Class name of the extension * @return string[]|Generator List of all direct owners of this extension */ protected function getOwnerClasses($extensionClass) { foreach (DataObjectAnnotator::getExtensionClasses() as $objectClass) { $config = Config::inst()->get( $objectClass, 'extensions', Config::UNINHERITED | Config::EXCLUDE_EXTRA_SOURCES ) ?: []; foreach ($config as $candidateClass) { if (Extension::get_classname_without_arguments($candidateClass) === $extensionClass) { yield $objectClass; break; } } } } /** * @param string $tagString */ protected function pushPropertyTag($tagString) { $this->tags['properties'][$tagString] = $this->pushTagWithExistingComment('property', $tagString); } /** * @param string $methodName * @param string $tagString */ protected function pushMethodTag($methodName, $tagString) { // Exception for `data()` method is needed if (!$this->reflector->hasMethod($methodName) || $methodName === 'data()') { $this->tags['methods'][$tagString] = $this->pushTagWithExistingComment('method', $tagString); } } } |