DocBlockGenerator   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 33
dl 0
loc 132
rs 10
c 2
b 0
f 0
wmc 11

7 Methods

Rating   Name   Duplication   Size   Complexity  
A mergeGeneratedTagsIntoDocBlock() 0 15 3
A __construct() 0 10 2
A getExistingTags() 0 10 2
A removeExistingSupportedTags() 0 9 1
A getExistingDocBlock() 0 3 1
A getGeneratedTags() 0 3 1
A getGeneratedDocBlock() 0 5 1
1
<?php
2
3
namespace SilverLeague\IDEAnnotator\Generators;
4
5
use phpDocumentor\Reflection\DocBlock;
6
use phpDocumentor\Reflection\DocBlock\Serializer;
7
use phpDocumentor\Reflection\DocBlock\Tag;
8
use phpDocumentor\Reflection\DocBlockFactory;
9
use SilverStripe\Control\Controller;
10
use InvalidArgumentException;
11
use LogicException;
12
use ReflectionClass;
13
use ReflectionException;
14
15
/**
16
 * Class DocBlockGenerator
17
 *
18
 * @package IDEAnnotator/Generators
19
 */
20
class DocBlockGenerator
21
{
22
    /**
23
     * The current class we are working with
24
     * @var string
25
     */
26
    protected $className = '';
27
28
    /**
29
     * @var ReflectionClass
30
     */
31
    protected $reflector;
32
33
    /**
34
     * @var AbstractTagGenerator
35
     */
36
    protected $tagGenerator;
37
38
    /**
39
     * @var DocBlockFactory
40
     */
41
    protected $docBlockFactory;
42
43
    /**
44
     * DocBlockGenerator constructor.
45
     *
46
     * @param $className
47
     * @throws ReflectionException
48
     * @throws InvalidArgumentException
49
     */
50
    public function __construct($className)
51
    {
52
        $this->className = $className;
53
        $this->reflector = new ReflectionClass($className);
54
        $this->docBlockFactory = DocBlockFactory::createInstance();
55
56
        $generatorClass = $this->reflector->isSubclassOf(Controller::class)
57
            ? ControllerTagGenerator::class : OrmTagGenerator::class;
58
59
        $this->tagGenerator = new $generatorClass($className, $this->getExistingTags());
60
    }
61
62
    /**
63
     * @return Tag[]
64
     * @throws InvalidArgumentException
65
     */
66
    public function getExistingTags()
67
    {
68
        $docBlock = $this->getExistingDocBlock();
69
        if (!$docBlock) {
70
            return [];
71
        }
72
73
        $docBlock = $this->docBlockFactory->create($docBlock);
74
75
        return $docBlock->getTags();
76
    }
77
78
    /**
79
     * Not that in case there are multiple doblocks for a class,
80
     * the last one will be returned
81
     *
82
     * If we file old style generated docblocks we remove them
83
     *
84
     * @return bool|string
85
     */
86
    public function getExistingDocBlock()
87
    {
88
        return $this->reflector->getDocComment();
89
    }
90
91
    /**
92
     * @return DocBlock|string
93
     * @throws LogicException
94
     * @throws InvalidArgumentException
95
     */
96
    public function getGeneratedDocBlock()
97
    {
98
        $docBlock = $this->getExistingDocBlock();
99
100
        return $this->mergeGeneratedTagsIntoDocBlock($docBlock);
101
    }
102
103
    /**
104
     * @param string $existingDocBlock
105
     * @return string
106
     * @throws LogicException
107
     * @throws InvalidArgumentException
108
     */
109
    protected function mergeGeneratedTagsIntoDocBlock($existingDocBlock)
110
    {
111
        $docBlock = $this->docBlockFactory->create(($existingDocBlock ?: "/**\n*/"));
112
113
        $summary = $docBlock->getSummary();
114
        if (!$summary) {
115
            $summary = sprintf('Class \\%s', $this->className);
116
        }
117
118
        $docBlock = new DocBlock($summary, $docBlock->getDescription(), $this->getGeneratedTags());
119
120
        $serializer = new Serializer();
121
        $docBlock = $serializer->getDocComment($docBlock);
122
123
        return $docBlock;
124
    }
125
126
    /**
127
     * Remove all existing tags that are supported by this module.
128
     *
129
     * This will make sure that removed ORM properties and Extenions will not remain in the docblock,
130
     * while providing the option to manually add docblocks like @author etc.
131
     *
132
     * @param $docBlock
133
     * @return string
134
     */
135
    public function removeExistingSupportedTags($docBlock)
136
    {
137
        $replacements = [
138
            "/ \* @property ([\s\S]*?)\n/",
139
            "/ \* @method ([\s\S]*?)\n/",
140
            "/ \* @mixin ([\s\S]*?)\n/"
141
        ];
142
143
        return (string)preg_replace($replacements, '', $docBlock);
144
    }
145
146
    /**
147
     * @return Tag[]
148
     */
149
    public function getGeneratedTags()
150
    {
151
        return $this->tagGenerator->getTags();
152
    }
153
}
154