Completed
Push — ezp25704-twig_1_23_deprecated_... ( b03955 )
by
unknown
46:18 queued 21:22
created

FieldRenderingExtension::initRuntime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 *
9
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\Core\MVC\Symfony\Templating\Twig\Extension;
12
13
use eZ\Publish\API\Repository\ContentTypeService;
14
use eZ\Publish\API\Repository\Values\Content\Content;
15
use eZ\Publish\API\Repository\Values\Content\Field;
16
use eZ\Publish\API\Repository\Values\ContentType\FieldDefinition;
17
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
18
use eZ\Publish\Core\Helper\TranslationHelper;
19
use eZ\Publish\Core\MVC\Symfony\FieldType\View\ParameterProviderRegistryInterface;
20
use eZ\Publish\Core\MVC\Symfony\Templating\FieldBlockRendererInterface;
21
use Twig_Environment;
22
use Twig_Extension;
23
use Twig_SimpleFunction;
24
25
/**
26
 * Twig extension for content fields/fieldDefinitions rendering (view and edit).
27
 */
28
class FieldRenderingExtension extends Twig_Extension
29
{
30
    /**
31
     * @var FieldBlockRendererInterface|\eZ\Publish\Core\MVC\Symfony\Templating\Twig\FieldBlockRenderer
32
     */
33
    private $fieldBlockRenderer;
34
35
    /**
36
     * @var ContentTypeService
37
     */
38
    private $contentTypeService;
39
40
    /**
41
     * @var ParameterProviderRegistryInterface
42
     */
43
    private $parameterProviderRegistry;
44
45
    /**
46
     * @var TranslationHelper
47
     */
48
    private $translationHelper;
49
50
    /**
51
     * Hash of field type identifiers (i.e. "ezstring"), indexed by field definition identifier.
52
     *
53
     * @var array
54
     */
55
    private $fieldTypeIdentifiers = [];
56
57
    public function __construct(
58
        FieldBlockRendererInterface $fieldBlockRenderer,
59
        ContentTypeService $contentTypeService,
60
        ParameterProviderRegistryInterface $parameterProviderRegistry,
61
        TranslationHelper $translationHelper
62
    ) {
63
        $this->fieldBlockRenderer = $fieldBlockRenderer;
0 ignored issues
show
Documentation Bug introduced by
$fieldBlockRenderer is of type object<eZ\Publish\Core\M...BlockRendererInterface>, but the property $fieldBlockRenderer was declared to be of type object<eZ\Publish\Core\M...wig\FieldBlockRenderer>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
64
        $this->contentTypeService = $contentTypeService;
65
        $this->parameterProviderRegistry = $parameterProviderRegistry;
66
        $this->translationHelper = $translationHelper;
67
    }
68
69
    public function getName()
70
    {
71
        return 'ezpublish.field_rendering';
72
    }
73
74
    public function getFunctions()
75
    {
76
        return array(
77
            new Twig_SimpleFunction(
78
                'ez_render_field',
79
                function(Twig_Environment $environment, Content $content, $fieldIdentifier, array $params = []) {
80
                    $this->fieldBlockRenderer->setTwig($environment);
81
                    return $this->renderField($content, $fieldIdentifier, $params);
82
                },
83
                ['is_safe' => ['html'], 'needs_environment' => true]
84
            ),
85
            new Twig_SimpleFunction(
86
                'ez_render_fielddefinition_settings',
87
                function(Twig_Environment $environment, FieldDefinition $fieldDefinition, array $params = []) {
88
                    $this->fieldBlockRenderer->setTwig($environment);
89
                    return $this->renderFieldDefinitionSettings($fieldDefinition, $params);
90
                },
91
                ['is_safe' => ['html'], 'needs_environment' => true]
92
            ),
93
        );
94
    }
95
96
    /**
97
     * Renders the HTML for the settings for the given field definition
98
     * $definition.
99
     *
100
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition $fieldDefinition
101
     *
102
     * @return string
103
     */
104
    public function renderFieldDefinitionSettings(FieldDefinition $fieldDefinition, array $params = [])
105
    {
106
        return $this->fieldBlockRenderer->renderFieldDefinitionView($fieldDefinition, $params);
107
    }
108
109
    /**
110
     * Renders the HTML for a given field.
111
     *
112
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
113
     * @param string $fieldIdentifier Identifier for the field we want to render
114
     * @param array $params An array of parameters to pass to the field view
115
     *
116
     * @return string The HTML markup
117
     *
118
     * @throws InvalidArgumentException
119
     */
120
    public function renderField(Content $content, $fieldIdentifier, array $params = [])
121
    {
122
        $field = $this->translationHelper->getTranslatedField($content, $fieldIdentifier, isset($params['lang']) ? $params['lang'] : null);
123 View Code Duplication
        if (!$field instanceof Field) {
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...
124
            throw new InvalidArgumentException(
125
                '$fieldIdentifier',
126
                "'{$fieldIdentifier}' field not present on content #{$content->contentInfo->id} '{$content->contentInfo->name}'"
127
            );
128
        }
129
130
        $params = $this->getRenderFieldBlockParameters($content, $field, $params);
131
        $fieldTypeIdentifier = $this->getFieldTypeIdentifier($content, $field);
132
133
        return $this->fieldBlockRenderer->renderContentFieldView($field, $fieldTypeIdentifier, $params);
134
    }
135
136
    /**
137
     * Generates the array of parameter to pass to the field template.
138
     *
139
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
140
     * @param \eZ\Publish\API\Repository\Values\Content\Field $field the Field to display
141
     * @param array $params An array of parameters to pass to the field view
142
     *
143
     * @return array
144
     */
145
    private function getRenderFieldBlockParameters(Content $content, Field $field, array $params = [])
146
    {
147
        // Merging passed parameters to default ones
148
        $params += [
149
            'parameters' => [], // parameters dedicated to template processing
150
            'attr' => [], // attributes to add on the enclosing HTML tags
151
        ];
152
153
        $versionInfo = $content->getVersionInfo();
154
        $contentInfo = $versionInfo->getContentInfo();
155
        $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId);
156
        $fieldDefinition = $contentType->getFieldDefinition($field->fieldDefIdentifier);
157
        // Adding Field, FieldSettings and ContentInfo objects to
158
        // parameters to be passed to the template
159
        $params += [
160
            'field' => $field,
161
            'content' => $content,
162
            'contentInfo' => $contentInfo,
163
            'versionInfo' => $versionInfo,
164
            'fieldSettings' => $fieldDefinition->getFieldSettings(),
165
        ];
166
167
        // Adding field type specific parameters if any.
168
        if ($this->parameterProviderRegistry->hasParameterProvider($fieldDefinition->fieldTypeIdentifier)) {
169
            $params['parameters'] += $this->parameterProviderRegistry
170
                ->getParameterProvider($fieldDefinition->fieldTypeIdentifier)
171
                ->getViewParameters($field);
172
        }
173
174
        // make sure we can easily add class="<fieldtypeidentifier>-field" to the
175
        // generated HTML
176
        if (isset($params['attr']['class'])) {
177
            $params['attr']['class'] .= ' ' . $this->getFieldTypeIdentifier($content, $field) . '-field';
178
        } else {
179
            $params['attr']['class'] = $this->getFieldTypeIdentifier($content, $field) . '-field';
180
        }
181
182
        return $params;
183
    }
184
185
    /**
186
     * Returns the field type identifier for $field.
187
     *
188
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
189
     * @param \eZ\Publish\API\Repository\Values\Content\Field $field
190
     *
191
     * @return string
192
     */
193
    private function getFieldTypeIdentifier(Content $content, Field $field)
194
    {
195
        $contentInfo = $content->getVersionInfo()->getContentInfo();
196
        $key = $contentInfo->contentTypeId . '  ' . $field->fieldDefIdentifier;
197
198
        if (!isset($this->fieldTypeIdentifiers[$key])) {
199
            $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId);
200
            $this->fieldTypeIdentifiers[$key] = $contentType
201
                ->getFieldDefinition($field->fieldDefIdentifier)
202
                ->fieldTypeIdentifier;
203
        }
204
205
        return $this->fieldTypeIdentifiers[$key];
206
    }
207
}
208