Completed
Push — master ( 071c16...b9f390 )
by Mike
03:33
created

Twig::router()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
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;
17
18
use phpDocumentor\Descriptor\ProjectDescriptor;
19
use phpDocumentor\Transformer\Router\Router;
20
use phpDocumentor\Transformer\Transformation;
21
use phpDocumentor\Transformer\Writer\Twig\EnvironmentFactory;
22
use Twig\Error\LoaderError;
23
use Twig\Error\RuntimeError;
24
use Twig\Error\SyntaxError;
25
26
/**
27
 * A specialized writer which uses the Twig templating engine to convert
28
 * templates to HTML output.
29
 *
30
 * This writer support the Query attribute of a Transformation to generate
31
 * multiple templates in one transformation.
32
 *
33
 * The Query attribute supports a simplified version of Twig queries and will
34
 * use each individual result as the 'node' global variable in the Twig template.
35
 *
36
 * Example:
37
 *
38
 *   Suppose a Query `indexes.classes` is given then this writer will be
39
 *   invoked as many times as there are classes in the project and the
40
 *   'node' global variable in twig will be filled with each individual
41
 *   class entry.
42
 *
43
 * When using the Query attribute in the transformation it is important to
44
 * use a variable in the Artifact attribute as well (otherwise the same file
45
 * would be overwritten several times).
46
 *
47
 * A simple example transformation line could be:
48
 *
49
 *     ```
50
 *     <transformation
51
 *         writer="twig"
52
 *         source="templates/twig/index.twig"
53
 *         artifact="index.html"/>
54
 *     ```
55
 *
56
 *     This example transformation would use this writer to transform the
57
 *     index.twig template file in the twig template folder into index.html at
58
 *     the destination location.
59
 *     Since no Query is provided the 'node' global variable will contain
60
 *     the Project Descriptor of the Object Graph.
61
 *
62
 * A complex example transformation line could be:
63
 *
64
 *     ```
65
 *     <transformation
66
 *         query="indexes.classes"
67
 *         writer="twig"
68
 *         source="templates/twig/class.twig"
69
 *         artifact="{{name}}.html"/>
70
 *     ```
71
 *
72
 *     This example transformation would use this writer to transform the
73
 *     class.twig template file in the twig template folder into a file with
74
 *     the 'name' property for an individual class inside the Object Graph.
75
 *     Since a Query *is* provided will the 'node' global variable contain a
76
 *     specific instance of a class applicable to the current iteration.
77
 *
78
 * @see self::getDestinationPath() for more information about variables in the
79
 *     Artifact attribute.
80
 */
81
final class Twig extends WriterAbstract
82
{
83
    private $environmentFactory;
84
    private $router;
85
86
    public function __construct(EnvironmentFactory $environmentFactory, Router $router)
87
    {
88
        $this->environmentFactory = $environmentFactory;
89
        $this->router = $router;
90
    }
91
92
    protected function router(): ?Router
93
    {
94
        return $this->router;
95
    }
96
97
    /**
98
     * This method combines the ProjectDescriptor and the given target template
99
     * and creates a static html page at the artifact location.
100
     *
101
     * @param ProjectDescriptor $project Document containing the structure.
102
     * @param Transformation $transformation Transformation to execute.
103
     *
104
     * @throws LoaderError
105
     * @throws RuntimeError
106
     * @throws SyntaxError
107
     */
108
    public function transform(ProjectDescriptor $project, Transformation $transformation): void
109
    {
110
        $template_path = $this->getTemplatePath($transformation);
111
112
        $finder = new Pathfinder();
113
        $nodes = $finder->find($project, $transformation->getQuery());
114
115
        foreach ($nodes as $node) {
116
            if (!$node) {
117
                continue;
118
            }
119
120
            $destination = $this->destination($node, $transformation);
121
            if ($destination === null) {
122
                continue;
123
            }
124
125
            $environment = $this->environmentFactory->create($project, $transformation, $destination);
126
            $environment->addGlobal('node', $node);
127
128
            $html = $environment->render(substr($transformation->getSource(), strlen($template_path)));
129
            file_put_contents($destination, $html);
130
        }
131
    }
132
133
    /**
134
     * Returns the path belonging to the template.
135
     */
136
    private function getTemplatePath(Transformation $transformation): string
137
    {
138
        $parts = preg_split('[\\\\|/]', $transformation->getSource());
139
140
        return $parts[0] . DIRECTORY_SEPARATOR . $parts[1];
141
    }
142
}
143