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\Writer\Twig; |
17
|
|
|
|
18
|
|
|
use Parsedown; |
19
|
|
|
use phpDocumentor\Descriptor\Collection; |
20
|
|
|
use phpDocumentor\Descriptor\ProjectDescriptor; |
21
|
|
|
use phpDocumentor\Transformer\Writer\Twig\ExtensionInterface; |
22
|
|
|
use phpDocumentor\Transformer\Router\Queue; |
23
|
|
|
use phpDocumentor\Transformer\Router\Renderer; |
24
|
|
|
use phpDocumentor\Transformer\Transformation; |
25
|
|
|
use Twig_Extension; |
26
|
|
|
use Twig_Extension_GlobalsInterface; |
27
|
|
|
use Twig_SimpleFilter; |
28
|
|
|
use Twig_SimpleFunction; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Basic extension adding phpDocumentor specific functionality for Twig |
32
|
|
|
* templates. |
33
|
|
|
* |
34
|
|
|
* Global variables: |
35
|
|
|
* |
36
|
|
|
* - *ast_node*, the current $data element |
37
|
|
|
* |
38
|
|
|
* Functions: |
39
|
|
|
* |
40
|
|
|
* - *path(string) *, converts the given relative path to be based of the projects |
41
|
|
|
* root instead of the current directory |
42
|
|
|
* |
43
|
|
|
* Filters: |
44
|
|
|
* |
45
|
|
|
* - *markdown*, converts the associated text from Markdown formatting to HTML. |
46
|
|
|
* - *trans*, translates the given string |
47
|
|
|
* - *route*, attempts to generate a URL for a given Descriptor |
48
|
|
|
* - *sort_desc*, sorts the given objects by their Name property/getter in a descending fashion |
49
|
|
|
* - *sort_asc*, sorts the given objects by their Name property/getter in a ascending fashion |
50
|
|
|
*/ |
51
|
|
|
class Extension extends Twig_Extension implements ExtensionInterface, Twig_Extension_GlobalsInterface |
52
|
|
|
{ |
53
|
|
|
/** |
54
|
|
|
* @var ProjectDescriptor |
55
|
|
|
*/ |
56
|
|
|
protected $data; |
57
|
|
|
|
58
|
|
|
/** @var Renderer */ |
59
|
|
|
protected $routeRenderer; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Registers the structure and transformation with this extension. |
63
|
|
|
* |
64
|
|
|
* @param ProjectDescriptor $project Represents the complete Abstract Syntax Tree. |
65
|
|
|
* @param Transformation $transformation Represents the transformation meta data used in the current generation |
66
|
|
|
* cycle. |
67
|
|
|
*/ |
68
|
|
|
public function __construct(ProjectDescriptor $project, Transformation $transformation) |
69
|
|
|
{ |
70
|
|
|
$this->data = $project; |
71
|
|
|
$this->routeRenderer = new Renderer(new Queue()); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Sets the router used to render the URL where a Descriptor can be found. |
76
|
|
|
*/ |
77
|
|
|
public function setRouters(Queue $routers): void |
78
|
|
|
{ |
79
|
|
|
$this->routeRenderer->setRouters($routers); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Sets the destination directory relative to the Project's Root. |
84
|
|
|
* |
85
|
|
|
* The destination is the target directory containing the resulting |
86
|
|
|
* file. This destination is relative to the Project's root and can |
87
|
|
|
* be used for the calculation of nesting depths, etc. |
88
|
|
|
* |
89
|
|
|
* @see Writer\Twig for the invocation of this method. |
90
|
|
|
*/ |
91
|
|
|
public function setDestination(string $destination): void |
92
|
|
|
{ |
93
|
|
|
$this->routeRenderer->setDestination($destination); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Returns the target directory relative to the Project's Root. |
98
|
|
|
*/ |
99
|
|
|
public function getDestination(): string |
100
|
|
|
{ |
101
|
|
|
return $this->routeRenderer->getDestination(); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Returns an array of global variables to inject into a Twig template. |
106
|
|
|
* |
107
|
|
|
* @return mixed[] |
108
|
|
|
*/ |
109
|
|
|
public function getGlobals(): array |
110
|
|
|
{ |
111
|
|
|
return [ |
112
|
|
|
'project' => $this->data, |
113
|
|
|
]; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Returns a listing of all functions that this extension adds. |
118
|
|
|
* |
119
|
|
|
* This method is automatically used by Twig upon registering this |
120
|
|
|
* extension (which is done automatically by phpDocumentor) to determine |
121
|
|
|
* an additional list of functions. |
122
|
|
|
* |
123
|
|
|
* See the Class' DocBlock for a listing of functionality added by this |
124
|
|
|
* Extension. |
125
|
|
|
* |
126
|
|
|
* @return Twig_SimpleFunction[] |
127
|
|
|
*/ |
128
|
|
|
public function getFunctions(): array |
129
|
|
|
{ |
130
|
|
|
return [ |
131
|
|
|
new Twig_SimpleFunction('path', [$this->routeRenderer, 'convertToRootPath']), |
132
|
|
|
]; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Returns a list of all filters that are exposed by this extension. |
137
|
|
|
* |
138
|
|
|
* @return Twig_SimpleFilter[] |
139
|
|
|
*/ |
140
|
|
|
public function getFilters(): array |
141
|
|
|
{ |
142
|
|
|
$parser = Parsedown::instance(); |
143
|
|
|
$routeRenderer = $this->routeRenderer; |
144
|
|
|
|
145
|
|
|
return [ |
146
|
|
|
'markdown' => new Twig_SimpleFilter( |
147
|
|
|
'markdown', |
148
|
|
|
function ($value) use ($parser) { |
149
|
|
|
return $parser->text($value); |
150
|
|
|
} |
151
|
|
|
), |
152
|
|
|
'trans' => new Twig_SimpleFilter( |
153
|
|
|
'trans', |
154
|
|
|
function ($value) { |
155
|
|
|
return $value; |
156
|
|
|
} |
157
|
|
|
), |
158
|
|
|
'route' => new Twig_SimpleFilter( |
159
|
|
|
'route', |
160
|
|
|
function ($value, $presentation = 'normal') use ($routeRenderer) { |
161
|
|
|
return $routeRenderer->render($value, $presentation); |
162
|
|
|
} |
163
|
|
|
), |
164
|
|
|
'sort' => new Twig_SimpleFilter( |
165
|
|
|
'sort_*', |
166
|
|
|
function ($direction, $collection) { |
167
|
|
|
if (!$collection instanceof Collection) { |
168
|
|
|
return $collection; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
$iterator = $collection->getIterator(); |
172
|
|
|
$iterator->uasort( |
173
|
|
|
function ($a, $b) use ($direction) { |
174
|
|
|
$aElem = strtolower($a->getName()); |
175
|
|
|
$bElem = strtolower($b->getName()); |
176
|
|
|
if ($aElem === $bElem) { |
177
|
|
|
return 0; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
if (($direction === 'asc' && $aElem > $bElem) || |
181
|
|
|
($direction === 'desc' && $aElem < $bElem) |
182
|
|
|
) { |
183
|
|
|
return 1; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
return -1; |
187
|
|
|
} |
188
|
|
|
); |
189
|
|
|
|
190
|
|
|
return $iterator; |
191
|
|
|
} |
192
|
|
|
), |
193
|
|
|
]; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Converts the given path to be relative to the root of the documentation |
198
|
|
|
* target directory. |
199
|
|
|
* |
200
|
|
|
* It is not possible to use absolute paths in documentation templates since |
201
|
|
|
* they may be used locally, or in a subfolder. As such we need to calculate |
202
|
|
|
* the number of levels to go up from the current document's directory and |
203
|
|
|
* then append the given path. |
204
|
|
|
* |
205
|
|
|
* For example: |
206
|
|
|
* |
207
|
|
|
* Suppose you are in <root>/classes/my/class.html and you want open |
208
|
|
|
* <root>/my/index.html then you provide 'my/index.html' to this method |
209
|
|
|
* and it will convert it into ../../my/index.html (<root>/classes/my is |
210
|
|
|
* two nesting levels until the root). |
211
|
|
|
* |
212
|
|
|
* This method does not try to normalize or optimize the paths in order to |
213
|
|
|
* save on development time and performance, and because it adds no real |
214
|
|
|
* value. |
215
|
|
|
*/ |
216
|
|
|
public function convertToRootPath(string $relative_path): string |
217
|
|
|
{ |
218
|
|
|
return $this->routeRenderer->convertToRootPath($relative_path); |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|