Completed
Push — develop ( 722f70...af048b )
by Jaap
15:12 queued 05:04
created

DescriptorAbstract   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 434
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 434
rs 8.5454
c 0
b 0
f 0
wmc 49
lcom 2
cbo 2

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A setFullyQualifiedStructuralElementName() 0 4 1
A getFullyQualifiedStructuralElementName() 0 4 1
A setName() 0 4 1
A getName() 0 4 1
A setNamespace() 0 4 1
A getNamespace() 0 4 1
A setSummary() 0 4 1
A getSummary() 0 13 4
A setDescription() 0 4 1
B getDescription() 0 17 5
A setLocation() 0 5 1
A getPath() 0 4 2
A getFile() 0 4 1
A setFile() 0 4 1
A getLine() 0 4 1
A setLine() 0 4 1
A setTags() 0 4 1
A getTags() 0 4 1
A setPackage() 0 4 1
B getPackage() 0 14 5
A getAuthor() 0 15 3
A getVersion() 0 15 3
A getCopyright() 0 15 3
A isDeprecated() 0 4 1
A setErrors() 0 4 1
A getErrors() 0 4 1
A __call() 0 11 2
A __toString() 0 4 1
A getInheritedElement() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like DescriptorAbstract often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DescriptorAbstract, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Descriptor;
13
14
use phpDocumentor\Descriptor\Filter\Filterable;
15
16
/**
17
 * Base class for descriptors containing the most used options.
18
 */
19
abstract class DescriptorAbstract implements Filterable
20
{
21
    /**
22
     * @var string $fqsen Fully Qualified Structural Element Name; the FQCN including method, property of constant name
23
     */
24
    protected $fqsen = '';
25
26
    /** @var string $name The local name for this element */
27
    protected $name = '';
28
29
    /** @var NamespaceDescriptor $namespace The namespace for this element */
30
    protected $namespace;
31
32
    /** @var string $package The package with which this element is associated */
33
    protected $package = '';
34
35
    /** @var string $summary A summary describing the function of this element in short. */
36
    protected $summary = '';
37
38
    /** @var string $description A more extensive description of this element. */
39
    protected $description = '';
40
41
    /** @var FileDescriptor|null $file The file to which this element belongs; if applicable */
42
    protected $fileDescriptor;
43
44
    /** @var int $line The line number on which this element occurs. */
45
    protected $line = 0;
46
47
    /** @var Collection $tags The tags associated with this element. */
48
    protected $tags;
49
50
    /** @var Collection $errors A list of errors found while building this element. */
51
    protected $errors;
52
53
    /** @var DescriptorAbstract|null the element from which to inherit information in this element */
54
    protected $inheritedElement = null;
55
56
    /**
57
     * Initializes this descriptor.
58
     */
59
    public function __construct()
60
    {
61
        $this->setTags(new Collection());
62
        $this->setErrors(new Collection());
63
    }
64
65
    /**
66
     * Sets the Fully Qualified Structural Element Name (FQSEN) for this element.
67
     *
68
     * @param string $name
69
     *
70
     * @return void
71
     */
72
    public function setFullyQualifiedStructuralElementName($name)
73
    {
74
        $this->fqsen = $name;
75
    }
76
77
    /**
78
     * Returns the Fully Qualified Structural Element Name (FQSEN) for this element.
79
     *
80
     * @return string
81
     */
82
    public function getFullyQualifiedStructuralElementName()
83
    {
84
        return $this->fqsen;
85
    }
86
87
    /**
88
     * Sets the local name for this element.
89
     *
90
     * @param string $name
91
     *
92
     * @return void
93
     */
94
    public function setName($name)
95
    {
96
        $this->name = $name;
97
    }
98
99
    /**
100
     * Returns the local name for this element.
101
     *
102
     * @return string
103
     */
104
    public function getName()
105
    {
106
        return $this->name;
107
    }
108
109
    /**
110
     * Sets the namespace (name) for this element.
111
     *
112
     * @param NamespaceDescriptor|string $namespace
113
     */
114
    public function setNamespace($namespace)
115
    {
116
        $this->namespace = $namespace;
0 ignored issues
show
Documentation Bug introduced by
It seems like $namespace can also be of type string. However, the property $namespace is declared as type object<phpDocumentor\Des...or\NamespaceDescriptor>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
117
    }
118
119
    /**
120
     * Returns the namespace for this element or null if none is attached.
121
     *
122
     * @return NamespaceDescriptor|string|null
123
     */
124
    public function getNamespace()
125
    {
126
        return $this->namespace;
127
    }
128
129
    /**
130
     * Sets the summary describing this element in short.
131
     *
132
     * @param string $summary
133
     *
134
     * @return void
135
     */
136
    public function setSummary($summary)
137
    {
138
        $this->summary = $summary;
139
    }
140
141
    /**
142
     * Returns the summary which describes this element.
143
     *
144
     * This method will automatically attempt to inherit the parent's summary if this one has none.
145
     *
146
     * @return string
147
     */
148
    public function getSummary()
149
    {
150
        if ($this->summary && strtolower(trim($this->summary)) != '{@inheritdoc}') {
151
            return $this->summary;
152
        }
153
154
        $parent = $this->getInheritedElement();
155
        if ($parent instanceof DescriptorAbstract) {
156
            return $parent->getSummary();
157
        }
158
159
        return $this->summary;
160
    }
161
162
    /**
163
     * Sets a description for this element.
164
     *
165
     * @param string $description
166
     *
167
     * @return void
168
     */
169
    public function setDescription($description)
170
    {
171
        $this->description = $description;
172
    }
173
174
    /**
175
     * Returns the description for this element.
176
     *
177
     * This method will automatically attempt to inherit the parent's description if this one has none.
178
     *
179
     * @return string
180
     */
181
    public function getDescription()
182
    {
183
        if ($this->description && strpos(strtolower($this->description), '{@inheritdoc}') === false) {
184
            return $this->description;
185
        }
186
187
        $parentElement = $this->getInheritedElement();
188
        if ($parentElement instanceof DescriptorAbstract) {
189
            $parentDescription = $parentElement->getDescription();
190
191
            return $this->description
192
                ? str_ireplace('{@inheritdoc}', $parentDescription, $this->description)
193
                : $parentDescription;
194
        }
195
196
        return $this->description;
197
    }
198
199
    /**
200
     * Sets the file and linenumber where this element is at.
201
     *
202
     * @param FileDescriptor $file
203
     * @param int            $line
204
     *
205
     * @return void
206
     */
207
    public function setLocation(FileDescriptor $file, $line = 0)
208
    {
209
        $this->setFile($file);
210
        $this->line = $line;
211
    }
212
213
    /**
214
     * Returns the path to the file containing this element relative to the project's root.
215
     *
216
     * @return string
217
     */
218
    public function getPath()
219
    {
220
        return $this->fileDescriptor ? $this->fileDescriptor->getPath() : '';
221
    }
222
223
    /**
224
     * Returns the file in which this element resides or null in case the element is not bound to a file..
225
     *
226
     * @return FileDescriptor|null
227
     */
228
    public function getFile()
229
    {
230
        return $this->fileDescriptor;
231
    }
232
233
    /**
234
     * Sets the file to which this element is associated.
235
     *
236
     * @param FileDescriptor $file
237
     *
238
     * @return false
239
     */
240
    public function setFile(FileDescriptor $file)
241
    {
242
        $this->fileDescriptor = $file;
243
    }
244
245
    /**
246
     * Returns the line number where the definition for this element can be found.
247
     *
248
     * @return int
249
     */
250
    public function getLine()
251
    {
252
        return $this->line;
253
    }
254
255
    /**
256
     * Sets the line number for this element's location in the source file.
257
     *
258
     * @param integer $lineNumber
259
     *
260
     * @return void
261
     */
262
    public function setLine($lineNumber)
263
    {
264
        $this->line = $lineNumber;
265
    }
266
267
    /**
268
     * Sets the tags associated with this element.
269
     *
270
     * @param Collection $tags
271
     *
272
     * @return void
273
     */
274
    public function setTags(Collection $tags)
275
    {
276
        $this->tags = $tags;
277
    }
278
279
    /**
280
     * Returns the tags associated with this element.
281
     *
282
     * @return Collection
283
     */
284
    public function getTags()
285
    {
286
        return $this->tags;
287
    }
288
289
    /**
290
     * Sets the name of the package to which this element belongs.
291
     *
292
     * @param PackageDescriptor $package
293
     *
294
     * @return void
295
     */
296
    public function setPackage($package)
297
    {
298
        $this->package = $package;
0 ignored issues
show
Documentation Bug introduced by
It seems like $package of type object<phpDocumentor\Des...ptor\PackageDescriptor> is incompatible with the declared type string of property $package.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
299
    }
300
301
    /**
302
     * Returns the package name for this element.
303
     *
304
     * @return PackageDescriptor
305
     */
306
    public function getPackage()
307
    {
308
        $inheritedElement = $this->getInheritedElement();
309
        if ($this->package instanceof PackageDescriptor
310
            && ! ($this->package->getName() === '\\' && $inheritedElement)) {
311
            return $this->package;
312
        }
313
314
        if ($inheritedElement instanceof DescriptorAbstract) {
315
            return $inheritedElement->getPackage();
316
        }
317
318
        return null;
319
    }
320
321
    /**
322
     * @return Collection
323
     */
324
    public function getAuthor()
325
    {
326
        /** @var Collection $author */
327
        $author = $this->getTags()->get('author', new Collection());
328
        if ($author->count() != 0) {
329
            return $author;
330
        }
331
332
        $inheritedElement = $this->getInheritedElement();
333
        if ($inheritedElement) {
334
            return $inheritedElement->getAuthor();
335
        }
336
337
        return new Collection();
338
    }
339
340
    /**
341
     * Returns the versions for this element.
342
     *
343
     * @return Collection
344
     */
345
    public function getVersion()
346
    {
347
        /** @var Collection $version */
348
        $version = $this->getTags()->get('version', new Collection());
349
        if ($version->count() != 0) {
350
            return $version;
351
        }
352
353
        $inheritedElement = $this->getInheritedElement();
354
        if ($inheritedElement) {
355
            return $inheritedElement->getVersion();
356
        }
357
358
        return new Collection();
359
    }
360
361
    /**
362
     * Returns the copyrights for this element.
363
     *
364
     * @return Collection
365
     */
366
    public function getCopyright()
367
    {
368
        /** @var Collection $copyright */
369
        $copyright = $this->getTags()->get('copyright', new Collection());
370
        if ($copyright->count() != 0) {
371
            return $copyright;
372
        }
373
374
        $inheritedElement = $this->getInheritedElement();
375
        if ($inheritedElement) {
376
            return $inheritedElement->getCopyright();
377
        }
378
379
        return new Collection();
380
    }
381
382
    /**
383
     * Checks whether this element is deprecated.
384
     *
385
     * @return boolean
386
     */
387
    public function isDeprecated()
388
    {
389
        return isset($this->tags['deprecated']);
390
    }
391
392
    /**
393
     * Sets a list of all errors associated with this element.
394
     *
395
     * @param Collection $errors
396
     */
397
    public function setErrors(Collection $errors)
398
    {
399
        $this->errors = $errors;
400
    }
401
402
    /**
403
     * Returns all errors that occur in this element.
404
     *
405
     * @return Collection
406
     */
407
    public function getErrors()
408
    {
409
        return $this->errors;
410
    }
411
412
    /**
413
     * Dynamically constructs a set of getters to retrieve tag (collections) with.
414
     *
415
     * Important: __call() is not a fast method of access; it is preferred to directly use the getTags() collection.
416
     * This interface is provided to allow for uniform and easy access to certain tags.
417
     *
418
     * @param string  $name
419
     * @param mixed[] $arguments
420
     *
421
     * @return Collection|null
422
     */
423
    public function __call($name, $arguments)
424
    {
425
        if (substr($name, 0, 3) !== 'get') {
426
            return null;
427
        }
428
429
        $tagName = substr($name, 3);
430
        $tagName[0] = strtolower($tagName[0]); // lowercase the first letter
431
432
        return $this->getTags()->get($tagName, new Collection());
433
    }
434
435
    /**
436
     * Represents this object by its unique identifier, the Fully Qualified Structural Element Name.
437
     *
438
     * @return string
439
     */
440
    public function __toString()
441
    {
442
        return $this->getFullyQualifiedStructuralElementName();
443
    }
444
445
    /**
446
     * @return DescriptorAbstract|null
447
     */
448
    public function getInheritedElement()
449
    {
450
        return $this->inheritedElement;
451
    }
452
}
453