Passed
Push — master ( 4109cd...3773bc )
by Dev
13:23
created

StaticAppGenerator::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 9
dl 0
loc 29
rs 9.7666
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace PiedWeb\CMSBundle\StaticGenerator;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use PiedWeb\CMSBundle\Entity\PageInterface;
7
use PiedWeb\CMSBundle\Entity\PageInterface as Page;
8
use PiedWeb\CMSBundle\Repository\PageRepository;
9
use PiedWeb\CMSBundle\Service\AppConfigHelper;
10
use PiedWeb\CMSBundle\Service\AppConfigHelper as App;
11
use PiedWeb\CMSBundle\Service\PageCanonicalService as PageCanonical;
12
use PiedWeb\CMSBundle\Utils\KernelTrait;
13
use PiedWeb\CMSBundle\Utils\GenerateLivePathForTrait;
14
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
15
use Symfony\Component\Filesystem\Filesystem;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpKernel\KernelInterface;
20
use Symfony\Component\Routing\Router;
21
use Symfony\Component\Routing\RouterInterface;
22
use Symfony\Contracts\Translation\TranslatorInterface;
23
use Twig\Environment as Twig;
24
use WyriHaximus\HtmlCompress\Factory as HtmlCompressor;
25
use WyriHaximus\HtmlCompress\HtmlCompressorInterface;
26
27
/**
28
 * Generate 1 App.
29
 */
30
class StaticAppGenerator
31
{
32
    use KernelTrait, GenerateLivePathForTrait;
33
34
    /**
35
     * Contain files relative to SEO wich will be hard copied.
36
     *
37
     * @var array
38
     */
39
    protected $robotsFiles = ['robots.txt'];
40
41
    /**
42
     * @var array
43
     */
44
    protected $dontCopy = ['index.php', '.htaccess'];
45
46
    /**
47
     * @var EntityManagerInterface
48
     */
49
    protected $em;
50
51
    /**
52
     * @var Filesystem
53
     */
54
    protected $filesystem;
55
56
    /**
57
     * @var Twig
58
     */
59
    protected $twig;
60
61
    /**
62
     * @var string
63
     */
64
    protected $webDir;
65
66
    /**
67
     * @var array
68
     */
69
    protected $apps;
70
    protected $app;
71
    protected $staticDomain;
72
    protected $mustGetPagesWithoutHost = true;
73
74
    /** var @string */
75
    protected $staticDir;
76
77
    /**
78
     * @var RequestStack
79
     */
80
    protected $requesStack;
81
82
    /**
83
     * @var \PiedWeb\CMSBundle\Service\PageCanonicalService
84
     */
85
    protected $pageCanonical;
86
87
    /**
88
     * @var TranslatorInterface
89
     */
90
    protected $translator;
91
92
    /**
93
     * @var HtmlCompressorInterface
94
     */
95
    protected $parser;
96
97
    /**
98
     * @var ParameterBagInterface
99
     */
100
    protected $params;
101
102
    /**
103
     * @var RouterInterface
104
     */
105
    protected $router;
106
107
    /**
108
     * Used in .htaccess generation.
109
     *
110
     * @var string
111
     */
112
    protected $redirections = '';
113
114
    public function __construct(
115
        EntityManagerInterface $em,
116
        Twig $twig,
117
        ParameterBagInterface $params,
118
        RequestStack $requesStack,
119
        PageCanonical $pageCanonical,
120
        TranslatorInterface $translator,
121
        RouterInterface $router,
122
        string $webDir,
123
        KernelInterface $kernel
124
    ) {
125
        $this->em = $em;
126
        $this->filesystem = new Filesystem();
127
        $this->twig = $twig;
128
        $this->params = $params;
129
        $this->requesStack = $requesStack;
130
        $this->webDir = $webDir;
131
        $this->pageCanonical = $pageCanonical;
132
        $this->translator = $translator;
133
        $this->router = $router;
134
        $this->apps = $this->params->get('pwc.apps');
135
        $this->parser = HtmlCompressor::construct();
136
137
        if (!method_exists($this->filesystem, 'dumpFile')) {
138
            throw new \RuntimeException('Method dumpFile() is not available. Upgrade your Filesystem.');
139
        }
140
141
        static::loadKernel($kernel);
142
        $this->kernel = $kernel;
143
    }
144
145
    public function generateAll($filter = null)
146
    {
147
148
        foreach ($this->apps as $app) {
149
            if ($filter && !in_array($filter, $app->getHost())) {
150
                    continue;
151
            }
152
            $this->generate($app, $this->mustGetPagesWithoutHost);
153
            //$this->generateStaticApp($app);
154
155
            $this->mustGetPagesWithoutHost = false;
156
        }
157
    }
158
159
    public function generateFromHost($host)
160
    {
161
        return $this->generateAll($host);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->generateAll($host) targeting PiedWeb\CMSBundle\Static...enerator::generateAll() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
162
    }
163
164
    /**
165
     * Main Logic is here.
166
     *
167
     * @throws \RuntimeException
168
     * @throws \LogicException
169
     */
170
    public function generate($app, $mustGetPagesWithoutHost = false)
171
    {
172
        $this->app = new App($app['hosts'][0], [$app]);
173
        $this->mustGetPagesWithoutHost = $mustGetPagesWithoutHost;
174
175
        $this->filesystem->remove($this->app->getStaticDir());
176
        $this->generatePages();
177
        $this->generateSitemaps();
178
        $this->generateErrorPages();
179
        $this->copyRobotsFiles();
180
        $this->generateServerManagerFile();
181
        $this->copyAssets();
182
        $this->copyMediaToDownload();
183
    }
184
185
    /**
186
     * Symlink doesn't work on github page, symlink only for apache if conf say OK to symlink.
187
     */
188
    protected function mustSymlink()
189
    {
190
        return $this->app->get('static_generateForApache') ? $this->app->get('static_symlinkMedia') : false;
191
    }
192
193
    /**
194
     * Generate .htaccess for Apache or CNAME for github
195
     * Must be run after generatePages() !!
196
     */
197
    protected function generateServerManagerFile()
198
    {
199
        if ($this->app->get('static_generateForApache')) {
200
            $this->generateHtaccess();
201
        } else { //if ($this->app['static_generateForGithubPages'])) {
202
            $this->generateCname();
203
        }
204
    }
205
206
    /**
207
     * Copy files relative to SEO (robots, sitemaps, etc.).
208
     */
209
    protected function copyRobotsFiles(): void
210
    {
211
        array_map([$this, 'copy'], $this->robotsFiles);
212
    }
213
214
    // todo
215
    // docs
216
    // https://help.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site
217
    protected function generateCname()
218
    {
219
        $this->filesystem->dumpFile($this->app->getStaticDir().'/CNAME', $this->app->getMainHost());
220
    }
221
222
    protected function generateHtaccess()
223
    {
224
        $htaccess = $this->twig->render('@PiedWebCMS/static/htaccess.twig', [
225
            'domain' => $this->app->getMainHost(),
226
            'redirections' => $this->redirections,
227
        ]);
228
        $this->filesystem->dumpFile($this->app->getStaticDir().'/.htaccess', $htaccess);
229
    }
230
231
    protected function copy(string $file): void
232
    {
233
        if (file_exists($file)) {
234
            copy(
235
                str_replace($this->params->get('kernel.project_dir').'/', '../', $this->webDir.'/'.$file),
236
                $this->app->getStaticDir().'/'.$file
237
            );
238
        }
239
    }
240
241
    /**
242
     * Copy (or symlink) for all assets in public
243
     * (and media previously generated by liip in public).
244
     */
245
    protected function copyAssets(): void
246
    {
247
        $symlink = $this->mustSymlink();
248
249
        $dir = dir($this->webDir);
250
        while (false !== $entry = $dir->read()) {
251
            if ('.' == $entry || '..' == $entry) {
252
                continue;
253
            }
254
            if (!\in_array($entry, $this->robotsFiles) && !\in_array($entry, $this->dontCopy)) {
255
                //$this->symlink(
256
                if (true === $symlink) {
257
                    $this->filesystem->symlink(
258
                        str_replace($this->params->get('kernel.project_dir').'/', '../', $this->webDir.'/'.$entry),
259
                        $this->app->getStaticDir().'/'.$entry
260
                    );
261
                } else {
262
                    $action = is_file($this->webDir.'/'.$entry) ? 'copy' : 'mirror';
263
                    $this->filesystem->$action($this->webDir.'/'.$entry, $this->app->getStaticDir().'/'.$entry);
264
                }
265
            }
266
        }
267
        $dir->close();
268
    }
269
270
    /**
271
     * Copy or Symlink "not image" media to download folder.
272
     *
273
     * @return void
274
     */
275
    protected function copyMediaToDownload()
276
    {
277
        $symlink = $this->mustSymlink();
278
279
        if (!file_exists($this->app->getStaticDir().'/download')) {
280
            $this->filesystem->mkdir($this->app->getStaticDir().'/download/');
281
            $this->filesystem->mkdir($this->app->getStaticDir().'/download/media');
282
        }
283
284
        $dir = dir($this->webDir.'/../media');
285
        while (false !== $entry = $dir->read()) {
286
            if ('.' == $entry || '..' == $entry) {
287
                continue;
288
            }
289
            // if the file is an image, it's ever exist (maybe it's slow to check every files)
290
            if (!file_exists($this->webDir.'/media/default/'.$entry)) {
291
                if (true === $symlink) {
292
                    $this->filesystem->symlink('../../../media/'.$entry, $this->app->getStaticDir().'/download/media/'.$entry);
293
                } else {
294
                    $this->filesystem->copy(
295
                        $this->webDir.'/../media/'.$entry,
296
                        $this->app->getStaticDir().'/download/media/'.$entry
297
                    );
298
                }
299
            }
300
        }
301
302
        //$this->filesystem->$action($this->webDir.'/../media', $this->app->getStaticDir().'/download/media');
303
    }
304
305
    protected function generateSitemaps(): void
306
    {
307
        foreach (explode('|', $this->params->get('pwc.locales')) as $locale) {
308
309
            foreach (['txt', 'xml'] as $format) {
310
                $this->generateSitemap($locale, $format);
311
            }
312
313
            $this->generateFeed($locale);
314
        }
315
    }
316
317
    protected function generateSitemap($locale, $format)
318
    {
319
        $liveUri = $this->generateLivePathFor($this->app->getMainHost(), 'piedweb_cms_page_sitemap', ['locale'=>$locale, '_format'=>$format]);
320
        $staticFile = $this->app->getStaticDir().'/sitemap'.$locale.'.'.$format; // todo get it from URI removing host
321
        $this->saveAsStatic($liveUri, $staticFile);
322
323
        if ($this->params->get('locale') == $locale ? '' : '.'.$locale) {
324
            $staticFile = $this->app->getStaticDir().'/sitemap.'.$format;
325
            $this->saveAsStatic($liveUri, $staticFile);
326
        }
327
    }
328
329
    protected function generateFeed($locale)
330
    {
331
        $liveUri = $this->generateLivePathFor($this->app->getMainHost(), 'piedweb_cms_page_main_feed', ['locale'=>$locale]);
332
        $staticFile = $this->app->getStaticDir().'/feed'.$locale.'.xml';
333
        $this->saveAsStatic($liveUri, $staticFile);
334
335
        if ($this->params->get('locale') == $locale ? '' : '.'.$locale) {
336
            $staticFile = $this->app->getStaticDir().'/feed.xml';
337
            $this->saveAsStatic($liveUri, $staticFile);
338
        }
339
    }
340
341
    /**
342
     * The function cache redirection found during generatePages and
343
     * format in self::$redirection the content for the .htaccess.
344
     *
345
     * @return void
346
     */
347
    protected function addRedirection(Page $page)
348
    {
349
        $this->redirections .= 'Redirect ';
350
        $this->redirections .= $page->getRedirectionCode().' ';
351
        $this->redirections .= $this->pageCanonical->generatePathForPage($page->getRealSlug());
352
        $this->redirections .= ' '.$page->getRedirection();
353
        $this->redirections .= PHP_EOL;
354
    }
355
356
    protected function generatePages(): void
357
    {
358
        $qb = $this->getPageRepository()->getQueryToFindPublished('p');
359
        $qb = $this->getPageRepository()->andHost($qb, $this->app->getMainHost(), $this->mustGetPagesWithoutHost);
360
        $pages = $qb->getQuery()->getResult();
361
362
        foreach ($pages as $page) {
363
            $this->generatePage($page);
364
            //if ($page->getRealSlug()) $this->generateFeedFor($page);
365
        }
366
367
    }
368
369
    protected function generatePage(Page $page)
370
    {
371
        /**/
372
        // check if it's a redirection
373
        if (false !== $page->getRedirection()) {
374
            $this->addRedirection($page);
375
376
            return;
377
        }
378
        /**/
379
380
        $this->saveAsStatic($this->generateLivePathFor($page), $this->generateFilePath($page));
381
    }
382
383
    protected function saveAsStatic($liveUri, $destination)
384
    {
385
        $request = Request::create($liveUri);
386
387
        $response = static::$appKernel->handle($request);
388
389
        if ($response->isRedirect()) {
390
            // todo
391
            //$this->addRedirection($liveUri, getRedirectUri)
392
            return;
393
        }
394
        elseif (200 != $response->getStatusCode()) {
395
            //$this->kernel = static::$appKernel;
396
            if ($response->getStatusCode() === 500 && $this->kernel->getEnvironment() == 'dev')
397
                exit($this->kernel->handle($request));
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
398
399
            return;
400
        }
401
402
        $content = $this->compress($response->getContent());
403
        $this->filesystem->dumpFile($destination, $content);
404
    }
405
406
    protected function compress($html)
407
    {
408
        return $this->parser->compress($html);
409
    }
410
411
    protected function generateFilePath(Page $page)
412
    {
413
        $slug = '' == $page->getRealSlug() ? 'index' : $page->getRealSlug();
414
        $route = $this->pageCanonical->generatePathForPage($slug);
415
416
        return $this->app->getStaticDir().$route.'.html';
417
    }
418
419
    /**
420
     * Generate static file for feed indexing children pages
421
     * (only if children pages exists).
422
     *
423
     * @return void
424
     */
425
    protected function generateFeedFor(Page $page)
426
    {
427
        $liveUri = $this->generateLivePathFor($page, 'piedweb_cms_page_feed');
428
        $staticFile = preg_replace('/.html$/', '.xml', $this->generateFilePath($page));
429
        $this->saveAsStatic($liveUri, $staticFile);
430
    }
431
432
    protected function generateErrorPages(): void
433
    {
434
        $this->generateErrorPage();
435
436
        // todo i18n error in .htaccess
437
        $locales = explode('|', $this->params->get('pwc.locales'));
438
439
        foreach ($locales as $locale) {
440
            $this->filesystem->mkdir($this->app->getStaticDir().'/'.$locale);
441
            $this->generateErrorPage($locale);
442
        }
443
    }
444
445
    protected function generateErrorPage($locale = null, $uri = '404.html')
446
    {
447
        if (null !== $locale) {
448
            $request = new Request();
449
            $request->setLocale($locale);
450
            $this->requesStack->push($request);
451
        }
452
453
        $dump = $this->parser->compress($this->twig->render('@Twig/Exception/error.html.twig'));
454
        $this->filesystem->dumpFile($this->app->getStaticDir().(null !== $locale ? '/'.$locale : '').'/'.$uri, $dump);
455
    }
456
457
    protected function getPageRepository(): PageRepository
458
    {
459
        return $this->em->getRepository($this->params->get('pwc.entity_page'));
460
    }
461
}
462