Passed
Pull Request — master (#1877)
by Arnaud
12:13 queued 05:29
created

Twig::__construct()   C

Complexity

Conditions 16
Paths 160

Size

Total Lines 95
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 56
CRAP Score 16.0335

Importance

Changes 0
Metric Value
cc 16
eloc 56
nc 160
nop 2
dl 0
loc 95
ccs 56
cts 59
cp 0.9492
crap 16.0335
rs 5.0666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Cecil\Renderer;
15
16
use Cecil\Builder;
17
use Cecil\Exception\RuntimeException;
18
use Cecil\Renderer\Extension\Core as CoreExtension;
19
use Cecil\Util;
20
use Symfony\Bridge\Twig\Extension\TranslationExtension;
21
use Symfony\Component\Translation\Formatter\MessageFormatter;
22
use Symfony\Component\Translation\IdentityTranslator;
23
use Symfony\Component\Translation\Translator;
24
use Twig\Extra\Intl\IntlExtension;
25
26
/**
27
 * Class Twig.
28
 */
29
class Twig implements RendererInterface
30
{
31
    /** @var Builder */
32
    private $builder;
33
34
    /** @var \Twig\Environment */
35
    private $twig;
36
37
    /** @var Translator */
38
    private $translator = null;
39
40
    /** @var \Twig\Profiler\Profile */
41
    private $profile = null;
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 1
    public function __construct(Builder $builder, $templatesPath)
47
    {
48 1
        $this->builder = $builder;
49
        // load layouts
50 1
        $loader = new \Twig\Loader\FilesystemLoader($templatesPath);
51
        // default options
52 1
        $loaderOptions = [
53 1
            'debug'            => $this->builder->isDebug(),
54 1
            'strict_variables' => true,
55 1
            'autoescape'       => false,
56 1
            'auto_reload'      => true,
57 1
            'cache'            => false,
58 1
        ];
59
        // use Twig cache?
60 1
        if ((bool) $this->builder->getConfig()->get('cache.templates.enabled')) {
61 1
            $loaderOptions = array_replace($loaderOptions, ['cache' => $this->builder->getConfig()->getCacheTemplatesPath()]);
62
        }
63
        // create the Twig instance
64 1
        $this->twig = new \Twig\Environment($loader, $loaderOptions);
65
        // set date format
66 1
        $this->twig->getExtension(\Twig\Extension\CoreExtension::class)
67 1
            ->setDateFormat((string) $this->builder->getConfig()->get('date.format'));
68
        // set timezone
69 1
        if ($this->builder->getConfig()->has('date.timezone')) {
70
            $this->twig->getExtension(\Twig\Extension\CoreExtension::class)
71
                ->setTimezone((string) $this->builder->getConfig()->get('date.timezone') ?? date_default_timezone_get());
72
        }
73
        /*
74
         * adds extensions
75
         */
76
        // Cecil core extension
77 1
        $this->twig->addExtension(new CoreExtension($this->builder));
78
        // required by `template_from_string()`
79 1
        $this->twig->addExtension(new \Twig\Extension\StringLoaderExtension());
80
        // l10n
81 1
        $this->translator = new Translator(
82 1
            $this->builder->getConfig()->getLanguageProperty('locale'),
83 1
            new MessageFormatter(new IdentityTranslator()),
84 1
            (bool) $this->builder->getConfig()->get('cache.templates.enabled') ? $this->builder->getConfig()->getCacheTranslationsPath() : null,
85 1
            $this->builder->isDebug()
86 1
        );
87 1
        if (\count($this->builder->getConfig()->getLanguages()) > 0) {
88 1
            foreach ((array) $this->builder->getConfig()->get('layouts.translations.formats') as $format) {
89 1
                $loader = sprintf('Symfony\Component\Translation\Loader\%sFileLoader', ucfirst($format));
90 1
                if (class_exists($loader)) {
91 1
                    $this->translator->addLoader($format, new $loader());
92 1
                    $this->builder->getLogger()->debug(sprintf('Translation loader for format "%s" found', $format));
93
                }
94
            }
95 1
            foreach ($this->builder->getConfig()->getLanguages() as $lang) {
96
                // internal
97 1
                $this->addTransResource($this->builder->getConfig()->getTranslationsInternalPath(), $lang['locale']);
98
                // themes
99 1
                if ($themes = $this->builder->getConfig()->getTheme()) {
100 1
                    foreach ($themes as $theme) {
101 1
                        $this->addTransResource($this->builder->getConfig()->getThemeDirPath($theme, 'translations'), $lang['locale']);
102
                    }
103
                }
104
                // site
105 1
                $this->addTransResource($this->builder->getConfig()->getTranslationsPath(), $lang['locale']);
106
            }
107
        }
108 1
        $this->twig->addExtension(new TranslationExtension($this->translator));
109
        // intl
110 1
        $this->twig->addExtension(new IntlExtension());
111 1
        if (\extension_loaded('intl')) {
112 1
            $this->builder->getLogger()->debug('PHP Intl extension is loaded');
113
        }
114
        // filters fallback
115 1
        $this->twig->registerUndefinedFilterCallback(function ($name) {
116
            switch ($name) {
117 1
                case 'localizeddate':
118 1
                    return new \Twig\TwigFilter($name, function (\DateTime $value = null) {
119 1
                        return date($this->builder->getConfig()->get('date.format') ?? 'F j, Y', $value->getTimestamp());
0 ignored issues
show
Bug introduced by
The method getTimestamp() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
                        return date($this->builder->getConfig()->get('date.format') ?? 'F j, Y', $value->/** @scrutinizer ignore-call */ getTimestamp());

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.

Loading history...
120 1
                    });
121
            }
122
123
            return false;
124 1
        });
125
        // debug
126 1
        if ($this->builder->isDebug()) {
127
            // dump()
128 1
            $this->twig->addExtension(new \Twig\Extension\DebugExtension());
129
            // profiler
130 1
            $this->profile = new \Twig\Profiler\Profile();
131 1
            $this->twig->addExtension(new \Twig\Extension\ProfilerExtension($this->profile));
132
        }
133
        // loads custom extensions
134 1
        if ($this->builder->getConfig()->has('layouts.extensions')) {
135 1
            foreach ((array) $this->builder->getConfig()->get('layouts.extensions') as $name => $class) {
136
                try {
137 1
                    $this->twig->addExtension(new $class($this->builder));
138 1
                    $this->builder->getLogger()->debug(sprintf('Twig extension "%s" added', $name));
139 1
                } catch (\Exception | \Error $e) {
140 1
                    $this->builder->getLogger()->error(sprintf('Unable to add Twig extension "%s": %s', $class, $e->getMessage()));
141
                }
142
            }
143
        }
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149 1
    public function addGlobal(string $name, $value): void
150
    {
151 1
        $this->twig->addGlobal($name, $value);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 1
    public function render(string $template, array $variables): string
158
    {
159 1
        return $this->twig->render($template, $variables);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 1
    public function setLocale(string $locale): void
166
    {
167 1
        if (\extension_loaded('intl')) {
168 1
            \Locale::setDefault($locale);
169
        }
170 1
        $this->translator === null ?: $this->translator->setLocale($locale);
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 1
    public function addTransResource(string $translationsDir, string $locale): void
177
    {
178 1
        $locales = [$locale];
179
        // if locale is 'fr_FR', trying to load ['fr', 'fr_FR']
180 1
        if (\strlen($locale) > 2) {
181 1
            array_unshift($locales, substr($locale, 0, 2));
182
        }
183 1
        foreach ($locales as $locale) {
184 1
            foreach ((array) $this->builder->getConfig()->get('layouts.translations.formats') as $format) {
185 1
                $translationFile = Util::joinPath($translationsDir, sprintf('messages.%s.%s', $locale, $format));
186 1
                if (Util\File::getFS()->exists($translationFile)) {
187 1
                    $this->translator->addResource($format, $translationFile, $locale);
188 1
                    $this->builder->getLogger()->debug(sprintf('Translation file "%s" added', $translationFile));
189
                }
190
            }
191
        }
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 1
    public function getDebugProfile(): ?\Twig\Profiler\Profile
198
    {
199 1
        return $this->profile;
200
    }
201
}
202