Completed
Push — develop ( 521632...eb9c4a )
by Mike
06:46
created

Transform::__invoke()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
nc 8
nop 1
dl 0
loc 33
ccs 0
cts 20
cp 0
crap 20
rs 9.392
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\Application\Stage;
17
18
use Exception;
19
use phpDocumentor\Compiler\Compiler;
20
use phpDocumentor\Descriptor\Cache\ProjectDescriptorMapper;
21
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
22
use phpDocumentor\Event\Dispatcher;
23
use phpDocumentor\Transformer\Event\PreTransformationEvent;
24
use phpDocumentor\Transformer\Event\PreTransformEvent;
25
use phpDocumentor\Transformer\Event\WriterInitializationEvent;
26
use phpDocumentor\Transformer\Transformer;
27
use phpDocumentor\Transformer\Writer\WriterAbstract;
28
use Psr\Log\LoggerInterface;
29
use Symfony\Component\Filesystem\Filesystem;
30
use Symfony\Component\Stopwatch\Stopwatch;
31
use Zend\Cache\Storage\StorageInterface;
32
33
/**
34
 * Transforms the structure file into the specified output format
35
 *
36
 * This task will execute the transformation rules described in the given
37
 * template (defaults to 'responsive') with the given source (defaults to
38
 * output/structure.xml) and writes these to the target location (defaults to
39
 * 'output').
40
 *
41
 * It is possible for the user to receive additional information using the
42
 * verbose option or stop additional information using the quiet option. Please
43
 * take note that the quiet option also disables logging to file.
44
 */
45
final class Transform
46
{
47
    /** @var ProjectDescriptorBuilder $builder Object containing the project meta-data and AST */
48
    private $builder;
49
50
    /** @var Transformer $transformer Principal object for guiding the transformation process */
51
    private $transformer;
52
53
    /** @var Compiler $compiler Collection of pre-transformation actions (Compiler Passes) */
54
    private $compiler;
55
56
    /** @var StorageInterface */
57
    private $cache;
58
59
    /** @var LoggerInterface */
60
    private $logger;
61
62
    /**
63
     * Initializes the command with all necessary dependencies to construct human-suitable output from the AST.
64
     */
65
    public function __construct(
66
        ProjectDescriptorBuilder $builder,
67
        Transformer $transformer,
68
        Compiler $compiler,
69
        StorageInterface $cache,
70
        LoggerInterface $logger
71
    ) {
72
        $this->builder = $builder;
73
        $this->transformer = $transformer;
74
        $this->compiler = $compiler;
75
        $this->cache = $cache;
76
        $this->logger = $logger;
77
78
        $this->connectOutputToEvents();
79
    }
80
81
    /**
82
     * Returns the builder object containing the AST and other meta-data.
83
     */
84
    private function getBuilder(): ProjectDescriptorBuilder
85
    {
86
        return $this->builder;
87
    }
88
89
    /**
90
     * Returns the transformer used to guide the transformation process from AST to output.
91
     */
92
    private function getTransformer(): Transformer
93
    {
94
        return $this->transformer;
95
    }
96
97
    /**
98
     * Executes the business logic involved with this command.
99
     *
100
     * @throws Exception if the target location is not a folder.
101
     */
102
    public function __invoke(array $configuration): int
103
    {
104
        $transformer = $this->getTransformer();
105
106
        $target = $configuration['phpdocumentor']['paths']['output']->getPath();
107
        $fileSystem = new Filesystem();
108
        if (! $fileSystem->isAbsolutePath((string) $target)) {
109
            $target = getcwd() . DIRECTORY_SEPARATOR . $target;
110
        }
111
112
        $transformer->setTarget((string) $target);
113
114
        $projectDescriptor = $this->getBuilder()->getProjectDescriptor();
115
        $mapper = new ProjectDescriptorMapper($this->getCache());
116
117
        $stopWatch = new Stopwatch();
118
        $stopWatch->start('cache');
119
        $mapper->populate($projectDescriptor);
120
        $stopWatch->stop('cache');
121
122
        foreach (array_column($configuration['phpdocumentor']['templates'], 'name') as $template) {
123
            $stopWatch->start('load template');
124
            $this->transformer->getTemplates()->load($template);
125
            $stopWatch->stop('load template');
126
        }
127
128
        /** @var \phpDocumentor\Compiler\CompilerPassInterface $pass */
129
        foreach ($this->compiler as $pass) {
130
            $pass->execute($projectDescriptor);
131
        }
132
133
        return 0;
134
    }
135
136
    private function getCache(): StorageInterface
137
    {
138
        return $this->cache;
139
    }
140
141
    /**
142
     * Connect a series of output messages to various events to display progress.
143
     */
144
    private function connectOutputToEvents(): void
145
    {
146
        Dispatcher::getInstance()->addListener(
147
            Transformer::EVENT_PRE_TRANSFORM,
148
            function (PreTransformEvent $event) {
149
                /** @var Transformer $transformer */
150
                $transformer = $event->getSubject();
151
                $templates = $transformer->getTemplates();
152
                $transformations = $templates->getTransformations();
153
                $this->logger->info(sprintf("\nApplying %d transformations", count($transformations)));
154
            }
155
        );
156
        Dispatcher::getInstance()->addListener(
157
            Transformer::EVENT_PRE_INITIALIZATION,
158
            function (WriterInitializationEvent $event) {
159
                if ($event->getWriter() instanceof WriterAbstract) {
160
                    $this->logger->info('  Initialize writer "' . get_class($event->getWriter()) . '"');
161
                }
162
            }
163
        );
164
        Dispatcher::getInstance()->addListener(
165
            Transformer::EVENT_PRE_TRANSFORMATION,
166
            function (PreTransformationEvent $event) {
167
                if ($event->getTransformation()->getWriter() instanceof WriterAbstract) {
168
                    $this->logger->info(
169
                        '  Execute transformation using writer "' . $event->getTransformation()->getWriter() . '"'
170
                    );
171
                }
172
            }
173
        );
174
    }
175
}
176