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\Plugin\Core\Transformer\Behaviour\Tag; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Behaviour that adds support for the uses tag |
16
|
|
|
*/ |
17
|
|
|
class UsesTag |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* Find all return tags that contain 'self' or '$this' and replace those |
21
|
|
|
* terms for the name of the current class' type. |
22
|
|
|
* |
23
|
|
|
* @param \DOMDocument $xml Structure source to apply behaviour onto. |
24
|
|
|
* |
25
|
|
|
* @todo split method into submethods |
26
|
|
|
* |
27
|
|
|
* @return \DOMDocument |
28
|
|
|
*/ |
29
|
|
|
public function process(\DOMDocument $xml) |
|
|
|
|
30
|
|
|
{ |
31
|
|
|
$xpath = new \DOMXPath($xml); |
32
|
|
|
$nodes = $xpath->query('//tag[@name=\'uses\']'); |
33
|
|
|
|
34
|
|
|
/** @var \DOMElement $node */ |
35
|
|
|
foreach ($nodes as $node) { |
36
|
|
|
$refers = $node->getAttribute('refers'); |
37
|
|
|
$refers_array = explode('::', $refers); |
38
|
|
|
|
39
|
|
|
// determine the type so we know where to put the @usedby tag on |
40
|
|
|
$type = 'class'; |
41
|
|
|
if (isset($refers_array[1])) { |
42
|
|
|
// starts with $ = property, ends with () = method, |
43
|
|
|
// otherwise constant |
44
|
|
|
$type = $refers_array[1][0] == '$' ? 'property' : 'constant'; |
45
|
|
|
$type = substr($refers_array[1], -2) == '()' ? 'method' : $type; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
switch ($type) { |
49
|
|
|
case 'class': |
50
|
|
|
// escape single quotes in the class name |
51
|
|
|
$xpath_refers = 'concat(\''.str_replace( |
52
|
|
|
array("'", '"'), |
53
|
|
|
array('\', "\'", \'', '\', \'"\' , \''), |
54
|
|
|
$refers |
55
|
|
|
) . "', '')"; |
56
|
|
|
|
57
|
|
|
$qry = '/project/file/class[full_name=' . $xpath_refers . ']'; |
58
|
|
|
break; |
59
|
|
|
default: |
60
|
|
|
$class_name = $refers_array[0]; |
61
|
|
|
|
62
|
|
|
// escape single quotes in the class name |
63
|
|
|
$xpath_class_name = 'concat(\''.str_replace( |
64
|
|
|
array("'", '"'), |
65
|
|
|
array('\', "\'", \'', '\', \'"\' , \''), |
66
|
|
|
$class_name |
67
|
|
|
) . "', '')"; |
68
|
|
|
|
69
|
|
|
// escape single quotes in the method name |
70
|
|
|
$xpath_method_name = 'concat(\''.str_replace( |
71
|
|
|
array("'", '"'), |
72
|
|
|
array('\', "\'", \'', '\', \'"\' , \''), |
73
|
|
|
rtrim($refers_array[1], '()') |
74
|
|
|
) . "', '')"; |
75
|
|
|
|
76
|
|
|
$qry = '/project/file/class[full_name=' . $xpath_class_name |
77
|
|
|
. ']/'.$type.'[name=' . $xpath_method_name .']'; |
78
|
|
|
break; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** @noinspection PhpUsageOfSilenceOperatorInspection as there is no pre-validation possible */ |
82
|
|
|
$referral_nodes = @$xpath->query($qry); |
83
|
|
|
|
84
|
|
|
// if the query is wrong; output a Critical error and continue to |
85
|
|
|
// the next @uses |
86
|
|
|
if ($referral_nodes === false) { |
87
|
|
|
continue; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
// check if the result is unique; if not we error and continue |
91
|
|
|
// to the next @uses |
92
|
|
|
if ($referral_nodes->length > 1) { |
93
|
|
|
continue; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
// if there is one matching element; link them together |
97
|
|
|
if ($referral_nodes->length > 0) { |
98
|
|
|
/** @var \DOMElement $referral */ |
99
|
|
|
$referral = $referral_nodes->item(0); |
100
|
|
|
$docblock = $referral->getElementsByTagName('docblock'); |
101
|
|
|
if ($docblock->length < 1) { |
102
|
|
|
$docblock = new \DOMElement('docblock'); |
103
|
|
|
$referral->appendChild($docblock); |
104
|
|
|
} else { |
105
|
|
|
$docblock = $docblock->item(0); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$used_by = new \DOMElement('tag'); |
109
|
|
|
$docblock->appendChild($used_by); |
110
|
|
|
$used_by->setAttribute('name', 'used_by'); |
111
|
|
|
$used_by->setAttribute('line', ''); |
112
|
|
|
|
113
|
|
|
// gather the name of the referring element and set that as refers |
114
|
|
|
// attribute |
115
|
|
|
if ($node->parentNode->parentNode->nodeName == 'class') { |
116
|
|
|
// if the element where the @uses is in is a class; nothing |
117
|
|
|
// more than the class name need to returned |
118
|
|
|
$referral_name = $node->parentNode->parentNode |
119
|
|
|
->getElementsByTagName('full_name')->item(0)->nodeValue; |
120
|
|
|
} else { |
|
|
|
|
121
|
|
|
|
122
|
|
|
$referral_class_name = null; |
123
|
|
|
if ($node->parentNode->parentNode->nodeName == 'method') { |
124
|
|
|
// gather the name of the class where the @uses is in |
125
|
|
|
$referral_class_name = $node->parentNode->parentNode |
126
|
|
|
->parentNode->getElementsByTagName('full_name')->item(0) |
127
|
|
|
->nodeValue; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
// gather the name of the subelement of the class where |
131
|
|
|
// the @uses is in |
132
|
|
|
$referral_name = $node->parentNode->parentNode |
133
|
|
|
->getElementsByTagName('name')->item(0)->nodeValue; |
134
|
|
|
|
135
|
|
|
// if it is a method; suffix with () |
136
|
|
|
if ($node->parentNode->parentNode->nodeName == 'method' |
137
|
|
|
|| $node->parentNode->parentNode->nodeName == 'function' |
138
|
|
|
) { |
139
|
|
|
$referral_name .= '()'; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
// only prefix class name if this is a class member |
143
|
|
|
if ($referral_class_name) { |
144
|
|
|
$referral_name = $referral_class_name . '::' |
145
|
|
|
. $referral_name; |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
$used_by->setAttribute('description', $referral_name); |
150
|
|
|
$used_by->setAttribute('refers', $referral_name); |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
return $xml; |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.
You can also find more information in the “Code” section of your repository.