GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

contentBlueprintsSections   F
last analyzed

Complexity

Total Complexity 157

Size/Duplication

Total Lines 993
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 483
c 3
b 0
f 0
dl 0
loc 993
rs 2
wmc 157

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __actionEdit() 0 3 1
B __actionIndex() 0 75 11
F __actionNew() 0 308 59
F __viewNew() 0 163 30
A addSectionOptions() 0 42 1
F __viewEdit() 0 221 33
A build() 0 11 2
B __viewIndex() 0 116 10
B validateTimestamp() 0 19 10

How to fix   Complexity   

Complex Class

Complex classes like contentBlueprintsSections often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use contentBlueprintsSections, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package content
4
 */
5
6
/**
7
 * This page controls the creation and maintenance of Symphony
8
 * Sections through the Section Index and Section Editor.
9
 */
10
11
class contentBlueprintsSections extends AdministrationPage
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
12
{
13
    public $_errors = array();
14
15
    public function build(array $context = array())
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$context" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$context"; expected 0 but found 1
Loading history...
16
    {
17
        if (isset($context[1])) {
18
            $section_id = $context[1];
19
            $context['associations'] = array(
20
                'parent' => SectionManager::fetchParentAssociations($section_id),
21
                'child' => SectionManager::fetchChildAssociations($section_id)
22
            );
23
        }
24
25
        return parent::build($context);
0 ignored issues
show
Bug introduced by
Are you sure the usage of parent::build($context) targeting AdministrationPage::build() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
26
    }
27
28
    public function __viewIndex()
29
    {
30
        $this->setPageType('table');
31
        $this->setTitle(__('%1$s &ndash; %2$s', array(__('Sections'), __('Symphony'))));
32
        $this->appendSubheading(__('Sections'), Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL().'new/', __('Create a section'), 'create button', null, array('accesskey' => 'c')));
33
34
        $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
35
36
        $aTableHead = array(
37
            array(__('Name'), 'col'),
38
            array(__('Entries'), 'col'),
39
            array(__('Navigation Group'), 'col')
40
        );
41
42
        $aTableBody = array();
43
44
        if (!is_array($sections) || empty($sections)) {
45
            $aTableBody = array(
46
                Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', null, count($aTableHead))), 'odd')
47
            );
48
        } else {
49
            foreach ($sections as $s) {
50
                $entry_count = EntryManager::fetchCount($s->get('id'));
51
52
                // Setup each cell
53
                $td1 = Widget::TableData(Widget::Anchor(General::sanitize($s->get('name')), Administration::instance()->getCurrentPageURL() . 'edit/' . $s->get('id') .'/', null, 'content'));
54
                $td1->appendChild(Widget::Label(__('Select Section %s', array(General::sanitize($s->get('name')))), null, 'accessible', null, array(
55
                    'for' => 'section-' . $s->get('id')
56
                )));
57
                $td1->appendChild(Widget::Input('items['.$s->get('id').']', $s->get('modification_date'), 'checkbox', array(
58
                    'id' => 'section-' . $s->get('id')
59
                )));
60
61
                $td2 = Widget::TableData(Widget::Anchor((string)$entry_count, SYMPHONY_URL . '/publish/' . $s->get('handle') . '/'));
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
62
                $td3 = Widget::TableData(General::sanitize($s->get('navigation_group')));
63
64
                // Create row
65
                $tr = Widget::TableRow(array($td1, $td2, $td3));
66
67
                if ($s->get('hidden') === 'yes') {
68
                    $tr->setAttribute('class', 'inactive');
69
                }
70
71
                $aTableBody[] = $tr;
72
            }
73
        }
74
75
        $table = Widget::Table(
76
            Widget::TableHead($aTableHead),
77
            null,
78
            Widget::TableBody($aTableBody),
79
            'orderable selectable',
80
            null,
81
            array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive')
82
        );
83
84
        $this->Form->appendChild($table);
85
86
        $version = new XMLElement('p', 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), array(
87
            'id' => 'version'
88
        ));
89
90
        $this->Form->appendChild($version);
91
92
        $tableActions = new XMLElement('div');
93
        $tableActions->setAttribute('class', 'actions');
94
95
        $options = array(
96
            array(null, false, __('With Selected...')),
97
            array('delete', false, __('Delete'), 'confirm', null, array(
98
                'data-message' => __('Are you sure you want to delete the selected sections?')
99
            )),
100
            array('delete-entries', false, __('Delete Entries'), 'confirm', null, array(
101
                'data-message' => __('Are you sure you want to delete all entries in the selected sections?')
102
            ))
103
        );
104
105
        if (is_array($sections) && !empty($sections)) {
106
            $index = 3;
107
            $options[$index] = array('label' => __('Set navigation group'), 'options' => array());
108
109
            $groups = array();
110
111
            foreach ($sections as $s) {
112
                if (in_array($s->get('navigation_group'), $groups)) {
113
                    continue;
114
                }
115
116
                $groups[] = $s->get('navigation_group');
117
118
                $value = 'set-navigation-group-' . urlencode($s->get('navigation_group'));
119
                $options[$index]['options'][] = array($value, false, General::sanitize($s->get('navigation_group')));
120
            }
121
        }
122
123
        /**
124
         * Allows an extension to modify the existing options for this page's
125
         * With Selected menu. If the `$options` parameter is an empty array,
126
         * the 'With Selected' menu will not be rendered.
127
         *
128
         * @delegate AddCustomActions
129
         * @since Symphony 2.3.2
130
         * @param string $context
131
         * '/blueprints/sections/'
132
         * @param array $options
133
         *  An array of arrays, where each child array represents an option
134
         *  in the With Selected menu. Options should follow the same format
135
         *  expected by `Widget::__SelectBuildOption`. Passed by reference.
136
         */
137
        Symphony::ExtensionManager()->notifyMembers('AddCustomActions', '/blueprints/sections/', array(
138
            'options' => &$options
139
        ));
140
141
        if (!empty($options)) {
142
            $tableActions->appendChild(Widget::Apply($options));
143
            $this->Form->appendChild($tableActions);
144
        }
145
    }
146
147
    public function __viewNew()
148
    {
149
        $this->setPageType('form');
150
        $this->setTitle(__('%1$s &ndash; %2$s', array(__('Sections'), __('Symphony'))));
151
        $this->appendSubheading(__('Untitled'));
152
        $this->insertBreadcrumbs(array(
153
            Widget::Anchor(__('Sections'), SYMPHONY_URL . '/blueprints/sections/'),
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
154
        ));
155
156
        $types = array();
157
158
        $fields = (isset($_POST['fields']) && is_array($_POST['fields'])) ? $_POST['fields'] : array();
159
        $meta = (isset($_POST['meta']) && is_array($_POST['meta'])) ? $_POST['meta'] : array('name'=>null);
160
161
        $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
162
163
        if ($formHasErrors) {
164
            $this->pageAlert(
165
                __('An error occurred while processing this form. See below for details.'),
166
                Alert::ERROR
167
            );
168
        }
169
170
        $showEmptyTemplate = (is_array($fields) && !empty($fields) ? false : true);
171
172
        if (!$showEmptyTemplate) {
173
            ksort($fields);
174
        }
175
176
        // Set navigation group, if not already set
177
        if (!isset($meta['navigation_group'])) {
178
            $meta['navigation_group'] = (isset($this->_navigation[0]['name']) ? $this->_navigation[0]['name'] : __('Content'));
179
        }
180
181
        $fieldset = new XMLElement('fieldset');
182
        $fieldset->setAttribute('class', 'settings');
183
        $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
184
185
        $namediv = new XMLElement('div', null, array('class' => 'column'));
186
187
        $label = Widget::Label(__('Name'));
188
        $label->appendChild(Widget::Input('meta[name]', (isset($meta['name']) ? General::sanitize($meta['name']) : null)));
189
190
        if (isset($this->_errors['name'])) {
191
            $namediv->appendChild(Widget::Error($label, $this->_errors['name']));
192
        } else {
193
            $namediv->appendChild($label);
194
        }
195
196
        $fieldset->appendChild($namediv);
197
198
        $div = new XMLElement('div', null, array('class' => 'two columns'));
199
200
        $handlediv = new XMLElement('div', null, array('class' => 'column'));
201
202
        $label = Widget::Label(__('Handle'));
203
        $label->appendChild(Widget::Input('meta[handle]', (isset($meta['handle']) ? General::sanitize($meta['handle']) : null)));
204
205
        if (isset($this->_errors['handle'])) {
206
            $handlediv->appendChild(Widget::Error($label, $this->_errors['handle']));
207
        } else {
208
            $handlediv->appendChild($label);
209
        }
210
211
        $div->appendChild($handlediv);
212
213
        $navgroupdiv = new XMLElement('div', null, array('class' => 'column'));
214
215
        $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
216
        $label = Widget::Label(__('Navigation Group'));
217
        $label->appendChild(Widget::Input('meta[navigation_group]', (isset($meta['navigation_group']) ? General::sanitize($meta['navigation_group']) : null)));
218
219
        if (isset($this->_errors['navigation_group'])) {
220
            $navgroupdiv->appendChild(Widget::Error($label, $this->_errors['navigation_group']));
221
        } else {
222
            $navgroupdiv->appendChild($label);
223
        }
224
225
        if (is_array($sections) && !empty($sections)) {
226
            $ul = new XMLElement('ul', null, array('class' => 'tags singular', 'data-interactive' => 'data-interactive'));
227
            $groups = array();
228
229
            foreach ($sections as $s) {
230
                if (in_array($s->get('navigation_group'), $groups)) {
231
                    continue;
232
                }
233
234
                $ul->appendChild(new XMLElement('li', General::sanitize($s->get('navigation_group'))));
235
                $groups[] = $s->get('navigation_group');
236
            }
237
238
            $navgroupdiv->appendChild($ul);
239
        }
240
241
        $div->appendChild($navgroupdiv);
242
        $fieldset->appendChild($div);
243
        $this->Form->appendChild($fieldset);
244
245
        $this->addSectionOptions($meta);
246
247
        $fieldset = new XMLElement('fieldset');
248
        $fieldset->setAttribute('class', 'settings');
249
250
        $legend = new XMLElement('legend', __('Fields'));
251
        $legend->setAttribute('id', 'fields-legend');
252
        $fieldset->appendChild($legend);
253
254
        $div = new XMLElement('div', null, array('class' => 'frame', 'id' => 'fields-duplicator'));
255
256
        $ol = new XMLElement('ol');
257
        $ol->setAttribute('data-add', __('Add field'));
258
        $ol->setAttribute('data-remove', __('Remove field'));
259
260
        if (!$showEmptyTemplate) {
261
            foreach ($fields as $position => $data) {
262
                if ($input = FieldManager::create($data['type'])) {
263
                    $input->setArray($data);
264
265
                    $wrapper = new XMLElement('li');
266
267
                    $input->set('sortorder', $position);
268
                    $input->displaySettingsPanel($wrapper, (isset($this->_errors[$position]) ? $this->_errors[$position] : null));
269
                    $ol->appendChild($wrapper);
270
                }
271
            }
272
        }
273
274
        foreach (FieldManager::listAll() as $type) {
275
            if ($type = FieldManager::create($type)) {
276
                $types[] = $type;
277
            }
278
        }
279
280
        uasort($types, function($a, $b) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
281
            return strnatcasecmp($a->_name, $b->_name);
282
        });
283
284
        foreach ($types as $type) {
285
            $defaults = array();
286
287
            $type->findDefaults($defaults);
288
            $type->setArray($defaults);
289
290
            $wrapper = new XMLElement('li');
291
            $wrapper->setAttribute('class', 'template field-' . $type->handle() . ($type->mustBeUnique() ? ' unique' : null));
292
            $wrapper->setAttribute('data-type', $type->handle());
293
294
            $type->set('sortorder', '-1');
295
            $type->displaySettingsPanel($wrapper);
296
297
            $ol->appendChild($wrapper);
298
        }
299
300
        $div->appendChild($ol);
301
        $fieldset->appendChild($div);
302
303
        $this->Form->appendChild($fieldset);
304
305
        $div = new XMLElement('div');
306
        $div->setAttribute('class', 'actions');
307
        $div->appendChild(Widget::Input('action[save]', __('Create Section'), 'submit', array('accesskey' => 's')));
308
309
        $this->Form->appendChild($div);
310
    }
311
312
    public function __viewEdit()
313
    {
314
        $section_id = $this->_context[1];
315
316
        if (!$section = SectionManager::fetch($section_id)) {
317
            Administration::instance()->throwCustomError(
318
                __('The Section, %s, could not be found.', array($section_id)),
319
                __('Unknown Section'),
320
                Page::HTTP_STATUS_NOT_FOUND
321
            );
322
        }
323
324
        $meta = $section->get();
325
        $section_id = $meta['id'];
326
        $types = array();
327
        $canonical_link = '/blueprints/sections/edit/' . $section_id . '/';
328
329
        $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
330
331
        if ($formHasErrors) {
332
            $this->pageAlert(
333
                __('An error occurred while processing this form. See below for details.'),
334
                Alert::ERROR
335
            );
336
337
            // These alerts are only valid if the form doesn't have errors
338
        } elseif (isset($this->_context[2])) {
339
            $time = Widget::Time();
340
341
            switch ($this->_context[2]) {
342
                case 'saved':
343
                    $message = __('Section updated at %s.', array($time->generate()));
344
                    break;
345
                case 'created':
346
                    $message = __('Section created at %s.', array($time->generate()));
347
            }
348
349
            $this->pageAlert(
350
                $message
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
351
                . ' <a href="' . SYMPHONY_URL . '/blueprints/sections/new/" accesskey="c">'
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
352
                . __('Create another?')
353
                . '</a> <a href="' . SYMPHONY_URL . '/blueprints/sections/" accesskey="a">'
354
                . __('View all Sections')
355
                . '</a>',
356
                Alert::SUCCESS
357
            );
358
        }
359
360
        if (isset($_POST['fields'])) {
361
            $fields = array();
362
            if (is_array($_POST['fields']) && !empty($_POST['fields'])) {
363
                foreach ($_POST['fields'] as $position => $data) {
364
                    if ($fields[$position] = FieldManager::create($data['type'])) {
365
                        $fields[$position]->setArray($data);
366
                        $fields[$position]->set('sortorder', $position);
367
                    }
368
                }
369
            }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
370
            $timestamp = isset($_POST['action']['timestamp'])
371
                ? $_POST['action']['timestamp']
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
372
                : $section->get('modification_date');
373
        } else {
374
            $fields = FieldManager::fetch(null, $section_id);
375
            $fields = array_values($fields);
376
            $timestamp = $section->get('modification_date');
377
        }
378
379
        if (isset($_POST['meta'])) {
380
            $meta = $_POST['meta'];
381
            if ($meta['name'] == '') {
382
                $meta['name'] = $section->get('name');
383
            }
384
        }
385
386
        $this->setPageType('form');
387
        $this->setTitle(__('%1$s &ndash; %2$s &ndash; %3$s', array(General::sanitize($meta['name']), __('Sections'), __('Symphony'))));
388
        $this->addElementToHead(new XMLElement('link', null, array(
389
            'rel' => 'canonical',
390
            'href' => SYMPHONY_URL . $canonical_link,
391
        )));
392
        $this->appendSubheading(General::sanitize($meta['name']),
393
            Widget::Anchor(__('View Entries'), SYMPHONY_URL . '/publish/' . $section->get('handle') . '/', __('View Section Entries'), 'button')
0 ignored issues
show
Bug introduced by
Are you sure $section->get('handle') of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

393
            Widget::Anchor(__('View Entries'), SYMPHONY_URL . '/publish/' . /** @scrutinizer ignore-type */ $section->get('handle') . '/', __('View Section Entries'), 'button')
Loading history...
394
        );
395
        $this->insertBreadcrumbs(array(
396
            Widget::Anchor(__('Sections'), SYMPHONY_URL . '/blueprints/sections/'),
397
        ));
398
399
        $fieldset = new XMLElement('fieldset');
400
        $fieldset->setAttribute('class', 'settings');
401
        $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
402
403
        $namediv = new XMLElement('div', null, array('class' => 'column'));
404
405
        $label = Widget::Label(__('Name'));
406
        $label->appendChild(Widget::Input('meta[name]', (isset($meta['name']) ? General::sanitize($meta['name']) : null)));
407
408
        if (isset($this->_errors['name'])) {
409
            $namediv->appendChild(Widget::Error($label, $this->_errors['name']));
410
        } else {
411
            $namediv->appendChild($label);
412
        }
413
414
        $fieldset->appendChild($namediv);
415
416
        $div = new XMLElement('div', null, array('class' => 'two columns'));
417
418
        $handlediv = new XMLElement('div', null, array('class' => 'column'));
419
420
        $label = Widget::Label(__('Handle'));
421
        $label->appendChild(Widget::Input('meta[handle]', (isset($meta['handle']) ? General::sanitize($meta['handle']) : null)));
422
423
        if (isset($this->_errors['handle'])) {
424
            $handlediv->appendChild(Widget::Error($label, $this->_errors['handle']));
425
        } else {
426
            $handlediv->appendChild($label);
427
        }
428
429
        $div->appendChild($handlediv);
430
431
        $navgroupdiv = new XMLElement('div', null, array('class' => 'column'));
432
433
        $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
434
        $label = Widget::Label(__('Navigation Group'));
435
        $label->appendChild(Widget::Input('meta[navigation_group]', General::sanitize($meta['navigation_group'])));
436
437
        if (isset($this->_errors['navigation_group'])) {
438
            $navgroupdiv->appendChild(Widget::Error($label, $this->_errors['navigation_group']));
439
        } else {
440
            $navgroupdiv->appendChild($label);
441
        }
442
443
        if (is_array($sections) && !empty($sections)) {
444
            $ul = new XMLElement('ul', null, array('class' => 'tags singular', 'data-interactive' => 'data-interactive'));
445
            $groups = array();
446
447
            foreach ($sections as $s) {
448
                if (in_array($s->get('navigation_group'), $groups)) {
449
                    continue;
450
                }
451
452
                $ul->appendChild(new XMLElement('li', General::sanitize($s->get('navigation_group'))));
453
                $groups[] = $s->get('navigation_group');
454
            }
455
456
            $navgroupdiv->appendChild($ul);
457
        }
458
459
        $div->appendChild($navgroupdiv);
460
        $fieldset->appendChild($div);
461
        $this->Form->appendChild($fieldset);
462
463
        $this->addSectionOptions($meta);
464
465
        $fieldset = new XMLElement('fieldset');
466
        $fieldset->setAttribute('class', 'settings');
467
468
        $legend = new XMLElement('legend', __('Fields'));
469
        $legend->setAttribute('id', 'fields-legend');
470
        $fieldset->appendChild($legend);
471
472
        $div = new XMLElement('div', null, array('class' => 'frame', 'id' => 'fields-duplicator'));
473
474
        $ol = new XMLElement('ol');
475
        $ol->setAttribute('data-add', __('Add field'));
476
        $ol->setAttribute('data-remove', __('Remove field'));
477
478
        if (is_array($fields) && !empty($fields)) {
479
            foreach ($fields as $position => $field) {
480
                $wrapper = new XMLElement('li', null, array('class' => 'field-' . $field->handle() . ($field->mustBeUnique() ? ' unique' : null)));
481
                $wrapper->setAttribute('data-type', $field->handle());
482
483
                $field->set('sortorder', $position);
484
                $field->displaySettingsPanel($wrapper, (isset($this->_errors[$position]) ? $this->_errors[$position] : null));
485
                $ol->appendChild($wrapper);
486
            }
487
        }
488
489
        foreach (FieldManager::listAll() as $type) {
490
            if ($type = FieldManager::create($type)) {
491
                array_push($types, $type);
492
            }
493
        }
494
495
        uasort($types, function($a, $b) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
496
            return strnatcasecmp($a->_name, $b->_name);
497
        });
498
499
        foreach ($types as $type) {
500
            $defaults = array();
501
502
            $type->findDefaults($defaults);
503
            $type->setArray($defaults);
504
505
            $wrapper = new XMLElement('li');
506
507
            $wrapper->setAttribute('class', 'template field-' . $type->handle() . ($type->mustBeUnique() ? ' unique' : null));
508
            $wrapper->setAttribute('data-type', $type->handle());
509
510
            $type->set('sortorder', '-1');
511
            $type->displaySettingsPanel($wrapper);
512
513
            $ol->appendChild($wrapper);
514
        }
515
516
        $div->appendChild($ol);
517
        $fieldset->appendChild($div);
518
519
        $this->Form->appendChild($fieldset);
520
521
        $div = new XMLElement('div');
522
        $div->setAttribute('class', 'actions');
523
        $div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', array('accesskey' => 's')));
524
525
        $button = new XMLElement('button', __('Delete'));
526
        $button->setAttributeArray(array('name' => 'action[delete]', 'class' => 'button confirm delete', 'title' => __('Delete this section'), 'type' => 'submit', 'accesskey' => 'd', 'data-message' => __('Are you sure you want to delete this section?')));
527
        $div->appendChild($button);
528
529
        $div->appendChild(Widget::Input('action[timestamp]', $timestamp, 'hidden'));
530
        $div->appendChild(Widget::Input('action[ignore-timestamp]', 'yes', 'checkbox', array('class' => 'irrelevant')));
531
532
        $this->Form->appendChild($div);
533
    }
534
535
    public function __actionIndex()
536
    {
537
        $checked = (is_array($_POST['items'])) ? array_keys($_POST['items']) : null;
538
539
        if (is_array($checked) && !empty($checked)) {
540
            /**
541
             * Extensions can listen for any custom actions that were added
542
             * through `AddCustomPreferenceFieldsets` or `AddCustomActions`
543
             * delegates.
544
             *
545
             * @delegate CustomActions
546
             * @since Symphony 2.3.2
547
             * @param string $context
548
             *  '/blueprints/sections/'
549
             * @param array $checked
550
             *  An array of the selected rows. The value is usually the ID of the
551
             *  the associated object.
552
             */
553
            Symphony::ExtensionManager()->notifyMembers('CustomActions', '/blueprints/sections/', array(
554
                'checked' => $checked
555
            ));
556
557
            if ($_POST['with-selected'] == 'delete') {
558
                /**
559
                 * Just prior to calling the Section Manager's delete function
560
                 *
561
                 * @delegate SectionPreDelete
562
                 * @since Symphony 2.2
563
                 * @param string $context
564
                 * '/blueprints/sections/'
565
                 * @param array $section_ids
566
                 *  An array of Section ID's passed by reference
567
                 */
568
                Symphony::ExtensionManager()->notifyMembers('SectionPreDelete', '/blueprints/sections/', array('section_ids' => &$checked));
569
570
                foreach ($checked as $section_id) {
571
                    SectionManager::delete($section_id);
572
                }
573
574
                redirect(SYMPHONY_URL . '/blueprints/sections/');
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
575
            } elseif ($_POST['with-selected'] == 'delete-entries') {
576
                foreach ($checked as $section_id) {
577
                    $entries = EntryManager::fetch(null, $section_id, null, null, null, null, false, false, null, false);
578
                    $entry_ids = array();
579
580
                    foreach ($entries as $entry) {
581
                        $entry_ids[] = $entry['id'];
582
                    }
583
584
                    /**
585
                     * Prior to deletion of entries.
586
                     *
587
                     * @delegate Delete
588
                     * @param string $context
589
                     * '/publish/'
590
                     * @param array $entry_id
591
                     *  An array of Entry ID's that are about to be deleted, passed by reference
592
                     */
593
                    Symphony::ExtensionManager()->notifyMembers('Delete', '/publish/', array('entry_id' => &$entry_ids));
594
595
                    EntryManager::delete($entry_ids, $section_id);
596
                }
597
598
                redirect(SYMPHONY_URL . '/blueprints/sections/');
599
            } elseif (preg_match('/^set-navigation-group-/', $_POST['with-selected'])) {
600
                $navigation_group = preg_replace('/^set-navigation-group-/', null, $_POST['with-selected']);
601
602
                foreach ($checked as $section_id) {
603
                    SectionManager::edit($section_id, array(
604
                        'navigation_group' => urldecode($navigation_group),
605
                        'modification_author_id' => Symphony::Author()->get('id'),
606
                    ));
607
                }
608
609
                redirect(SYMPHONY_URL . '/blueprints/sections/');
610
            }
611
        }
612
    }
613
614
    public function __actionNew()
615
    {
616
        if (@array_key_exists('save', $_POST['action']) || @array_key_exists('done', $_POST['action'])) {
617
            $canProceed = true;
618
            $edit = ($this->_context[0] == "edit");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal edit does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
619
            $this->_errors = array();
620
621
            $fields = isset($_POST['fields']) ? $_POST['fields'] : array();
622
            $meta = $_POST['meta'];
623
624
            if ($edit) {
625
                $section_id = $this->_context[1];
626
                $existing_section = SectionManager::fetch($section_id);
627
                $canProceed = $this->validateTimestamp($section_id, true);
628
                if (!$canProceed) {
629
                    $this->addTimestampValidationPageAlert($this->_errors['timestamp'], $existing_section, 'save');
0 ignored issues
show
Bug introduced by
It seems like $existing_section can also be of type array; however, parameter $existingObject of AdministrationPage::addT...mpValidationPageAlert() does only seem to accept Entry|Section, 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 ignore-type  annotation

629
                    $this->addTimestampValidationPageAlert($this->_errors['timestamp'], /** @scrutinizer ignore-type */ $existing_section, 'save');
Loading history...
630
                }
631
            }
632
633
            // Check handle to ensure it is unique
634
            $meta['handle'] = $_POST['meta']['handle'] = Lang::createHandle((isset($meta['handle']) && !empty($meta['handle']))
635
                ? $meta['handle']
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
636
                : $meta['name']);
637
638
            // Check to ensure all the required section fields are filled
639
            if (!isset($meta['name']) || strlen(trim($meta['name'])) == 0) {
640
                $this->_errors['name'] = __('This is a required field.');
641
                $canProceed = false;
642
643
                // Check for duplicate section handle during edit
644
            } elseif ($edit) {
645
                $s = SectionManager::fetchIDFromHandle(Lang::createHandle($meta['handle']));
646
647
                if (
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after opening bracket; newline found
Loading history...
648
                    $meta['handle'] !== $existing_section->get('handle')
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $existing_section does not seem to be defined for all execution paths leading up to this point.
Loading history...
649
                    && !is_null($s) && $s !== $section_id
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $section_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
650
                ) {
651
                    $this->_errors['handle'] = __('A Section with the handle %s already exists', array('<code>' . $meta['handle'] . '</code>'));
652
                    $canProceed = false;
653
                }
654
655
                // Existing section during creation
656
            } elseif (!is_null(SectionManager::fetchIDFromHandle(Lang::createHandle($meta['handle'])))) {
0 ignored issues
show
introduced by
The condition is_null(SectionManager::...ndle($meta['handle']))) is always false.
Loading history...
657
                $this->_errors['handle'] = __('A Section with the handle %s already exists', array('<code>' . $meta['handle'] . '</code>'));
658
                $canProceed = false;
659
            }
660
661
            // Check to ensure all the required section fields are filled
662
            if (!isset($meta['navigation_group']) || strlen(trim($meta['navigation_group'])) == 0) {
663
                $this->_errors['navigation_group'] = __('This is a required field.');
664
                $canProceed = false;
665
            }
666
667
            // Basic custom field checking
668
            if (is_array($fields) && !empty($fields)) {
669
                // Check for duplicate CF names
670
                if ($canProceed) {
671
                    $name_list = array();
672
673
                    foreach ($fields as $position => $data) {
674
                        if (trim($data['element_name']) == '') {
675
                            $data['element_name'] = $fields[$position]['element_name'] = $_POST['fields'][$position]['element_name'] = Lang::createHandle($data['label'], 255, '-', false, true, array('@^[\d-]+@i' => ''));
676
                        }
677
678
                        if (trim($data['element_name']) != '' && in_array($data['element_name'], $name_list)) {
679
                            $this->_errors[$position] = array('element_name' => __('A field with this handle already exists. All handle must be unique.'));
680
                            $canProceed = false;
681
                            break;
682
                        }
683
684
                        $name_list[] = $data['element_name'];
685
                    }
686
                }
687
688
                if ($canProceed) {
689
                    $unique = array();
690
691
                    foreach ($fields as $position => $data) {
692
                        $field = FieldManager::create($data['type']);
693
                        $field->setFromPOST($data);
694
695
                        if (isset($existing_section)) {
696
                            $field->set('parent_section', $existing_section->get('id'));
697
                        }
698
699
                        if ($field->mustBeUnique() && !in_array($field->get('type'), $unique)) {
700
                            $unique[] = $field->get('type');
701
                        } elseif ($field->mustBeUnique() && in_array($field->get('type'), $unique)) {
702
                            // Warning. cannot have 2 of this field!
703
                            $canProceed = false;
704
                            $this->_errors[$position] = array('label' => __('There is already a field of type %s. There can only be one per section.', array('<code>' . $field->handle() . '</code>')));
705
                        }
706
707
                        $errors = array();
708
709
                        if (Field::__OK__ != $field->checkFields($errors, false) && !empty($errors)) {
710
                            $this->_errors[$position] = $errors;
711
                            $canProceed = false;
712
                        }
713
                    }
714
                }
715
            }
716
717
            if ($canProceed) {
718
                // If we are creating a new Section
719
                if (!$edit) {
720
                    $meta['sortorder'] = SectionManager::fetchNextSortOrder();
721
722
                    /**
723
                     * Just prior to saving the Section settings. Use with caution as
724
                     * there is no additional processing to ensure that Field's or Section's
725
                     * are unique.
726
                     *
727
                     * @delegate SectionPreCreate
728
                     * @since Symphony 2.2
729
                     * @param string $context
730
                     * '/blueprints/sections/'
731
                     * @param array $meta
732
                     *  The section's settings, passed by reference
733
                     * @param array $fields
734
                     *  An associative array of the fields that will be saved to this
735
                     *  section with the key being the position in the Section Editor
736
                     *  and the value being a Field object, passed by reference
737
                     */
738
                    Symphony::ExtensionManager()->notifyMembers('SectionPreCreate', '/blueprints/sections/', array('meta' => &$meta, 'fields' => &$fields));
739
740
                    $meta['author_id'] = Symphony::Author()->get('id');
741
                    $meta['modification_author_id'] = $meta['author_id'];
742
743
                    if (!$section_id = SectionManager::add($meta)) {
744
                        $this->pageAlert(__('An unknown database occurred while attempting to create the section.'), Alert::ERROR);
745
                    }
746
747
                    // We are editing a Section
748
                } else {
749
750
                    /**
751
                     * Just prior to updating the Section settings. Use with caution as
752
                     * there is no additional processing to ensure that Field's or Section's
753
                     * are unique.
754
                     *
755
                     * @delegate SectionPreEdit
756
                     * @since Symphony 2.2
757
                     * @param string $context
758
                     * '/blueprints/sections/'
759
                     * @param integer $section_id
760
                     *  The Section ID that is about to be edited.
761
                     * @param array $meta
762
                     *  The section's settings, passed by reference
763
                     * @param array $fields
764
                     *  An associative array of the fields that will be saved to this
765
                     *  section with the key being the position in the Section Editor
766
                     *  and the value being a Field object, passed by reference
767
                     */
768
                    Symphony::ExtensionManager()->notifyMembers('SectionPreEdit', '/blueprints/sections/', array('section_id' => $section_id, 'meta' => &$meta, 'fields' => &$fields));
769
770
                    $meta['modification_author_id'] = Symphony::Author()->get('id');
771
772
                    if (!SectionManager::edit($section_id, $meta)) {
773
                        $canProceed = false;
774
                        $this->pageAlert(__('An unknown database occurred while attempting to create the section.'), Alert::ERROR);
775
                    }
776
                }
777
778
                if ($section_id && $canProceed) {
779
                    if ($edit) {
780
                        // Delete missing CF's
781
                        $id_list = array();
782
783
                        if (is_array($fields) && !empty($fields)) {
784
                            foreach ($fields as $position => $data) {
785
                                if (isset($data['id'])) {
786
                                    $id_list[] = $data['id'];
787
                                }
788
                            }
789
                        }
790
791
                        $missing_cfs = Symphony::Database()->fetchCol('id', "SELECT `id` FROM `tbl_fields` WHERE `parent_section` = '$section_id' AND `id` NOT IN ('".@implode("', '", $id_list)."')");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $section_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
792
793
                        if (is_array($missing_cfs) && !empty($missing_cfs)) {
794
                            foreach ($missing_cfs as $id) {
795
                                FieldManager::delete($id);
796
                            }
797
                        }
798
                    }
799
800
                    // Save each custom field
801
                    if (is_array($fields) && !empty($fields)) {
802
                        foreach ($fields as $position => $data) {
803
                            $field = FieldManager::create($data['type']);
804
                            $field->setFromPOST($data);
805
                            $field->set('sortorder', (string)$position);
806
                            $field->set('parent_section', $section_id);
807
808
                            // It is possible that the "existing" field has been deleted
809
                            // so we are dealing with an invalid id.
810
                            // First make sure the field table still exists and that
811
                            // there is a field with the corresponding id in it
812
                            $newField = !((boolean)$field->get('id') && $field->tableExists() && $field->exists());
813
                            // If the field has not been found, erase the id from $_POST
814
                            if ($newField) {
815
                                $field->set('id', false);
816
                            }
817
818
                            // Save data
819
                            $field->commit();
820
                            // Get the new id
821
                            $field_id = $field->get('id');
822
823
                            if ($field_id) {
824
                                if ($newField) {
825
                                    /**
826
                                     * After creation of a Field.
827
                                     *
828
                                     * @delegate FieldPostCreate
829
                                     * @param string $context
830
                                     * '/blueprints/sections/'
831
                                     * @param Field $field
832
                                     *  The Field object, passed by reference
833
                                     * @param array $data
834
                                     *  The settings for ths `$field`, passed by reference
835
                                     */
836
                                    Symphony::ExtensionManager()->notifyMembers('FieldPostCreate', '/blueprints/sections/', array('field' => &$field, 'data' => &$data));
837
                                } else {
838
                                    /**
839
                                     * After editing of a Field.
840
                                     *
841
                                     * @delegate FieldPostEdit
842
                                     * @param string $context
843
                                     * '/blueprints/sections/'
844
                                     * @param Field $field
845
                                     *  The Field object, passed by reference
846
                                     * @param array $data
847
                                     *  The settings for ths `$field`, passed by reference
848
                                     */
849
                                    Symphony::ExtensionManager()->notifyMembers('FieldPostEdit', '/blueprints/sections/', array('field' => &$field, 'data' => &$data));
850
                                }
851
                            }
852
                        }
853
                    }
854
855
                    if (!$edit) {
856
                        /**
857
                         * After the Section has been created, and all the Field's have been
858
                         * created for this section, but just before the redirect
859
                         *
860
                         * @delegate SectionPostCreate
861
                         * @since Symphony 2.2
862
                         * @param string $context
863
                         * '/blueprints/sections/'
864
                         * @param integer $section_id
865
                         *  The newly created Section ID.
866
                         */
867
                        Symphony::ExtensionManager()->notifyMembers('SectionPostCreate', '/blueprints/sections/', array('section_id' => $section_id));
868
869
                        redirect(SYMPHONY_URL . "/blueprints/sections/edit/$section_id/created/");
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $section_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
870
                    } else {
871
                        /**
872
                         * After the Section has been updated, and all the Field's have been
873
                         * updated for this section, but just before the redirect
874
                         *
875
                         * @delegate SectionPostEdit
876
                         * @since Symphony 2.2
877
                         * @param string $context
878
                         * '/blueprints/sections/'
879
                         * @param integer $section_id
880
                         *  The edited Section ID.
881
                         */
882
                        Symphony::ExtensionManager()->notifyMembers('SectionPostEdit', '/blueprints/sections/', array('section_id' => $section_id));
883
884
                        redirect(SYMPHONY_URL . "/blueprints/sections/edit/$section_id/saved/");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $section_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
885
                    }
886
                }
887
            }
888
        }
889
890
        if (@array_key_exists('delete', $_POST['action'])) {
891
            $section_id = $this->_context[1];
892
            $canProceed = $this->validateTimestamp($section_id);
893
894
            if (!$canProceed) {
895
                $this->addTimestampValidationPageAlert(
896
                    $this->_errors['timestamp'],
897
                    SectionManager::fetch($section_id),
898
                    'delete'
899
                );
900
                return;
901
            }
902
903
            $section_ids = array($section_id);
904
905
            /**
906
             * Just prior to calling the Section Manager's delete function
907
             *
908
             * @delegate SectionPreDelete
909
             * @since Symphony 2.2
910
             * @param string $context
911
             * '/blueprints/sections/'
912
             * @param array $section_ids
913
             *  An array of Section ID's passed by reference
914
             */
915
            Symphony::ExtensionManager()->notifyMembers('SectionPreDelete', '/blueprints/sections/', array('section_ids' => &$section_ids));
916
917
            foreach ($section_ids as $section) {
918
                SectionManager::delete($section);
919
            }
920
921
            redirect(SYMPHONY_URL . '/blueprints/sections/');
922
        }
923
    }
924
925
    public function __actionEdit()
926
    {
927
        return $this->__actionNew();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->__actionNew() targeting contentBlueprintsSections::__actionNew() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
928
    }
929
930
    public function addSectionOptions(array &$meta = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$meta" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$meta"; expected 0 but found 1
Loading history...
931
    {
932
        $fieldset = new XMLElement('fieldset');
933
        $fieldset->setAttribute('class', 'settings');
934
        $fieldset->appendChild(new XMLElement('legend', __('Options')));
935
936
        $div = new XMLElement('div', null, array('class' => 'two columns'));
937
938
        $hidediv = new XMLElement('div', null, array('class' => 'column'));
939
        $label = Widget::Checkbox('meta[hidden]', $meta['hidden'], __('Hide this section from the back-end menu'));
940
        $hidediv->appendChild($label);
941
        $div->appendChild($hidediv);
942
943
        $filterdiv = new XMLElement('div', null, array('class' => 'column'));
944
        $label = Widget::Checkbox('meta[filter]', $meta['filter'], __('Allow filtering of section entries'));
945
        $filterdiv->appendChild($label);
946
947
        $div->appendChild($filterdiv);
948
        $fieldset->appendChild($div);
949
        $this->Form->appendChild($fieldset);
950
951
        /**
952
         * Allows extensions to add elements to the header of the Section Editor
953
         * form. Usually for section settings, this delegate is passed the current
954
         * `$meta` array and the `$this->_errors` array.
955
         *
956
         * @delegate AddSectionElements
957
         * @since Symphony 2.2
958
         * @param string $context
959
         * '/blueprints/sections/'
960
         * @param XMLElement $form
961
         *  An XMLElement of the current `$this->Form`, just after the Section
962
         *  settings have been appended, but before the Fields duplicator
963
         * @param array $meta
964
         *  The current $_POST['meta'] array
965
         * @param array $errors
966
         *  The current errors array
967
         */
968
        Symphony::ExtensionManager()->notifyMembers('AddSectionElements', '/blueprints/sections/', array(
969
            'form' => &$this->Form,
970
            'meta' => &$meta,
971
            'errors' => &$this->_errors
972
        ));
973
    }
974
975
    /**
976
     * Given $_POST values, this function will validate the current timestamp
977
     * and set the proper error messages.
978
     *
979
     * @since Symphony 2.7.0
980
     * @param  int $section_id
981
     *   The entry id to validate
982
     * @return boolean
983
     *   true if the timestamp is valid
984
     */
985
    protected function validateTimestamp($section_id, $checkMissing = false)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$checkMissing" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$checkMissing"; expected 0 but found 1
Loading history...
986
    {
987
        if (!isset($_POST['action']['ignore-timestamp'])) {
988
            if ($checkMissing && !isset($_POST['action']['timestamp'])) {
989
                if (isset($this->_errors) && is_array($this->_errors)) {
990
                    $this->_errors['timestamp'] = __('The section could not be saved due to conflicting changes');
991
                }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
992
                return false;
993
            } elseif (isset($_POST['action']['timestamp'])) {
994
                $tv = new TimestampValidator('sections');
995
                if (!$tv->check($section_id, $_POST['action']['timestamp'])) {
996
                    if (isset($this->_errors) && is_array($this->_errors)) {
997
                        $this->_errors['timestamp'] = __('The section could not be saved due to conflicting changes');
998
                    }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
999
                    return false;
1000
                }
1001
            }
1002
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1003
        return true;
1004
    }
1005
}
1006