Completed
Pull Request — master (#107)
by Simon
02:49
created

DocBlockGenerator::getGeneratedDocBlock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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