Completed
Push — develop ( 80740b...61b5c3 )
by Mike
10:20
created

ReturnTag   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 72
rs 10
c 0
b 0
f 0
wmc 8
lcom 0
cbo 0

1 Method

Rating   Name   Duplication   Size   Complexity  
B process() 0 61 8
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\Transformer\Behaviour\Tag;
17
18
/**
19
 * Behaviour that adds support for the return tag
20
 */
21
class ReturnTag
22
{
23
    /**
24
     * Find all return tags that contain 'self' or '$this' and replace those
25
     * terms for the name of the current class' type.
26
     *
27
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
28
     *
29
     * @return \DOMDocument
30
     */
31
    public function process(\DOMDocument $xml)
32
    {
33
        $ignoreQry = '//tag[@name=\'return\' and @type=\'self\']'
34
            . '|//tag[@name=\'return\' and @type=\'$this\']'
35
            . '|//tag[@name=\'return\']/type[.=\'self\']'
36
            . '|//tag[@name=\'return\']/type[.=\'$this\']';
37
38
        $xpath = new \DOMXPath($xml);
39
        $nodes = $xpath->query($ignoreQry);
40
41
        /** @var \DOMElement $node */
42
        foreach ($nodes as $node) {
43
            // if a node with name 'type' is selected we need to reach one
44
            // level further.
45
            $docblock = ($node->nodeName === 'type')
46
                ? $node->parentNode->parentNode
47
                : $node->parentNode;
48
49
            /** @var \DOMElement $method */
50
            $method = $docblock->parentNode;
51
52
            // if the method is not a method but a global function: error!
53
            if ($method->nodeName !== 'method') {
54
                continue;
55
            }
56
57
            /** @var \DOMElement $parentNode */
58
            $parentNode = $method->parentNode;
59
            $type = $parentNode->getElementsByTagName('full_name')
60
                ->item(0)->nodeValue;
61
62
            // nodes with name type need to set their content; otherwise we set
63
            // an attribute of the class itself
64
            if ($node->nodeName === 'type') {
65
                $node->nodeValue = $type;
66
67
                // add a new tag @fluent to indicate that this is a fluent interface
68
                // we only add it here since there should always be a node `type`
69
                $fluent_tag = new \DOMElement('tag');
70
                $docblock->appendChild($fluent_tag);
71
                $fluent_tag->setAttribute('name', 'fluent');
72
                $fluent_tag->setAttribute(
73
                    'description',
74
                    'This method is part of a fluent interface and will return '
75
                    . 'the same instance'
76
                );
77
            } else {
78
                $node->setAttribute('type', $type);
79
            }
80
81
            // check if an excerpt is set and override that as well
82
            if ($node->hasAttribute('excerpt')
83
                && (($node->getAttribute('excerpt') === 'self')
84
                || ($node->getAttribute('excerpt') === '$this'))
85
            ) {
86
                $node->setAttribute('excerpt', $type);
87
            }
88
        }
89
90
        return $xml;
91
    }
92
}
93