ConfigurablePage::onAfterWrite()   B
last analyzed

Complexity

Conditions 6
Paths 3

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.0061

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 17
cts 18
cp 0.9444
rs 8.439
c 0
b 0
f 0
cc 6
eloc 15
nc 3
nop 0
crap 6.0061
1
<?php
2
3
/**
4
 * ConfigurablePage is the page class for the module.
5
 *
6
 * @author  Mohamed Alsharaf <[email protected]>
7
 */
8
class ConfigurablePage extends Page
9
{
10
    private static $many_many = [
11
        'Fields' => 'Moo_EditableField',
12
    ];
13
    private static $many_many_extraFields = [
14
        'Fields' => [
15
            'Value' => 'Text',
16
            'Sort'  => 'Int',
17
            'Group' => 'Int',
18
        ],
19
    ];
20
    private static $has_one = [
21
        'EditableFieldGroup' => 'Moo_EditableFieldGroup',
22
    ];
23
    private static $singular_name = 'Configurable Page';
24
    private static $plural_name   = 'Configurable Pages';
25
    private static $description   = 'Create page with configurable fields';
26
    private static $icon          = 'configurablepage/images/icon.png';
27
28
    /**
29
     * An array of required field names.
30
     *
31
     * @var array
32
     */
33
    protected $requiredFields = [];
34
35
    /**
36
     * An instance of ManyManyList containing the current values from the configurable fields.
37
     *
38
     * @var ManyManyList
39
     */
40
    protected $editableFields;
41
42
    /**
43
     * List of allowed child page types.
44
     *
45
     * @var array
46
     */
47
    private static $allowed_children = ['ConfigurablePage', 'SiteTree'];
48
49
    /**
50
     * (non-PHPdoc).
51
     *
52
     * @see SiteTree::getCMSFields()
53
     */
54 1
    public function getCMSFields()
55
    {
56
        // Get the fields from the parent implementation
57 1
        $fields = parent::getCMSFields();
58
59
        // List of available fields in the page
60 1
        $groupFields = $this->EditableFieldGroup()->Fields();
61 1
        $list        = $this->Fields()->addMany($groupFields)->sort('Sort', 'ASC');
62
63
        // Add tab to edit fields values
64 1
        $this->buildPageFieldsTab($list, $fields);
65
66
        // Add tab to manage page fields
67 1
        $this->buildManageFieldsTab($list, $fields);
68
69 1
        return $fields;
70
    }
71
72
    /**
73
     * Create tab to manage page fields.
74
     *
75
     * @param FieldList $fields
76
     */
77 1
    protected function buildManageFieldsTab(ManyManyList $list, FieldList $fields)
78
    {
79
        // GridField for managing page specific fields
80 1
        $config = GridFieldConfig_RelationEditor::create();
81 1
        $config->getComponentByType('GridFieldPaginator')->setItemsPerPage(10);
82 1
        $config->removeComponentsByType('GridFieldAddNewButton');
83 1
        $config->removeComponentsByType('GridFieldEditButton');
84 1
        $config->getComponentByType('GridFieldDataColumns')->setDisplayFields([
85 1
            'Name'  => _t('ConfigurablePage.NAME', 'Name'),
86 1
            'Title' => _t('ConfigurablePage.TITLE', 'Title'),
87 1
            'Group' => _t('ConfigurablePage.GROUP', 'Group'),
88 1
        ]);
89 1
        $config->addComponent(new GridFieldOrderableRows('Sort'));
90 1
        $config->getComponentByType('GridFieldDataColumns')
91 1
            ->setFieldFormatting([
92
                'Group' => function ($value) {
93
                    return !$value ? '' : $this->EditableFieldGroup()->Title;
94 1
                },
95 1
            ]);
96 1
        $fieldsField = new GridField('Fields', 'Fields', $list, $config);
97
98
        // Drop-down list of editable field groups
99 1
        $groups = Moo_EditableFieldGroup::get()->map();
100 1
        $groups->unshift('', '');
101
102 1
        $groupsField = new DropdownField(
103 1
            'EditableFieldGroupID',
104 1
            _t('ConfigurablePage.FIELDGROUP', 'Editable field group'),
105
            $groups
106 1
        );
107 1
        $groupsField->setDescription(_t(
108 1
            'ConfigurablePage.FIELDGROUP_HELP',
109
            'Select a group to load its collection of fields in the current page. '
110
            . 'You need to click save to update the page fields.'
111 1
        ));
112
113
        // Add fields to manage page fields tab
114 1
        $fields->addFieldsToTab('Root.ManagePageFields', [
115 1
            $groupsField, $fieldsField,
116 1
        ]);
117 1
    }
118
119
    /**
120
     * Create tab to edit fields values.
121
     *
122
     * @param ManyManyList $list
123
     * @param FieldList    $fields
124
     */
125 1
    protected function buildPageFieldsTab(ManyManyList $list, FieldList $fields)
126
    {
127 1
        $fields->findOrMakeTab('Root.Fields', _t('ConfigurablePage.FIELDS', 'Fields'));
128
129
        $list->each(function (Moo_EditableField $editableField) use ($fields) {
130 1
            $field = $this->getFieldFromEditableField($editableField);
131 1
            if (false !== $field) {
132 1
                $fields->addFieldToTab('Root.Fields', $field);
133 1
            }
134 1
        });
135 1
    }
136
137
    /**
138
     * Add an editable field to the fields tab.
139
     *
140
     * @param Moo_EditableField $editableField
141
     *
142
     * @return bool|FormField
143
     */
144 1
    protected function getFieldFromEditableField(Moo_EditableField $editableField)
145
    {
146
        // Get the raw form field from the editable version
147 1
        $field = $editableField->getFormField();
148 1
        if (!$field) {
149 1
            return false;
150
        }
151
152
        // Set the error / formatting messages
153 1
        $field->setCustomValidationMessage($editableField->getErrorMessage());
154
155
        // Set the right title on this field
156 1
        $right = $editableField->getSetting('RightTitle');
157 1
        if ($right) {
158
            $field->setRightTitle($right);
159
            $field->addExtraClass('help');
160
        }
161
162
        // Set the required field
163 1
        if ($editableField->Required) {
164 1
            $this->requiredFields[] = $editableField->Name;
165 1
        }
166
167
        // Set the value
168 1
        if (!$field instanceof DatalessField) {
169 1
            $field->value = Convert::raw2att($editableField->Value);
170 1
            $this->setField($editableField->Name, $editableField->Value);
171 1
        }
172
173 1
        return $field;
174
    }
175
176
    /**
177
     * Set required fields.
178
     *
179
     * @return RequiredFields
180
     */
181 1
    public function getCMSValidator()
182
    {
183 1
        return new RequiredFields($this->requiredFields);
184
    }
185
186 3
    public function onAfterWrite()
187
    {
188 3
        parent::onAfterWrite();
189
190
        // Skip on publishing
191 3
        if (Versioned::get_live_stage() == Versioned::current_stage()) {
192
            return;
193
        }
194
195
        // Update the values of all fields added from editable field
196 3
        if ($this->ID && $this->manyMany('Fields') && $pageFields = $this->getEditableFields()) {
197 3
            $pageFields->each(function (Moo_EditableField $pageField) use ($pageFields) {
198
                // Set submitted value into the field
199 2
                $field = $pageField->getFormField();
200 2
                if (!$field) {
201 1
                    return;
202
                }
203 2
                $field->setValue($this->{$pageField->Name});
204
205
                // Extra fields to be saved
206 2
                $value = $field->Value();
207 2
                $sort = $pageField->Sort;
208 2
                $group = $pageField->Group;
209
210
                // Clone the editable field object
211
                // Remove the current saved one
212 2
                $pageFields->remove($pageField);
213
                // Add the clone with the new extra data
214 2
                $pageFields->add($pageField, ['Value' => $value, 'Sort' => $sort, 'Group' => $group]);
215 3
            });
216 3
        }
217 3
    }
218
219
    /**
220
     * Format the page Content.
221
     *
222
     * @return string
223
     */
224 2
    public function Content()
225
    {
226
        // Get custom fields
227 2
        $fields = $this->getEditableFields();
228 2
        $values = [];
229
230
        // Add custom fields to the current object
231
        // & create dictionary of the custom fields values
232 2
        foreach ($fields as $field) {
233 2
            $value = $field->getViewValue();
234 2
            $name  = $field->getViewFieldName();
235
236
            // Fields with false value are not viewable data
237 2
            if ($value !== false) {
238 2
                $this->setField($name, $value);
239 2
                $values['$' . $name] = $field->getValueAsString();
240 2
            }
241 2
        }
242
243
        // Execute content from extensions
244
        // Set content from view template module
245 2
        $this->extend('Content');
246
247
        // & Replace ${Field Name} with a string value
248 2
        return strtr($this->Content, $values);
249
    }
250
251
    /**
252
     * Get an array of all of the editable fields for the view template.
253
     *
254
     * @return ManyManyList
255
     */
256 3
    public function getEditableFields()
257
    {
258 3
        if (null === $this->editableFields) {
259
            // Fields from editable field groups
260 3
            $groupFields = $this->EditableFieldGroup()->Fields();
261 3
            $ids         = $groupFields->getIDList();
262
263
            // Set page specific fields
264 3
            $this->editableFields = $this->Fields();
265
266
            // Remove all fields that are used to belong to editable field group
267
            // Then sync editable field group with page specific fields
268
            // Else remove all of a group editable fields if exists
269 3
            if (!empty($ids)) {
270
                $this->editableFields->removeByFilter(
271
                    '"Group" > 0 AND EditableFieldID NOT IN (' . implode(',', $ids) . ')'
272
                )->addMany($groupFields);
273
            } else {
274 3
                $this->editableFields->removeByFilter('"Group" > 0');
275
            }
276 3
        }
277
278 3
        return $this->editableFields;
279
    }
280
}
281