Completed
Push — develop ( 0b8425...c51867 )
by Jaap
15s queued 11s
created

ProjectDescriptorBuilder   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 17.95%

Importance

Changes 0
Metric Value
dl 0
loc 221
ccs 14
cts 78
cp 0.1795
rs 10
c 0
b 0
f 0
wmc 29
lcom 1
cbo 9

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A createProjectDescriptor() 0 4 1
A setProjectDescriptor() 0 4 1
A getProjectDescriptor() 0 4 1
A isVisibilityAllowed() 0 19 5
B buildDescriptor() 0 23 6
A getAssembler() 0 4 1
A filter() 0 4 1
A filterEachDescriptor() 0 14 3
A filterDescriptor() 0 14 3
A mapCodeToSeverity() 0 4 1
A build() 0 26 4
A getDefaultPackage() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @author    Mike van Riel <[email protected]>
11
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
12
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
13
 * @link      http://phpdoc.org
14
 */
15
16
namespace phpDocumentor\Descriptor;
17
18
use phpDocumentor\Descriptor\Builder\AssemblerFactory;
19
use phpDocumentor\Descriptor\Builder\AssemblerInterface;
20
use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
21
use phpDocumentor\Descriptor\Filter\Filter;
22
use phpDocumentor\Descriptor\Filter\Filterable;
23
use phpDocumentor\Descriptor\ProjectDescriptor\Settings;
24
use phpDocumentor\Reflection\Php\Project;
25
use Psr\Log\LogLevel;
26
27
/**
28
 * Builds a Project Descriptor and underlying tree.
29
 */
30
class ProjectDescriptorBuilder
31
{
32
    /** @var string */
33
    const DEFAULT_PROJECT_NAME = 'Untitled project';
34
35
    /** @var AssemblerFactory $assemblerFactory */
36
    protected $assemblerFactory;
37
38
    /** @var Filter $filter */
39
    protected $filter;
40
41
    /** @var ProjectDescriptor $project */
42
    protected $project;
43
44
    private $defaultPackage;
45
46
    public function __construct(AssemblerFactory $assemblerFactory, Filter $filterManager)
47
    {
48
        $this->assemblerFactory = $assemblerFactory;
49
        $this->filter = $filterManager;
50
    }
51 1
52
    public function createProjectDescriptor()
53 1
    {
54 1
        $this->project = new ProjectDescriptor(self::DEFAULT_PROJECT_NAME);
55
    }
56 1
57
    public function setProjectDescriptor(ProjectDescriptor $projectDescriptor)
58 1
    {
59 1
        $this->project = $projectDescriptor;
60
    }
61
62
    /**
63
     * Returns the project descriptor that is being built.
64
     *
65
     * @return ProjectDescriptor
66 2
     */
67
    public function getProjectDescriptor()
68 2
    {
69
        return $this->project;
70
    }
71
72
    /**
73
     * Verifies whether the given visibility is allowed to be included in the Descriptors.
74
     *
75
     * This method is used anytime a Descriptor is added to a collection (for example, when adding a Method to a Class)
76
     * to determine whether the visibility of that element is matches what the user has specified when it ran
77
     * phpDocumentor.
78
     *
79
     * @param string|integer $visibility One of the visibility constants of the ProjectDescriptor class or the words
80
     *     'public', 'protected', 'private' or 'internal'.
81
     *
82
     * @see ProjectDescriptor where the visibility is stored and that declares the constants to use.
83
     *
84
     * @return boolean
85 1
     */
86
    public function isVisibilityAllowed($visibility)
87
    {
88 1
        switch ($visibility) {
89
            case 'public':
90
                $visibility = Settings::VISIBILITY_PUBLIC;
91 1
                break;
92
            case 'protected':
93
                $visibility = Settings::VISIBILITY_PROTECTED;
94 1
                break;
95
            case 'private':
96
                $visibility = Settings::VISIBILITY_PRIVATE;
97 1
                break;
98
            case 'internal':
99
                $visibility = Settings::VISIBILITY_INTERNAL;
100
                break;
101
        }
102 1
103
        return $this->getProjectDescriptor()->isVisibilityAllowed($visibility);
104
    }
105
106
    /**
107
     * Takes the given data and attempts to build a Descriptor from it.
108
     *
109
     * @param mixed $data
110
     *
111
     * @throws \InvalidArgumentException if no Assembler could be found that matches the given data.
112
     *
113
     * @return DescriptorAbstract|Collection|null
114
     */
115
    public function buildDescriptor($data)
116
    {
117
        $assembler = $this->getAssembler($data);
118
        if (!$assembler) {
119
            throw new \InvalidArgumentException(
120
                'Unable to build a Descriptor; the provided data did not match any Assembler ' . get_class($data)
121
            );
122
        }
123
124
        if ($assembler instanceof Builder\AssemblerAbstract) {
125
            $assembler->setBuilder($this);
126
        }
127
128
        // create Descriptor and populate with the provided data
129
        $descriptor = $assembler->create($data);
130
        if (!$descriptor) {
131
            return null;
132
        }
133
134
        return (!is_array($descriptor) && (!$descriptor instanceof Collection))
135
            ? $this->filterDescriptor($descriptor)
136
            : $this->filterEachDescriptor($descriptor);
0 ignored issues
show
Documentation introduced by
$descriptor is of type array|object<phpDocumentor\Descriptor\Collection>, but the function expects a array<integer,object<php...or\DescriptorAbstract>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
137
    }
138
139
    /**
140
     * Attempts to find an assembler matching the given data.
141
     *
142
     * @param mixed $data
143
     *
144
     * @return AssemblerInterface|null
145
     */
146
    public function getAssembler($data)
147
    {
148
        return $this->assemblerFactory->get($data);
149
    }
150
151
    /**
152
     * Analyzes a Descriptor and alters its state based on its state or even removes the descriptor.
153
     *
154
     * @return Filterable
155
     */
156
    public function filter(Filterable $descriptor)
157
    {
158
        return $this->filter->filter($descriptor);
159
    }
160
161
    /**
162
     * Filters each descriptor, validates them, stores the validation results and returns a collection of transmuted
163
     * objects.
164
     *
165
     * @param DescriptorAbstract[] $descriptor
166
     *
167
     * @return Collection
168
     */
169
    private function filterEachDescriptor($descriptor)
170
    {
171
        $descriptors = new Collection();
172
        foreach ($descriptor as $key => $item) {
173
            $item = $this->filterDescriptor($item);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $item is correct as $this->filterDescriptor($item) (which targets phpDocumentor\Descriptor...der::filterDescriptor()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
174
            if (!$item) {
175
                continue;
176
            }
177
178
            $descriptors[$key] = $item;
179
        }
180
181
        return $descriptors;
182
    }
183
184
    /**
185
     * Filters a descriptor, validates it, stores the validation results and returns the transmuted object or null
186
     * if it is supposed to be removed.
187
     *
188
     * @param Descriptor $descriptor
189
     *
190
     * @return Descriptor|null
191
     */
192
    protected function filterDescriptor(Descriptor $descriptor)
193
    {
194
        if (!$descriptor instanceof Filterable) {
195
            return $descriptor;
196
        }
197
198
        // filter the descriptor; this may result in the descriptor being removed!
199
        $descriptor = $this->filter($descriptor);
200
        if (!$descriptor) {
201
            return null;
202
        }
203
204
        return $descriptor;
205
    }
206
207
    /**
208
     * Map error code to severity.
209
     *
210
     * @param int $code
211
     *
212
     * @return string
213
     */
214
    protected function mapCodeToSeverity($code)
0 ignored issues
show
Unused Code introduced by
The parameter $code is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
215
    {
216
        return LogLevel::ERROR;
217
    }
218
219
    public function build(Project $project)
220
    {
221
        $packageName = $project->getRootNamespace()->getFqsen()->getName();
222
        $this->defaultPackage = new PackageDescriptor();
223
        $this->defaultPackage->setFullyQualifiedStructuralElementName((string) $project->getRootNamespace()->getFqsen());
224
        $this->defaultPackage->setName($packageName);
225
        $this->defaultPackage->setNamespace(
226
            substr((string) $project->getRootNamespace()->getFqsen(), 0, -strlen($packageName) - 1)
227
        );
228
229
        foreach ($project->getFiles() as $file) {
230
            $descriptor = $this->buildDescriptor($file);
231
            if (!$descriptor) {
232
                return;
233
            }
234
235
            $this->getProjectDescriptor()->getFiles()->set($descriptor->getPath(), $descriptor);
236
        }
237
238
        $namespaces = $this->getProjectDescriptor()->getIndexes()->get('namespaces', new Collection());
239
//        $namespaces->add($this->defaultPackage);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
240
241
        foreach ($project->getNamespaces() as $namespace) {
242
            $namespaces->set((string) $namespace->getFqsen(), $this->buildDescriptor($namespace));
243
        }
244
    }
245
246
    public function getDefaultPackage()
247
    {
248
        return $this->defaultPackage;
249
    }
250
}
251