Completed
Pull Request — master (#41)
by Vladimir
02:29
created

Website::isNoClean()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
namespace allejo\stakx\Object;
4
5
use allejo\stakx\Core\StakxLogger;
6
use allejo\stakx\Manager\AssetManager;
7
use allejo\stakx\Manager\MenuManager;
8
use allejo\stakx\Manager\PageManager;
9
use allejo\stakx\Manager\ThemeManager;
10
use allejo\stakx\System\FileExplorer;
11
use allejo\stakx\System\Filesystem;
12
use allejo\stakx\Manager\CollectionManager;
13
use allejo\stakx\Manager\DataManager;
14
use allejo\stakx\System\Folder;
15
use JasonLewis\ResourceWatcher\Event;
16
use JasonLewis\ResourceWatcher\Resource\FileResource;
17
use JasonLewis\ResourceWatcher\Tracker;
18
use JasonLewis\ResourceWatcher\Watcher;
19
use Symfony\Component\Console\Output\OutputInterface;
20
21
class Website
22
{
23
    /**
24
     * The location of where the compiled website will be written to
25
     *
26
     * @var Folder
27
     */
28
    private $outputDirectory;
29
30
    /**
31
     * The main configuration to be used to build the specified website
32
     *
33
     * @var Configuration
34
     */
35
    private $configuration;
36
37
    /**
38
     * When set to true, the Stakx website will be built without a configuration file
39
     *
40
     * @var bool
41
     */
42
    private $confLess;
43
44
    /**
45
     * When set to true, Twig templates will not have access to filters or functions which provide access to the
46
     * filesystem
47
     *
48
     * @var bool
49
     */
50
    private $safeMode;
51
52
    /**
53
     * When set to true, Stakx will not clean the _site folder after a rebuild
54
     *
55
     * @var bool
56
     */
57
    private $noClean;
58
59
    /**
60
     * @var StakxLogger
61
     */
62
    private $output;
63
64
    /**
65
     * @var AssetManager
66
     */
67
    private $am;
68
69
    /**
70
     * @var CollectionManager
71
     */
72
    private $cm;
73
74
    /**
75
     * @var DataManager
76
     */
77
    private $dm;
78
79
    /**
80
     * @var Filesystem
81
     */
82
    private $fs;
83
84
    /** @var MenuManager */
85
    private $mm;
86
87
    /**
88
     * @var PageManager
89
     */
90
    private $pm;
91
92
    /**
93
     * @var ThemeManager
94
     */
95
    private $tm;
96
97
    /**
98
     * Website constructor.
99
     *
100
     * @param OutputInterface $output
101
     */
102
    public function __construct (OutputInterface $output)
103
    {
104
        $this->output = new StakxLogger($output);
105
        $this->cm = new CollectionManager();
106
        $this->dm = new DataManager();
107
        $this->mm = new MenuManager();
108
        $this->pm = new PageManager();
109
        $this->fs = new Filesystem();
110
    }
111
112
    /**
113
     * Compile the website.
114
     *
115
     * @param bool $tracking Whether or not to keep track of files as they're compiled to save time in 'watch'
116
     */
117
    public function build ($tracking = false)
118
    {
119
        // Configure the environment
120
        $this->createFolderStructure(!$this->noClean);
121
122
        // Our output directory
123
        $this->outputDirectory = new Folder($this->getConfiguration()->getTargetFolder());
124
        $this->outputDirectory->setTargetDirectory($this->getConfiguration()->getBaseUrl());
125
126
        // Parse DataItems
127
        $this->dm->setLogger($this->output);
128
        $this->dm->enableTracking($tracking);
129
        $this->dm->parseDataItems($this->getConfiguration()->getDataFolders());
130
        $this->dm->parseDataSets($this->getConfiguration()->getDataSets());
131
132
        // Prepare Collections
133
        $this->cm->setLogger($this->output);
134
        $this->cm->enableTracking($tracking);
135
        $this->cm->parseCollections($this->getConfiguration()->getCollectionsFolders());
136
137
        // Handle PageViews
138
        $this->pm->setLogger($this->output);
139
        $this->pm->enableTracking($tracking);
140
        $this->pm->setTargetFolder($this->outputDirectory);
141
        $this->pm->setCollections($this->cm->getCollections());
142
        $this->pm->setRedirectTemplate($this->getConfiguration()->getRedirectTemplate());
143
        $this->pm->parsePageViews($this->getConfiguration()->getPageViewFolders());
144
145
        $this->mm->setLogger($this->output);
146
        $this->mm->buildFromPageViews($this->pm->getStaticPages());
147
148
        $this->pm->configureTwig($this->getConfiguration(), array(
149
            'safe'    => $this->safeMode,
150
            'globals' => array(
151
                array('name' => 'site',        'value' => $this->getConfiguration()->getConfiguration()),
152
                array('name' => 'collections', 'value' => $this->cm->getJailedCollections()),
153
                array('name' => 'menu',        'value' => $this->mm->getSiteMenu()),
154
                array('name' => 'pages',       'value' => $this->pm->getJailedStaticPages()),
155
                array('name' => 'data',        'value' => $this->dm->getDataItems())
156
            )
157
        ));
158
        $this->pm->compileAll();
159
160
        // At this point, we are looking at static files to copy over meaning we need to ignore all of the files that
161
        // make up the source of a stakx website
162
        $assetsToIgnore = array_merge(
163
            Configuration::$stakxSourceFiles,
164
            $this->getConfiguration()->getExcludes()
165
        );
166
167
        //
168
        // Theme Management
169
        //
170
        $theme = $this->configuration->getTheme();
171
172
        if (!is_null($theme))
173
        {
174
            $this->output->notice("Looking for '${theme}' theme...");
175
176
            $this->tm = new ThemeManager($theme);
177
            $this->tm->configureFinder($this->getConfiguration()->getIncludes(), $assetsToIgnore);
178
            $this->tm->setLogger($this->output);
179
            $this->tm->enableTracking($tracking);
180
            $this->tm->setFolder($this->outputDirectory);
181
            $this->tm->copyFiles();
182
        }
183
184
        //
185
        // Static file management
186
        //
187
        $this->am = new AssetManager();
188
        $this->am->configureFinder($this->getConfiguration()->getIncludes(), $assetsToIgnore);
189
        $this->am->setLogger($this->output);
190
        $this->am->setFolder($this->outputDirectory);
191
        $this->am->enableTracking($tracking);
192
        $this->am->copyFiles();
193
    }
194
195
    public function watch ()
196
    {
197
        $this->output->writeln('Building website...');
198
        $this->build(true);
199
        $this->output->writeln(sprintf('Watching %s', getcwd()));
200
201
        $fileExplorer = FileExplorer::create(
202
            getcwd(),
203
            array_merge($this->getConfiguration()->getExcludes(), array(
204
                $this->getConfiguration()->getTargetFolder()
205
            )),
206
            $this->getConfiguration()->getIncludes()
207
        );
208
        $tracker    = new Tracker();
209
        $watcher    = new Watcher($tracker, $this->fs);
210
        $listener   = $watcher->watch(getcwd(), $fileExplorer->getExplorer());
211
        $targetPath = $this->getConfiguration()->getTargetFolder();
212
213
        $this->output->writeln('Watch started successfully');
214
215
        $listener->onAnything(function (Event $event, FileResource $resouce, $path) use ($targetPath)
216
        {
217
            $filePath = $this->fs->getRelativePath($path);
218
219
            try
220
            {
221
                switch ($event->getCode())
222
                {
223
                    case Event::RESOURCE_CREATED:
224
                        $this->creationWatcher($filePath);
225
                        break;
226
227
                    case Event::RESOURCE_MODIFIED:
228
                        $this->modificationWatcher($filePath);
229
                        break;
230
                }
231
            }
232
            catch (\Exception $e)
233
            {
234
                $this->output->error(sprintf("Your website failed to build with the following error: %s",
235
                    $e->getMessage()
236
                ));
237
            }
238
        });
239
240
        $watcher->start();
241
    }
242
243
    /**
244
     * @return Configuration
245
     */
246
    public function getConfiguration ()
247
    {
248
        return $this->configuration;
249
    }
250
251
    /**
252
     * @param string $configFile
253
     *
254
     * @throws \LogicException
255
     */
256
    public function setConfiguration ($configFile)
257
    {
258
        if (!$this->fs->exists($configFile) && !$this->isConfLess())
259
        {
260
            $this->output->error("You are trying to build a website in a directory without a configuration file. Is this what you meant to do?");
261
            $this->output->error("To build a website without a configuration, use the '--no-conf' option");
262
263
            throw new \LogicException("Cannot build a website without a configuration when not in Configuration-less mode");
264
        }
265
266
        if ($this->isConfLess())
267
        {
268
            $configFile = "";
269
        }
270
271
        $this->configuration = new Configuration();
272
        $this->configuration->setLogger($this->output);
273
        $this->configuration->parseConfiguration($configFile);
274
    }
275
276
    /**
277
     * Get whether or not the website is being built in Configuration-less mode
278
     *
279
     * @return bool True when being built with no configuration file
280
     */
281
    public function isConfLess ()
282
    {
283
        return $this->confLess;
284
    }
285
286
    /**
287
     * Set whether or not the website should be built with a configuration
288
     *
289
     * @param bool $status True when a website should be built without a configuration
290
     */
291
    public function setConfLess ($status)
292
    {
293
        $this->confLess = $status;
294
    }
295
296
    /**
297
     * Get whether or not the website is being built in safe mode.
298
     *
299
     * Safe mode is defined as disabling file system access from Twig and disabling user Twig extensions
300
     *
301
     * @return bool True when the website is being built in safe mode
302
     */
303
    public function isSafeMode ()
304
    {
305
        return $this->safeMode;
306
    }
307
308
    /**
309
     * Set whether a website should be built in safe mode
310
     *
311
     * @param bool $bool True if a website should be built in safe mode
312
     */
313
    public function setSafeMode ($bool)
314
    {
315
        $this->safeMode = $bool;
316
    }
317
318
    /**
319
     * @return boolean
320
     */
321
    public function isNoClean()
322
    {
323
        return $this->noClean;
324
    }
325
326
    /**
327
     * @param boolean $noClean
328
     */
329
    public function setNoClean($noClean)
330
    {
331
        $this->noClean = $noClean;
332
    }
333
334
    private function creationWatcher ($filePath)
335
    {
336
        $this->output->writeln(sprintf("File creation detected: %s", $filePath));
337
338
        if ($this->pm->isHandled($filePath))
339
        {
340
            $this->pm->createNewItem($filePath);
341
            $this->pm->refreshItem($filePath);
342
        }
343
        else if ($this->cm->isHandled($filePath))
344
        {
345
            $contentItem = $this->cm->createNewItem($filePath);
346
347
            $this->pm->updateTwigVariable('collections', $this->cm->getCollections());
0 ignored issues
show
Documentation introduced by
$this->cm->getCollections() is of type array<integer,array<inte...x\Object\ContentItem>>>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
348
            $this->pm->updatePageView($contentItem);
349
            $this->pm->compileContentItem($contentItem);
350
            $this->pm->compileSome(array(
351
                'namespace' => 'collections',
352
                'dependency' => $contentItem->getCollection()
353
            ));
354
        }
355 View Code Duplication
        else if ($this->dm->isHandled($filePath))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
356
        {
357
            $change = $this->dm->createNewItem($filePath);
358
359
            $this->pm->updateTwigVariable('data', $this->dm->getDataItems());
0 ignored issues
show
Documentation introduced by
$this->dm->getDataItems() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
360
            $this->pm->compileSome(array(
361
                'namespace' => 'data',
362
                'dependency' => $change
363
            ));
364
        }
365
        else if (!is_null($this->tm) && $this->tm->isHandled($filePath))
366
        {
367
            $this->tm->createNewItem($filePath);
368
        }
369
        else if ($this->am->isHandled($filePath))
370
        {
371
            $this->am->createNewItem($filePath);
372
        }
373
    }
374
375
    private function modificationWatcher ($filePath)
376
    {
377
        $this->output->writeln(sprintf("File change detected: %s", $filePath));
378
379
        if ($this->pm->isTracked($filePath))
380
        {
381
            $this->pm->refreshItem($filePath);
382
        }
383
        else if ($this->cm->isTracked($filePath))
384
        {
385
            $contentItem = &$this->cm->getContentItem($filePath);
386
            $contentItem->refreshFileContent();
387
388
            $this->pm->compileContentItem($contentItem);
389
            $this->pm->compileSome(array(
390
                'namespace' => 'collections',
391
                'dependency' => $contentItem->getCollection()
392
            ));
393
        }
394 View Code Duplication
        else if ($this->dm->isTracked($filePath))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
395
        {
396
            $change = $this->dm->refreshItem($filePath);
397
398
            $this->pm->updateTwigVariable('data', $this->dm->getDataItems());
0 ignored issues
show
Documentation introduced by
$this->dm->getDataItems() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
399
            $this->pm->compileSome(array(
400
                'namespace' => 'data',
401
                'dependency' => $change
402
            ));
403
        }
404
        else if (!is_null($this->tm) && $this->tm->isTracked($filePath))
405
        {
406
            $this->tm->refreshItem($filePath);
407
        }
408
        else if ($this->am->isTracked($filePath))
409
        {
410
            $this->am->refreshItem($filePath);
411
        }
412
    }
413
414
    /**
415
     * Prepare the Stakx environment by creating necessary cache folders
416
     *
417
     * @param bool $cleanDirectory Clean the target directory
418
     */
419
    private function createFolderStructure ($cleanDirectory)
420
    {
421
        $tarDir = $this->fs->absolutePath($this->configuration->getTargetFolder());
422
423
        if ($cleanDirectory)
424
        {
425
            $this->fs->remove($tarDir);
426
        }
427
428
        $this->fs->remove($this->fs->absolutePath('.stakx-cache'));
429
        $this->fs->mkdir($this->fs->absolutePath('.stakx-cache/twig'));
430
        $this->fs->mkdir($tarDir);
431
    }
432
}