Completed
Pull Request — master (#10)
by Tomáš
04:48 queued 01:50
created

TwigFormatter   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 6
dl 0
loc 94
ccs 0
cts 55
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A formatBlocks() 0 20 4
A findAllBlocks() 0 8 2
A formatPage() 0 15 2
A massageTemplate() 0 17 3
1
<?php
2
3
/*
4
 * This file is a part of Sculpin.
5
 *
6
 * (c) Dragonfly Development Inc.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symplify\PHP7_Sculpin\TwigBundle;
13
14
use Symplify\PHP7_Sculpin\Formatter\FormatContext;
15
use Symplify\PHP7_Sculpin\Formatter\FormatterInterface;
16
17
final class TwigFormatter implements FormatterInterface
18
{
19
    /**
20
     * @var \Twig_Environment
21
     */
22
    private $twig;
23
24
    /**
25
     * @var \Twig_Loader_Array
26
     */
27
    private $arrayLoader;
28
29
    /**
30
     * Constructor.
31
     *
32
     * @param \Twig_Environment  $twig        Twig
33
     * @param \Twig_Loader_Array $arrayLoader Array Loader
34
     */
35
    public function __construct(\Twig_Environment $twig, \Twig_Loader_Array $arrayLoader)
36
    {
37
        $this->twig = $twig;
38
        $this->arrayLoader = $arrayLoader;
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function formatBlocks(FormatContext $formatContext) : array
45
    {
46
        try {
47
            $this->arrayLoader->setTemplate($formatContext->templateId(), $this->massageTemplate($formatContext));
48
            $data = $formatContext->data()->export();
49
            $template = $this->twig->loadTemplate($formatContext->templateId());
50
51
            if (!count($blockNames = $this->findAllBlocks($template, $data))) {
0 ignored issues
show
Compatibility introduced by
$template of type object<Twig_TemplateInterface> is not a sub-type of object<Twig_Template>. It seems like you assume a concrete implementation of the interface Twig_TemplateInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
52
                return ['content' => $template->render($data)];
53
            }
54
            $blocks = [];
55
            foreach ($blockNames as $blockName) {
56
                $blocks[$blockName] = $template->renderBlock($blockName, $data);
0 ignored issues
show
Bug introduced by
The method renderBlock() does not exist on Twig_TemplateInterface. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
57
            }
58
59
            return $blocks;
60
        } catch (\Exception $e) {
61
            echo ' [ '.get_class($e).': '.$e->getMessage()." ]\n";
62
        }
63
    }
64
65
    public function findAllBlocks(\Twig_Template $template, array $context)
66
    {
67
        if (false !== $parent = $template->getParent($context)) {
68
            return array_unique(array_merge($this->findAllBlocks($parent, $context), $template->getBlockNames()));
0 ignored issues
show
Compatibility introduced by
$parent of type object<Twig_TemplateInterface> is not a sub-type of object<Twig_Template>. It seems like you assume a concrete implementation of the interface Twig_TemplateInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
69
        }
70
71
        return $template->getBlockNames();
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function formatPage(FormatContext $formatContext) : string
78
    {
79
        try {
80
            $this->arrayLoader->setTemplate(
81
                $formatContext->templateId(),
82
                $this->massageTemplate($formatContext)
83
            );
84
85
            $data = $formatContext->data()->export();
86
87
            return $this->twig->render($formatContext->templateId(), $data);
88
        } catch (\Exception $e) {
89
            echo ' [ '.get_class($e).': '.$e->getMessage()." ]\n";
90
        }
91
    }
92
93
    private function massageTemplate(FormatContext $formatContext)
94
    {
95
        $template = $formatContext->template();
96
        if ($layout = $formatContext->data()->get('layout')) {
97
            // Completely remove anything in verbatim sections so that any blocks defined in there will
98
            // not trigger the "you've already defined blocks!" check since this is almost certainly
99
            // NOT the intention of the source's author.
100
            $verbatim = preg_replace('/{%\s+verbatim\s+%}(.*?){%\s+endverbatim\s+%}/si', '', $template);
101
102
            if (!preg_match_all('/{%\s+block\s+(\w+)\s+%}(.*?){%\s+endblock\s+%}/si', $verbatim, $matches)) {
103
                $template = '{% block content %}'.$template.'{% endblock %}';
104
            }
105
            $template = '{% extends "'.$layout.'" %}'.$template;
106
        }
107
108
        return $template;
109
    }
110
}
111