These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace phpDocumentor\Application\Renderer; |
||
4 | |||
5 | use phpDocumentor\DomainModel\Path; |
||
6 | use phpDocumentor\Application\Renderer\Template\Action\Twig; |
||
7 | use phpDocumentor\Application\Renderer\TwigRenderer\Extension; |
||
8 | use phpDocumentor\Application\Renderer\Template\Action; |
||
9 | use phpDocumentor\Application\Renderer\TwigRenderer\Pathfinder; |
||
10 | use phpDocumentor\DomainModel\Renderer\RenderContext; |
||
11 | use phpDocumentor\Infrastructure\Renderer\Template\LocalPathsRepository; |
||
12 | use phpDocumentor\DomainModel\Renderer\Router\ForFileProxy; |
||
13 | use phpDocumentor\DomainModel\Renderer\Router\Queue; |
||
14 | use phpDocumentor\DomainModel\ReadModel\ReadModel; |
||
15 | use phpDocumentor\DomainModel\ReadModel\Factory; |
||
16 | use phpDocumentor\DomainModel\ReadModel\ReadModels; |
||
17 | |||
18 | class TwigRenderer |
||
19 | { |
||
20 | public function render(ReadModel $view, Path $destination, $template = null) |
||
0 ignored issues
–
show
|
|||
21 | { |
||
22 | // TODO: Implement render() method. |
||
23 | } |
||
24 | |||
25 | /** @var Pathfinder */ |
||
26 | private $pathfinder; |
||
27 | |||
28 | /** @var Queue */ |
||
29 | private $routers; |
||
30 | |||
31 | /** @var LocalPathsRepository */ |
||
32 | private $fileRepository; |
||
33 | |||
34 | /** @var string */ |
||
35 | private $cacheFolder = ''; |
||
36 | |||
37 | /** @var Factory */ |
||
38 | private $viewFactory; |
||
39 | |||
40 | public function __construct( |
||
41 | Pathfinder $pathfinder, |
||
42 | Queue $routers, |
||
43 | LocalPathsRepository $fileRepository, |
||
44 | Factory $viewFactory, |
||
45 | $cacheFolder = null |
||
46 | ) { |
||
47 | if ($cacheFolder === null) { |
||
48 | $cacheFolder = sys_get_temp_dir() . '/phpdoc-twig-cache'; |
||
49 | } |
||
50 | |||
51 | $this->pathfinder = $pathfinder; |
||
52 | $this->routers = $routers; |
||
53 | $this->fileRepository = $fileRepository; |
||
54 | $this->cacheFolder = $cacheFolder; |
||
55 | $this->viewFactory = $viewFactory; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * Executes the activities that this Action represents. |
||
60 | * |
||
61 | * @param Action|Twig $action |
||
62 | * |
||
63 | * @return void |
||
64 | */ |
||
65 | public function __invoke(Action $action) |
||
66 | { |
||
67 | $dataView = $this->viewFactory->create($action->getDataView(), $action->getRenderPass()->getDocumentation()); |
||
68 | $views = new ReadModels([$dataView->getName() => $dataView()]); |
||
69 | |||
70 | // TODO: Move path finding to View |
||
71 | $nodes = $this->pathfinder->find($dataView(), $action->getQuery()); |
||
72 | |||
73 | foreach ($nodes as $node) { |
||
74 | if (!$node) { |
||
75 | continue; |
||
76 | } |
||
77 | |||
78 | if (! ($action->getDestination())) { |
||
79 | $rule = $this->routers->match($node); |
||
80 | if (!$rule) { |
||
81 | throw new \InvalidArgumentException( |
||
82 | 'No matching routing rule could be found for the given node, please provide an artifact ' |
||
83 | . 'location, encountered: ' . ($node === null ? 'NULL' : get_class($node)) |
||
84 | ); |
||
85 | } |
||
86 | |||
87 | $rule = new ForFileProxy($rule); |
||
88 | $url = $rule->generate($node); |
||
89 | if ($url === false || $url[0] !== DIRECTORY_SEPARATOR) { |
||
90 | $destination = false; |
||
91 | } else { |
||
92 | $destination = $action->getDestination() . $url; |
||
93 | } |
||
94 | } else { |
||
95 | $destination = $this->getDestinationPath($node, $action->getDestination()); |
||
96 | } |
||
97 | |||
98 | if ($destination === false) { |
||
99 | continue; |
||
100 | } |
||
101 | |||
102 | $destination = $action->getRenderPass()->getDestination() . '/' . ltrim($destination, '\\/'); |
||
103 | |||
104 | // create directory if it does not exist yet |
||
105 | if (!file_exists(dirname($destination))) { |
||
106 | mkdir(dirname($destination), 0777, true); |
||
107 | } |
||
108 | |||
109 | // move to local variable because we want to add to it without affecting other runs |
||
110 | $templatesFolders = $this->fileRepository->listLocations($action->getTemplate()); |
||
111 | |||
112 | $environment = new \Twig_Environment( |
||
113 | new \Twig_Loader_Filesystem($templatesFolders), |
||
114 | array('cache' => $this->cacheFolder, 'auto_reload' => true) |
||
115 | ); |
||
116 | |||
117 | $this->addPhpDocumentorExtension($views, $destination, $environment, $action->getRenderPass()); |
||
118 | // $this->addExtensionsFromTemplateConfiguration($transformation, $project, $environment); |
||
119 | $environment->addGlobal('node', $node); |
||
120 | |||
121 | $html = $environment->render((string)$action->getView()); |
||
122 | file_put_contents($destination, $html); |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Adds the phpDocumentor base extension to the Twig Environment. |
||
128 | * |
||
129 | * @param ReadModels $views |
||
130 | * @param string $destination |
||
131 | * @param \Twig_Environment $twigEnvironment |
||
132 | * |
||
133 | * @return void |
||
134 | */ |
||
135 | private function addPhpDocumentorExtension( |
||
136 | ReadModels $views, |
||
137 | $destination, |
||
138 | \Twig_Environment $twigEnvironment, |
||
139 | RenderContext $renderPass |
||
140 | ) { |
||
141 | $baseExtension = new Extension($views); |
||
142 | $baseExtension->setDestination(substr($destination, strlen($renderPass->getDestination()) + 1)); |
||
0 ignored issues
–
show
The method
getDestination() does not seem to exist on object<phpDocumentor\Dom...Renderer\RenderContext> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
143 | $baseExtension->setRouters($this->routers); |
||
144 | $twigEnvironment->addExtension($baseExtension); |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Tries to add any custom extensions that have been defined in the template or the transformation's configuration. |
||
149 | * |
||
150 | * This method will read the `twig-extension` parameter of the transformation (which inherits the template's |
||
151 | * parameter set) and try to add those extensions to the environment. |
||
152 | * |
||
153 | * @param Transformation $transformation |
||
154 | * @param ProjectInterface $project |
||
155 | * @param \Twig_Environment $twigEnvironment |
||
156 | * |
||
157 | * @throws \InvalidArgumentException if a twig-extension should be loaded but it could not be found. |
||
158 | * |
||
159 | * @return void |
||
160 | */ |
||
161 | // protected function addExtensionsFromTemplateConfiguration( |
||
162 | // Transformation $transformation, |
||
163 | // ProjectInterface $project, |
||
164 | // \Twig_Environment $twigEnvironment |
||
165 | // ) { |
||
166 | // $isDebug = $transformation->getParameter('twig-debug') |
||
167 | // ? $transformation->getParameter('twig-debug')->getValue() |
||
168 | // : false; |
||
169 | // if ($isDebug == 'true') { |
||
170 | // $twigEnvironment->enableDebug(); |
||
171 | // $twigEnvironment->enableAutoReload(); |
||
172 | // $twigEnvironment->addExtension(new \Twig_Extension_Debug()); |
||
173 | // } |
||
174 | // |
||
175 | // /** @var Template\Parameter $extension */ |
||
176 | // foreach ($transformation->getParametersWithKey('twig-extension') as $extension) { |
||
177 | // $extensionValue = $extension->getValue(); |
||
178 | // if (!class_exists($extensionValue)) { |
||
179 | // throw new \InvalidArgumentException('Unknown twig extension: ' . $extensionValue); |
||
180 | // } |
||
181 | // |
||
182 | // // to support 'normal' Twig extensions we check the interface to determine what instantiation to do. |
||
183 | // $implementsInterface = in_array( |
||
184 | // 'phpDocumentor\Plugin\Twig\ExtensionInterface', |
||
185 | // class_implements($extensionValue) |
||
186 | // ); |
||
187 | // |
||
188 | // $twigEnvironment->addExtension( |
||
189 | // $implementsInterface ? new $extensionValue($project, $transformation) : new $extensionValue() |
||
190 | // ); |
||
191 | // } |
||
192 | // } |
||
193 | |||
194 | /** |
||
195 | * Uses the currently selected node and transformation to assemble the destination path for the file. |
||
196 | * |
||
197 | * The Twig writer accepts the use of a Query to be able to generate output for multiple objects using the same |
||
198 | * template. |
||
199 | * |
||
200 | * The given node is the result of such a query, or if no query given the selected element, and the transformation |
||
201 | * contains the destination file. |
||
202 | * |
||
203 | * Since it is important to be able to generate a unique name per element can the user provide a template variable |
||
204 | * in the name of the file. |
||
205 | * Such a template variable always resides between double braces and tries to take the node value of a given |
||
206 | * query string. |
||
207 | * |
||
208 | * Example: |
||
209 | * |
||
210 | * An artifact stating `classes/{{name}}.html` will try to find the |
||
211 | * node 'name' as a child of the given $node and use that value instead. |
||
212 | * |
||
213 | * @param DescriptorAbstract $node |
||
214 | * |
||
215 | * @throws \InvalidArgumentException if no artifact is provided and no routing rule matches. |
||
216 | * @throws \UnexpectedValueException if the provided node does not contain anything. |
||
217 | * |
||
218 | * @return string|false returns the destination location or false if generation should be aborted. |
||
219 | */ |
||
220 | private function getDestinationPath($node, $destination) |
||
221 | { |
||
222 | $destination = preg_replace_callback( |
||
223 | '/{{([^}]+)}}/', // explicitly do not use the unicode modifier; this breaks windows |
||
224 | function ($query) use ($node) { |
||
225 | // strip any surrounding \ or / |
||
226 | $filepart = trim((string)current($this->pathfinder->find($node, $query[1])), '\\/'); |
||
227 | $filepart = implode('/', array_map('urlencode', explode('/', $filepart))); |
||
228 | |||
229 | return $filepart; |
||
230 | }, |
||
231 | $destination |
||
232 | ); |
||
233 | |||
234 | return $destination; |
||
235 | } |
||
236 | } |
||
237 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.