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