1 | <?php |
||||
2 | |||||
3 | namespace DNADesign\Elemental\Forms; |
||||
4 | |||||
5 | use BlocksPage; |
||||
0 ignored issues
–
show
|
|||||
6 | use DNADesign\Elemental\Controllers\ElementalAreaController; |
||||
7 | use DNADesign\Elemental\Models\BaseElement; |
||||
8 | use DNADesign\Elemental\Models\ElementalArea; |
||||
9 | use DNADesign\Elemental\Services\ElementTabProvider; |
||||
10 | use SilverStripe\Control\Controller; |
||||
11 | use SilverStripe\Core\Config\Config; |
||||
12 | use SilverStripe\Core\Injector\Injector; |
||||
13 | use SilverStripe\Forms\CompositeField; |
||||
14 | use SilverStripe\Forms\FieldGroup; |
||||
15 | use SilverStripe\Forms\FieldList; |
||||
16 | use SilverStripe\Forms\FormField; |
||||
17 | use SilverStripe\Forms\GridField\GridField; |
||||
18 | use SilverStripe\Forms\TabSet; |
||||
19 | use SilverStripe\ORM\DataObjectInterface; |
||||
20 | use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass; |
||||
21 | |||||
22 | class ElementalAreaField extends GridField |
||||
23 | { |
||||
24 | /** |
||||
25 | * @var ElementalArea $area |
||||
26 | */ |
||||
27 | protected $area; |
||||
28 | |||||
29 | /** |
||||
30 | * @var array $type |
||||
31 | */ |
||||
32 | protected $types = []; |
||||
33 | |||||
34 | /** |
||||
35 | * @var null |
||||
36 | */ |
||||
37 | protected $inputType = null; |
||||
38 | |||||
39 | protected $modelClassName = BaseElement::class; |
||||
40 | |||||
41 | /** |
||||
42 | * @param string $name |
||||
43 | * @param ElementalArea $area |
||||
44 | * @param string[] $blockTypes |
||||
45 | */ |
||||
46 | public function __construct($name, ElementalArea $area, array $blockTypes) |
||||
47 | { |
||||
48 | $this->setTypes($blockTypes); |
||||
49 | |||||
50 | $config = new ElementalAreaConfig(); |
||||
51 | |||||
52 | if (!empty($blockTypes)) { |
||||
53 | /** @var GridFieldAddNewMultiClass $adder */ |
||||
54 | $adder = Injector::inst()->create(GridFieldAddNewMultiClass::class); |
||||
55 | $adder->setClasses($blockTypes); |
||||
56 | $config->addComponent($adder); |
||||
57 | } |
||||
58 | |||||
59 | // By default, no need for a title on the editor. If there is more than one area then use `setTitle` to describe |
||||
60 | parent::__construct($name, '', $area->Elements(), $config); |
||||
0 ignored issues
–
show
It seems like
$area->Elements() can also be of type DNADesign\Elemental\Models\BaseElement[] ; however, parameter $dataList of SilverStripe\Forms\GridF...ridField::__construct() does only seem to accept SilverStripe\ORM\SS_List|null , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
61 | $this->area = $area; |
||||
62 | |||||
63 | $this->addExtraClass('element-editor__container no-change-track'); |
||||
64 | } |
||||
65 | |||||
66 | /** |
||||
67 | * @param array $types |
||||
68 | * |
||||
69 | * @return $this |
||||
70 | */ |
||||
71 | public function setTypes($types) |
||||
72 | { |
||||
73 | $this->types = $types; |
||||
74 | |||||
75 | return $this; |
||||
76 | } |
||||
77 | |||||
78 | /** |
||||
79 | * @return array |
||||
80 | */ |
||||
81 | public function getTypes() |
||||
82 | { |
||||
83 | $types = $this->types; |
||||
84 | |||||
85 | $this->extend('updateGetTypes', $types); |
||||
86 | |||||
87 | return $types; |
||||
88 | } |
||||
89 | |||||
90 | /** |
||||
91 | * @return ElementalArea |
||||
92 | */ |
||||
93 | public function getArea() |
||||
94 | { |
||||
95 | return $this->area; |
||||
96 | } |
||||
97 | |||||
98 | /** |
||||
99 | * Overloaded to skip GridField implementation - this is copied from FormField. |
||||
100 | * |
||||
101 | * @param array $properties |
||||
102 | * @return \SilverStripe\ORM\FieldType\DBHTMLText|string |
||||
103 | */ |
||||
104 | public function FieldHolder($properties = array()) |
||||
105 | { |
||||
106 | $context = $this; |
||||
107 | |||||
108 | if (count($properties)) { |
||||
109 | $context = $this->customise($properties); |
||||
110 | } |
||||
111 | |||||
112 | return $context->renderWith($this->getFieldHolderTemplates()); |
||||
113 | } |
||||
114 | |||||
115 | public function getSchemaDataDefaults() |
||||
116 | { |
||||
117 | $schemaData = parent::getSchemaDataDefaults(); |
||||
118 | |||||
119 | $area = $this->getArea(); |
||||
120 | $pageId = ($area && ($page = $area->getOwnerPage())) ? $page->ID : null; |
||||
121 | $schemaData['page-id'] = $pageId; |
||||
122 | $schemaData['elemental-area-id'] = $area ? (int) $area->ID : null; |
||||
123 | |||||
124 | $allowedTypes = $this->getTypes(); |
||||
125 | $schemaData['allowed-elements'] = array_keys($allowedTypes); |
||||
126 | |||||
127 | return $schemaData; |
||||
128 | } |
||||
129 | |||||
130 | /** |
||||
131 | * A getter method that seems redundant in that it is a function that returns a function, |
||||
132 | * however the returned closure is used in an array map function to return a complete FieldList |
||||
133 | * representing a read only view of the element passed in (to the closure). |
||||
134 | * |
||||
135 | * @return callable |
||||
136 | */ |
||||
137 | protected function getReadOnlyBlockReducer() |
||||
138 | { |
||||
139 | return function (BaseElement $element) { |
||||
140 | $parentName = 'Element' . $element->ID; |
||||
141 | $elementFields = $element->getCMSFields(); |
||||
142 | |||||
143 | // Obtain highest impact fields for a summary (e.g. Title & Content) |
||||
144 | foreach ($elementFields as $field) { |
||||
145 | if (is_object($field) && $field instanceof TabSet) { |
||||
146 | // Assign the fields of the first Tab in the TabSet - most regularly 'Root.Main' |
||||
147 | $elementFields = $field->FieldList()->first()->FieldList(); |
||||
148 | break; |
||||
149 | } |
||||
150 | } |
||||
151 | |||||
152 | // Set values (before names don't match anymore) |
||||
153 | $elementFields->setValues($element->getQueriedDatabaseFields()); |
||||
154 | |||||
155 | // Combine into an appropriately named group |
||||
156 | $elementGroup = FieldGroup::create($elementFields); |
||||
157 | $elementGroup->setForm($this->getForm()); |
||||
158 | $elementGroup->setName($parentName); |
||||
159 | $elementGroup->addExtraClass('elemental-area__element--historic'); |
||||
160 | |||||
161 | // Also set the important data for the rendering Component |
||||
162 | $elementGroup->setSchemaData([ |
||||
163 | 'data' => [ |
||||
164 | 'ElementID' => $element->ID, |
||||
165 | 'ElementType' => $element->getType(), |
||||
166 | 'ElementIcon' => $element->config()->icon, |
||||
167 | 'ElementTitle' => $element->Title, |
||||
168 | // @todo: Change this to block history permalink when that functionality becomes available. |
||||
169 | 'ElementEditLink' => $element->CMSEditLink() |
||||
170 | ] |
||||
171 | ]); |
||||
172 | |||||
173 | return $elementGroup; |
||||
174 | }; |
||||
175 | } |
||||
176 | |||||
177 | /** |
||||
178 | * Provides a readonly representation of the GridField (superclass) Uses a reducer |
||||
179 | * {@see ElementalAreaField::getReadOnlyBlockReducer()} to fetch a read only representation of the listed class |
||||
180 | * {@see GridField::getModelClass()} |
||||
181 | * |
||||
182 | * @return CompositeField |
||||
183 | */ |
||||
184 | public function performReadonlyTransformation() |
||||
185 | { |
||||
186 | /** @var CompositeField $readOnlyField */ |
||||
187 | $readOnlyField = $this->castedCopy(CompositeField::class); |
||||
188 | $blockReducer = $this->getReadOnlyBlockReducer(); |
||||
189 | $readOnlyField->setChildren( |
||||
190 | FieldList::create(array_map($blockReducer, $this->getArea()->Elements()->toArray())) |
||||
191 | ); |
||||
192 | |||||
193 | $readOnlyField = $readOnlyField->performReadonlyTransformation(); |
||||
194 | |||||
195 | // Ensure field names are unique between elements on parent form but only after transformations have been |
||||
196 | // performed |
||||
197 | /** @var FieldGroup $elementForm */ |
||||
198 | foreach ($readOnlyField->getChildren() as $elementForm) { |
||||
199 | $parentName = $elementForm->getName(); |
||||
200 | $elementForm->getChildren()->recursiveWalk(function (FormField $field) use ($parentName) { |
||||
201 | $field->setName($parentName . '_' . $field->getName()); |
||||
202 | }); |
||||
203 | } |
||||
204 | |||||
205 | return $readOnlyField |
||||
206 | ->setReadOnly(true) |
||||
207 | ->setName($this->getName()) |
||||
208 | ->addExtraClass('elemental-area--read-only'); |
||||
209 | } |
||||
210 | |||||
211 | public function setSubmittedValue($value, $data = null) |
||||
212 | { |
||||
213 | // Content comes through as a JSON encoded list through a hidden field. |
||||
214 | return $this->setValue(json_decode($value, true)); |
||||
215 | } |
||||
216 | |||||
217 | public function saveInto(DataObjectInterface $dataObject) |
||||
218 | { |
||||
219 | /** @var BlocksPage $dataObject */ |
||||
220 | parent::saveInto($dataObject); |
||||
221 | |||||
222 | $elementData = $this->Value(); |
||||
223 | $idPrefixLength = strlen(sprintf(ElementalAreaController::FORM_NAME_TEMPLATE, '')); |
||||
224 | |||||
225 | if (!$elementData) { |
||||
226 | return; |
||||
227 | } |
||||
228 | |||||
229 | foreach ($elementData as $form => $data) { |
||||
230 | // Extract the ID |
||||
231 | $elementId = (int) substr($form, $idPrefixLength); |
||||
232 | |||||
233 | /** @var BaseElement $element */ |
||||
234 | $element = $this->getArea()->Elements()->byID($elementId); |
||||
235 | |||||
236 | if (!$element) { |
||||
237 | // Ignore invalid elements |
||||
238 | continue; |
||||
239 | } |
||||
240 | |||||
241 | $data = ElementalAreaController::removeNamespacesFromFields($data, $element->ID); |
||||
242 | |||||
243 | $element->updateFromFormData($data); |
||||
244 | $element->write(); |
||||
245 | } |
||||
246 | } |
||||
247 | } |
||||
248 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths