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.
Completed
Pull Request — integration (#2604)
by Brendan
05:13
created

contentBlueprintsSections::__actionNew()   F

Complexity

Conditions 54
Paths > 20000

Size

Total Lines 300
Code Lines 121

Duplication

Lines 4
Ratio 1.33 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 54
eloc 121
c 5
b 0
f 0
nc 91803
nop 0
dl 4
loc 300
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
    class contentBlueprintsSections extends AdministrationPage
11
    {
12
        public $_errors = array();
13
14
        /**
15
         * The Sections page has /action/id/flag/ context.
16
         * eg. /edit/1/saved/
17
         *
18
         * @param array $context
19
         * @param array $parts
20
         * @return array
21
         */
22 View Code Duplication
        public function parseContext(array &$context, array $parts)
23
        {
24
            // Order is important!
25
            $params = array_fill_keys(array('action', 'id', 'flag'), null);
26
27
            if (isset($parts[2])) {
28
                $extras = preg_split('/\//', $parts[2], -1, PREG_SPLIT_NO_EMPTY);
29
                list($params['action'], $params['id'], $params['flag']) = $extras;
30
                $params['id'] = (int)$params['id'];
31
            }
32
33
            $context = array_filter($params);
34
        }
35
36 View Code Duplication
        public function build(array $context = array())
37
        {
38
            $section_id = $context['id'];
39
40
            if (isset($section_id)) {
41
                $context['associations'] = array(
42
                    'parent' => SectionManager::fetchParentAssociations($section_id),
43
                    'child' => SectionManager::fetchChildAssociations($section_id)
44
                );
45
            }
46
47
            return parent::build($context);
48
        }
49
50
        public function __viewIndex()
51
        {
52
            $this->setPageType('table');
53
            $this->setTitle(__('%1$s &ndash; %2$s', array(__('Sections'), __('Symphony'))));
54
            $this->appendSubheading(__('Sections'),
55
                Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL() . 'new/',
56
                    __('Create a section'), 'create button', null, array('accesskey' => 'c')));
57
58
            $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
59
60
            $aTableHead = array(
61
                array(__('Name'), 'col'),
62
                array(__('Entries'), 'col'),
63
                array(__('Navigation Group'), 'col')
64
            );
65
66
            $aTableBody = array();
67
68
            if (!is_array($sections) || empty($sections)) {
69
                $aTableBody = array(
70
                    Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', null, count($aTableHead))),
71
                        'odd')
72
                );
73
            } else {
74
                foreach ($sections as $s) {
75
                    $entry_count = EntryManager::fetchCount($s->get('id'));
76
77
                    // Setup each cell
78
                    $td1 = Widget::TableData(Widget::Anchor($s->get('name'),
79
                        Administration::instance()->getCurrentPageURL() . 'edit/' . $s->get('id') . '/', null,
80
                        'content'));
81
                    $td1->appendChild(Widget::Label(__('Select Section %s', array($s->get('name'))), null, 'accessible',
82
                        null, array(
83
                            'for' => 'section-' . $s->get('id')
84
                        )));
85
                    $td1->appendChild(Widget::Input('items[' . $s->get('id') . ']', 'on', 'checkbox', array(
86
                        'id' => 'section-' . $s->get('id')
87
                    )));
88
89
                    $td2 = Widget::TableData(Widget::Anchor("$entry_count",
90
                        SYMPHONY_URL . '/publish/' . $s->get('handle') . '/'));
91
                    $td3 = Widget::TableData($s->get('navigation_group'));
92
93
                    // Create row
94
                    $tr = Widget::TableRow(array($td1, $td2, $td3));
95
96
                    if ($s->get('hidden') === 'yes') {
97
                        $tr->setAttribute('class', 'inactive');
98
                    }
99
100
                    $aTableBody[] = $tr;
101
                }
102
            }
103
104
            $table = Widget::Table(
105
                Widget::TableHead($aTableHead),
106
                null,
107
                Widget::TableBody($aTableBody),
108
                'orderable selectable',
109
                null,
110
                array(
111
                    'role' => 'directory',
112
                    'aria-labelledby' => 'symphony-subheading',
113
                    'data-interactive' => 'data-interactive'
114
                )
115
            );
116
117
            $this->Form->appendChild($table);
118
119
            $version = new XMLElement('p', 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), array(
120
                'id' => 'version'
121
            ));
122
123
            $this->Form->appendChild($version);
124
125
            $tableActions = new XMLElement('div');
126
            $tableActions->setAttribute('class', 'actions');
127
128
            $options = array(
129
                array(null, false, __('With Selected...')),
130
                array(
131
                    'delete',
132
                    false,
133
                    __('Delete'),
134
                    'confirm',
135
                    null,
136
                    array(
137
                        'data-message' => __('Are you sure you want to delete the selected sections?')
138
                    )
139
                ),
140
                array(
141
                    'delete-entries',
142
                    false,
143
                    __('Delete Entries'),
144
                    'confirm',
145
                    null,
146
                    array(
147
                        'data-message' => __('Are you sure you want to delete all entries in the selected sections?')
148
                    )
149
                )
150
            );
151
152
            if (is_array($sections) && !empty($sections)) {
153
                $index = 3;
154
                $options[$index] = array('label' => __('Set navigation group'), 'options' => array());
155
156
                $groups = array();
157
158
                foreach ($sections as $s) {
159
                    if (in_array($s->get('navigation_group'), $groups)) {
160
                        continue;
161
                    }
162
163
                    $groups[] = $s->get('navigation_group');
164
165
                    $value = 'set-navigation-group-' . urlencode($s->get('navigation_group'));
166
                    $options[$index]['options'][] = array($value, false, $s->get('navigation_group'));
167
                }
168
            }
169
170
            /**
171
             * Allows an extension to modify the existing options for this page's
172
             * With Selected menu. If the `$options` parameter is an empty array,
173
             * the 'With Selected' menu will not be rendered.
174
             *
175
             * @delegate AddCustomActions
176
             * @since Symphony 2.3.2
177
             * @param string $context
178
             * '/blueprints/sections/'
179
             * @param array $options
180
             *  An array of arrays, where each child array represents an option
181
             *  in the With Selected menu. Options should follow the same format
182
             *  expected by `Widget::__SelectBuildOption`. Passed by reference.
183
             */
184
            Symphony::ExtensionManager()->notifyMembers('AddCustomActions', '/blueprints/sections/', array(
185
                'options' => &$options
186
            ));
187
188
            if (!empty($options)) {
189
                $tableActions->appendChild(Widget::Apply($options));
190
                $this->Form->appendChild($tableActions);
191
            }
192
        }
193
194
        public function __viewNew()
0 ignored issues
show
Coding Style introduced by
__viewNew uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
195
        {
196
            $this->setPageType('form');
197
            $this->setTitle(__('%1$s &ndash; %2$s', array(__('Sections'), __('Symphony'))));
198
            $this->appendSubheading(__('Untitled'));
199
            $this->insertBreadcrumbs(array(
200
                Widget::Anchor(__('Sections'), SYMPHONY_URL . '/blueprints/sections/'),
201
            ));
202
203
            $types = array();
204
205
            $fields = (isset($_POST['fields']) && is_array($_POST['fields'])) ? $_POST['fields'] : array();
206
            $meta = (isset($_POST['meta']) && is_array($_POST['meta'])) ? $_POST['meta'] : array('name' => null);
207
208
            $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
209
210
            if ($formHasErrors) {
211
                $this->pageAlert(
212
                    __('An error occurred while processing this form. See below for details.'),
213
                    Alert::ERROR
214
                );
215
            }
216
217
            $showEmptyTemplate = (is_array($fields) && !empty($fields) ? false : true);
218
219
            if (!$showEmptyTemplate) {
220
                ksort($fields);
221
            }
222
223
            // Set navigation group, if not already set
224
            if (!isset($meta['navigation_group'])) {
225
                $meta['navigation_group'] = (isset($this->_navigation[0]['name']) ? $this->_navigation[0]['name'] : __('Content'));
226
            }
227
228
            $fieldset = new XMLElement('fieldset');
229
            $fieldset->setAttribute('class', 'settings');
230
            $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
231
232
            $namediv = new XMLElement('div', null, array('class' => 'column'));
233
234
            $label = Widget::Label(__('Name'));
235
            $label->appendChild(Widget::Input('meta[name]',
236
                (isset($meta['name']) ? General::sanitize($meta['name']) : null)));
237
238 View Code Duplication
            if (isset($this->_errors['name'])) {
239
                $namediv->appendChild(Widget::Error($label, $this->_errors['name']));
240
            } else {
241
                $namediv->appendChild($label);
242
            }
243
244
            $fieldset->appendChild($namediv);
245
246
            $div = new XMLElement('div', null, array('class' => 'two columns'));
247
248
            $handlediv = new XMLElement('div', null, array('class' => 'column'));
249
250
            $label = Widget::Label(__('Handle'));
251
            $label->appendChild(Widget::Input('meta[handle]',
252
                (isset($meta['handle']) ? General::sanitize($meta['handle']) : null)));
253
254 View Code Duplication
            if (isset($this->_errors['handle'])) {
255
                $handlediv->appendChild(Widget::Error($label, $this->_errors['handle']));
256
            } else {
257
                $handlediv->appendChild($label);
258
            }
259
260
            $div->appendChild($handlediv);
261
262
            $navgroupdiv = new XMLElement('div', null, array('class' => 'column'));
263
264
            $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
265
            $label = Widget::Label(__('Navigation Group'));
266
            $label->appendChild(Widget::Input('meta[navigation_group]', $meta['navigation_group']));
267
268 View Code Duplication
            if (isset($this->_errors['navigation_group'])) {
269
                $navgroupdiv->appendChild(Widget::Error($label, $this->_errors['navigation_group']));
270
            } else {
271
                $navgroupdiv->appendChild($label);
272
            }
273
274 View Code Duplication
            if (is_array($sections) && !empty($sections)) {
275
                $ul = new XMLElement('ul', null,
276
                    array('class' => 'tags singular', 'data-interactive' => 'data-interactive'));
277
                $groups = array();
278
279
                foreach ($sections as $s) {
280
                    if (in_array($s->get('navigation_group'), $groups)) {
281
                        continue;
282
                    }
283
284
                    $ul->appendChild(new XMLElement('li', $s->get('navigation_group')));
285
                    $groups[] = $s->get('navigation_group');
286
                }
287
288
                $navgroupdiv->appendChild($ul);
289
            }
290
291
            $div->appendChild($navgroupdiv);
292
            $fieldset->appendChild($div);
293
            $this->Form->appendChild($fieldset);
294
295
            $this->addSectionOptions($meta);
296
297
            $fieldset = new XMLElement('fieldset');
298
            $fieldset->setAttribute('class', 'settings');
299
300
            $legend = new XMLElement('legend', __('Fields'));
301
            $legend->setAttribute('id', 'fields-legend');
302
            $fieldset->appendChild($legend);
303
304
            $div = new XMLElement('div', null, array('class' => 'frame', 'id' => 'fields-duplicator'));
305
306
            $ol = new XMLElement('ol');
307
            $ol->setAttribute('data-add', __('Add field'));
308
            $ol->setAttribute('data-remove', __('Remove field'));
309
310
            if (!$showEmptyTemplate) {
311
                foreach ($fields as $position => $data) {
312
                    if ($input = FieldManager::create($data['type'])) {
313
                        $input->setArray($data);
314
315
                        $wrapper = new XMLElement('li');
316
317
                        $input->set('sortorder', $position);
318
                        $input->displaySettingsPanel($wrapper,
319
                            (isset($this->_errors[$position]) ? $this->_errors[$position] : null));
320
                        $ol->appendChild($wrapper);
321
                    }
322
                }
323
            }
324
325
            foreach (FieldManager::listAll() as $type) {
326
                if ($type = FieldManager::create($type)) {
327
                    $types[] = $type;
328
                }
329
            }
330
331
            uasort($types, function ($a, $b) {
332
                return strnatcasecmp($a->_name, $b->_name);
333
            });
334
335 View Code Duplication
            foreach ($types as $type) {
336
                $defaults = array();
337
338
                $type->findDefaults($defaults);
339
                $type->setArray($defaults);
340
341
                $wrapper = new XMLElement('li');
342
                $wrapper->setAttribute('class',
343
                    'template field-' . $type->handle() . ($type->mustBeUnique() ? ' unique' : null));
344
                $wrapper->setAttribute('data-type', $type->handle());
345
346
                $type->set('sortorder', '-1');
347
                $type->displaySettingsPanel($wrapper);
348
349
                $ol->appendChild($wrapper);
350
            }
351
352
            $div->appendChild($ol);
353
            $fieldset->appendChild($div);
354
355
            $this->Form->appendChild($fieldset);
356
357
            $div = new XMLElement('div');
358
            $div->setAttribute('class', 'actions');
359
            $div->appendChild(Widget::Input('action[save]', __('Create Section'), 'submit', array('accesskey' => 's')));
360
361
            $this->Form->appendChild($div);
362
        }
363
364
        public function addSectionOptions(array &$meta = null)
365
        {
366
            $fieldset = new XMLElement('fieldset');
367
            $fieldset->setAttribute('class', 'settings');
368
            $fieldset->appendChild(new XMLElement('legend', __('Options')));
369
370
            $div = new XMLElement('div', null, array('class' => 'two columns'));
371
372
            $hidediv = new XMLElement('div', null, array('class' => 'column'));
373
            $label = Widget::Checkbox('meta[hidden]', $meta['hidden'], __('Hide this section from the back-end menu'));
374
            $hidediv->appendChild($label);
375
            $div->appendChild($hidediv);
376
377
            $filterdiv = new XMLElement('div', null, array('class' => 'column'));
378
            $label = Widget::Checkbox('meta[filter]', $meta['filter'], __('Allow filtering of section entries'));
379
            $filterdiv->appendChild($label);
380
381
            $div->appendChild($filterdiv);
382
            $fieldset->appendChild($div);
383
            $this->Form->appendChild($fieldset);
384
385
            /**
386
             * Allows extensions to add elements to the header of the Section Editor
387
             * form. Usually for section settings, this delegate is passed the current
388
             * `$meta` array and the `$this->_errors` array.
389
             *
390
             * @delegate AddSectionElements
391
             * @since Symphony 2.2
392
             * @param string $context
393
             * '/blueprints/sections/'
394
             * @param XMLElement $form
395
             *  An XMLElement of the current `$this->Form`, just after the Section
396
             *  settings have been appended, but before the Fields duplicator
397
             * @param array $meta
398
             *  The current $_POST['meta'] array
399
             * @param array $errors
400
             *  The current errors array
401
             */
402
            Symphony::ExtensionManager()->notifyMembers('AddSectionElements', '/blueprints/sections/', array(
403
                'form' => &$this->Form,
404
                'meta' => &$meta,
405
                'errors' => &$this->_errors
406
            ));
407
        }
408
409
        public function __viewEdit()
0 ignored issues
show
Coding Style introduced by
__viewEdit uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
410
        {
411
            $section_id = $this->_context['id'];
412
413 View Code Duplication
            if (!$section = SectionManager::fetch($section_id)) {
414
                Administration::instance()->throwCustomError(
415
                    __('The Section, %s, could not be found.', array($section_id)),
416
                    __('Unknown Section'),
417
                    Page::HTTP_STATUS_NOT_FOUND
418
                );
419
            }
420
421
            $meta = $section->get();
422
            $section_id = $meta['id'];
423
            $types = array();
424
425
            $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
426
427 View Code Duplication
            if ($formHasErrors) {
428
                $this->pageAlert(
429
                    __('An error occurred while processing this form. See below for details.'),
430
                    Alert::ERROR
431
                );
432
433
                // These alerts are only valid if the form doesn't have errors
434
            } elseif (isset($this->_context['flag'])) {
435
                $time = Widget::Time();
436
437
                switch ($this->_context['flag']) {
438
                    case 'saved':
439
                        $message = __('Section updated at %s.', array($time->generate()));
440
                        break;
441
                    case 'created':
442
                        $message = __('Section created at %s.', array($time->generate()));
443
                }
444
445
                $this->pageAlert(
446
                    $message
0 ignored issues
show
Bug introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
447
                    . ' <a href="' . SYMPHONY_URL . '/blueprints/sections/new/" accesskey="c">'
448
                    . __('Create another?')
449
                    . '</a> <a href="' . SYMPHONY_URL . '/blueprints/sections/" accesskey="a">'
450
                    . __('View all Sections')
451
                    . '</a>',
452
                    Alert::SUCCESS
453
                );
454
            }
455
456
            if (isset($_POST['fields'])) {
457
                $fields = array();
458
459
                if (is_array($_POST['fields']) && !empty($_POST['fields'])) {
460
                    foreach ($_POST['fields'] as $position => $data) {
461
                        if ($fields[$position] = FieldManager::create($data['type'])) {
462
                            $fields[$position]->setArray($data);
463
                            $fields[$position]->set('sortorder', $position);
464
                        }
465
                    }
466
                }
467
            } else {
468
                $fields = FieldManager::fetch(null, $section_id);
469
                $fields = array_values($fields);
470
            }
471
472
            if (isset($_POST['meta'])) {
473
                $meta = $_POST['meta'];
474
                if ($meta['name'] === '') {
475
                    $meta['name'] = $section->get('name');
476
                }
477
            }
478
479
            $this->setPageType('form');
480
            $this->setTitle(__('%1$s &ndash; %2$s &ndash; %3$s', array($meta['name'], __('Sections'), __('Symphony'))));
481
            $this->appendSubheading($meta['name'],
482
                Widget::Anchor(__('View Entries'), SYMPHONY_URL . '/publish/' . $section->get('handle'),
483
                    __('View Section Entries'), 'button')
484
            );
485
            $this->insertBreadcrumbs(array(
486
                Widget::Anchor(__('Sections'), SYMPHONY_URL . '/blueprints/sections/'),
487
            ));
488
489
            $fieldset = new XMLElement('fieldset');
490
            $fieldset->setAttribute('class', 'settings');
491
            $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
492
493
            $namediv = new XMLElement('div', null, array('class' => 'column'));
494
495
            $label = Widget::Label(__('Name'));
496
            $label->appendChild(Widget::Input('meta[name]',
497
                (isset($meta['name']) ? General::sanitize($meta['name']) : null)));
498
499 View Code Duplication
            if (isset($this->_errors['name'])) {
500
                $namediv->appendChild(Widget::Error($label, $this->_errors['name']));
501
            } else {
502
                $namediv->appendChild($label);
503
            }
504
505
            $fieldset->appendChild($namediv);
506
507
            $div = new XMLElement('div', null, array('class' => 'two columns'));
508
509
            $handlediv = new XMLElement('div', null, array('class' => 'column'));
510
511
            $label = Widget::Label(__('Handle'));
512
            $label->appendChild(Widget::Input('meta[handle]',
513
                (isset($meta['handle']) ? General::sanitize($meta['handle']) : null)));
514
515 View Code Duplication
            if (isset($this->_errors['handle'])) {
516
                $handlediv->appendChild(Widget::Error($label, $this->_errors['handle']));
517
            } else {
518
                $handlediv->appendChild($label);
519
            }
520
521
            $div->appendChild($handlediv);
522
523
            $navgroupdiv = new XMLElement('div', null, array('class' => 'column'));
524
525
            $sections = SectionManager::fetch(null, 'ASC', 'sortorder');
526
            $label = Widget::Label(__('Navigation Group'));
527
            $label->appendChild(Widget::Input('meta[navigation_group]', $meta['navigation_group']));
528
529 View Code Duplication
            if (isset($this->_errors['navigation_group'])) {
530
                $navgroupdiv->appendChild(Widget::Error($label, $this->_errors['navigation_group']));
531
            } else {
532
                $navgroupdiv->appendChild($label);
533
            }
534
535 View Code Duplication
            if (is_array($sections) && !empty($sections)) {
536
                $ul = new XMLElement('ul', null,
537
                    array('class' => 'tags singular', 'data-interactive' => 'data-interactive'));
538
                $groups = array();
539
540
                foreach ($sections as $s) {
541
                    if (in_array($s->get('navigation_group'), $groups)) {
542
                        continue;
543
                    }
544
545
                    $ul->appendChild(new XMLElement('li', $s->get('navigation_group')));
546
                    $groups[] = $s->get('navigation_group');
547
                }
548
549
                $navgroupdiv->appendChild($ul);
550
            }
551
552
            $div->appendChild($navgroupdiv);
553
            $fieldset->appendChild($div);
554
            $this->Form->appendChild($fieldset);
555
556
            $this->addSectionOptions($meta);
557
558
            $fieldset = new XMLElement('fieldset');
559
            $fieldset->setAttribute('class', 'settings');
560
561
            $legend = new XMLElement('legend', __('Fields'));
562
            $legend->setAttribute('id', 'fields-legend');
563
            $fieldset->appendChild($legend);
564
565
            $div = new XMLElement('div', null, array('class' => 'frame', 'id' => 'fields-duplicator'));
566
567
            $ol = new XMLElement('ol');
568
            $ol->setAttribute('data-add', __('Add field'));
569
            $ol->setAttribute('data-remove', __('Remove field'));
570
571
            if (is_array($fields) && !empty($fields)) {
572
                foreach ($fields as $position => $field) {
573
                    $wrapper = new XMLElement('li', null,
574
                        array('class' => 'field-' . $field->handle() . ($field->mustBeUnique() ? ' unique' : null)));
575
                    $wrapper->setAttribute('data-type', $field->handle());
576
577
                    $field->set('sortorder', $position);
578
                    $field->displaySettingsPanel($wrapper,
579
                        (isset($this->_errors[$position]) ? $this->_errors[$position] : null));
580
                    $ol->appendChild($wrapper);
581
                }
582
            }
583
584
            foreach (FieldManager::listAll() as $type) {
585
                if ($type = FieldManager::create($type)) {
586
                    array_push($types, $type);
587
                }
588
            }
589
590
            uasort($types, function ($a, $b) {
591
                return strnatcasecmp($a->_name, $b->_name);
592
            });
593
594 View Code Duplication
            foreach ($types as $type) {
595
                $defaults = array();
596
597
                $type->findDefaults($defaults);
598
                $type->setArray($defaults);
599
600
                $wrapper = new XMLElement('li');
601
602
                $wrapper->setAttribute('class',
603
                    'template field-' . $type->handle() . ($type->mustBeUnique() ? ' unique' : null));
604
                $wrapper->setAttribute('data-type', $type->handle());
605
606
                $type->set('sortorder', '-1');
607
                $type->displaySettingsPanel($wrapper);
608
609
                $ol->appendChild($wrapper);
610
            }
611
612
            $div->appendChild($ol);
613
            $fieldset->appendChild($div);
614
615
            $this->Form->appendChild($fieldset);
616
617
            $div = new XMLElement('div');
618
            $div->setAttribute('class', 'actions');
619
            $div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', array('accesskey' => 's')));
620
621
            $button = new XMLElement('button', __('Delete'));
622
            $button->setAttributeArray(array(
623
                'name' => 'action[delete]',
624
                'class' => 'button confirm delete',
625
                'title' => __('Delete this section'),
626
                'type' => 'submit',
627
                'accesskey' => 'd',
628
                'data-message' => __('Are you sure you want to delete this section?')
629
            ));
630
            $div->appendChild($button);
631
632
            $this->Form->appendChild($div);
633
        }
634
635
        public function __actionIndex()
0 ignored issues
show
Coding Style introduced by
__actionIndex uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
636
        {
637
            $checked = (is_array($_POST['items'])) ? array_keys($_POST['items']) : null;
638
639
            if (is_array($checked) && !empty($checked)) {
640
                /**
641
                 * Extensions can listen for any custom actions that were added
642
                 * through `AddCustomPreferenceFieldsets` or `AddCustomActions`
643
                 * delegates.
644
                 *
645
                 * @delegate CustomActions
646
                 * @since Symphony 2.3.2
647
                 * @param string $context
648
                 *  '/blueprints/sections/'
649
                 * @param array $checked
650
                 *  An array of the selected rows. The value is usually the ID of the
651
                 *  the associated object.
652
                 */
653
                Symphony::ExtensionManager()->notifyMembers('CustomActions', '/blueprints/sections/', array(
654
                    'checked' => $checked
655
                ));
656
657
                if ($_POST['with-selected'] === 'delete') {
658
                    /**
659
                     * Just prior to calling the Section Manager's delete function
660
                     *
661
                     * @delegate SectionPreDelete
662
                     * @since Symphony 2.2
663
                     * @param string $context
664
                     * '/blueprints/sections/'
665
                     * @param array $section_ids
666
                     *  An array of Section ID's passed by reference
667
                     */
668
                    Symphony::ExtensionManager()->notifyMembers('SectionPreDelete', '/blueprints/sections/',
669
                        array('section_ids' => &$checked));
670
671
                    foreach ($checked as $section_id) {
672
                        SectionManager::delete($section_id);
673
                    }
674
675
                    /**
676
                     * Just after calling the Section Manager's delete function
677
                     *
678
                     * @delegate SectionPostDelete
679
                     * @since Symphony 3.0.0
680
                     * @param string $context
681
                     * '/blueprints/sections/'
682
                     * @param array $section_ids
683
                     *  An array of Section ID's that were deleted
684
                     */
685
                    Symphony::ExtensionManager()->notifyMembers('SectionPostDelete', '/blueprints/sections/',
686
                        array('section_ids' => $checked));
687
688
                    redirect(SYMPHONY_URL . '/blueprints/sections/');
689
                } elseif ($_POST['with-selected'] === 'delete-entries') {
690
                    foreach ($checked as $section_id) {
691
                        $entries = EntryManager::fetch(null, $section_id, null, null, null, null, false, false, null,
692
                            false);
693
                        $entry_ids = array();
694
695
                        foreach ($entries as $entry) {
0 ignored issues
show
Bug introduced by
The expression $entries of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
696
                            $entry_ids[] = $entry['id'];
697
                        }
698
699
                        /**
700
                         * Prior to deletion of entries.
701
                         *
702
                         * @delegate Delete
703
                         * @param string $context
704
                         * '/publish/'
705
                         * @param array $entry_id
706
                         *  An array of Entry ID's that are about to be deleted, passed by reference
707
                         */
708
                        Symphony::ExtensionManager()->notifyMembers('Delete', '/publish/',
709
                            array('entry_id' => &$entry_ids));
710
711
                        EntryManager::delete($entry_ids, $section_id);
712
                    }
713
714
                    redirect(SYMPHONY_URL . '/blueprints/sections/');
715
                } elseif (preg_match('/^set-navigation-group-/', $_POST['with-selected'])) {
716
                    $navigation_group = preg_replace('/^set-navigation-group-/', null, $_POST['with-selected']);
717
718
                    foreach ($checked as $section_id) {
719
                        SectionManager::edit($section_id, array('navigation_group' => urldecode($navigation_group)));
720
                    }
721
722
                    redirect(SYMPHONY_URL . '/blueprints/sections/');
723
                }
724
            }
725
        }
726
727
        public function __actionEdit()
728
        {
729
            return $this->__actionNew();
730
        }
731
732
        public function __actionNew()
0 ignored issues
show
Coding Style introduced by
__actionNew uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
733
        {
734
            if (@array_key_exists('save', $_POST['action']) || @array_key_exists('done', $_POST['action'])) {
735
                $canProceed = true;
736
                $edit = ($this->_context['action'] === "edit");
737
                $this->_errors = array();
738
739
                $fields = isset($_POST['fields']) ? $_POST['fields'] : array();
740
                $meta = $_POST['meta'];
741
742
                if ($edit) {
743
                    $section_id = $this->_context['id'];
744
                    $existing_section = SectionManager::fetch($section_id);
745
                }
746
747
                // Check handle to ensure it is unique
748
                $meta['handle'] = $_POST['meta']['handle'] = Lang::createHandle((isset($meta['handle']) && !empty($meta['handle']))
749
                    ? $meta['handle']
750
                    : $meta['name']);
751
752
                // Check to ensure all the required section fields are filled
753
                if (!isset($meta['name']) || strlen(trim($meta['name'])) === 0) {
754
                    $this->_errors['name'] = __('This is a required field.');
755
                    $canProceed = false;
756
757
                    // Check for duplicate section handle during edit
758
                } elseif ($edit) {
759
                    $s = SectionManager::fetchIDFromHandle(Lang::createHandle($meta['handle']));
760
761
                    if (
762
                        $meta['handle'] !== $existing_section->get('handle')
0 ignored issues
show
Bug introduced by
The variable $existing_section does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
763
                        && !is_null($s) && $s !== $section_id
0 ignored issues
show
Bug introduced by
The variable $section_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
764
                    ) {
765
                        $this->_errors['handle'] = __('A Section with the handle %s already exists',
766
                            array('<code>' . $meta['handle'] . '</code>'));
767
                        $canProceed = false;
768
                    }
769
770
                    // Existing section during creation
771
                } elseif (!is_null(SectionManager::fetchIDFromHandle(Lang::createHandle($meta['handle'])))) {
772
                    $this->_errors['handle'] = __('A Section with the handle %s already exists',
773
                        array('<code>' . $meta['handle'] . '</code>'));
774
                    $canProceed = false;
775
                }
776
777
                // Check to ensure all the required section fields are filled
778 View Code Duplication
                if (!isset($meta['navigation_group']) || strlen(trim($meta['navigation_group'])) === 0) {
779
                    $this->_errors['navigation_group'] = __('This is a required field.');
780
                    $canProceed = false;
781
                }
782
783
                // Basic custom field checking
784
                if (is_array($fields) && !empty($fields)) {
785
                    // Check for duplicate CF names
786
                    if ($canProceed) {
787
                        $name_list = array();
788
789
                        foreach ($fields as $position => $data) {
790
                            if (trim($data['element_name']) === '') {
791
                                $data['element_name'] = $fields[$position]['element_name'] = $_POST['fields'][$position]['element_name'] = Lang::createHandle($data['label'],
792
                                    255, '-', false, true, array('@^[\d-]+@i' => ''));
793
                            }
794
795
                            if (trim($data['element_name']) !== '' && in_array($data['element_name'], $name_list)) {
796
                                $this->_errors[$position] = array('element_name' => __('A field with this handle already exists. All handle must be unique.'));
797
                                $canProceed = false;
798
                                break;
799
                            }
800
801
                            $name_list[] = $data['element_name'];
802
                        }
803
                    }
804
805
                    if ($canProceed) {
806
                        $unique = array();
807
808
                        foreach ($fields as $position => $data) {
809
                            $field = FieldManager::create($data['type']);
810
                            $field->setFromPOST($data);
811
812
                            if (isset($existing_section)) {
813
                                $field->set('parent_section', $existing_section->get('id'));
814
                            }
815
816
                            if ($field->mustBeUnique() && !in_array($field->get('type'), $unique)) {
817
                                $unique[] = $field->get('type');
818
                            } elseif ($field->mustBeUnique() && in_array($field->get('type'), $unique)) {
819
                                // Warning. cannot have 2 of this field!
820
                                $canProceed = false;
821
                                $this->_errors[$position] = array(
822
                                    'label' => __('There is already a field of type %s. There can only be one per section.',
823
                                        array('<code>' . $field->handle() . '</code>'))
824
                                );
825
                            }
826
827
                            $errors = array();
828
829
                            if (Field::__OK__ !== $field->checkFields($errors, false) && !empty($errors)) {
830
                                $this->_errors[$position] = $errors;
831
                                $canProceed = false;
832
                            }
833
                        }
834
                    }
835
                }
836
837
                if ($canProceed) {
838
                    // If we are creating a new Section
839
                    if (!$edit) {
840
                        $meta['sortorder'] = SectionManager::fetchNextSortOrder();
841
842
                        /**
843
                         * Just prior to saving the Section settings. Use with caution as
844
                         * there is no additional processing to ensure that Field's or Section's
845
                         * are unique.
846
                         *
847
                         * @delegate SectionPreCreate
848
                         * @since Symphony 2.2
849
                         * @param string $context
850
                         * '/blueprints/sections/'
851
                         * @param array $meta
852
                         *  The section's settings, passed by reference
853
                         * @param array $fields
854
                         *  An associative array of the fields that will be saved to this
855
                         *  section with the key being the position in the Section Editor
856
                         *  and the value being a Field object, passed by reference
857
                         */
858
                        Symphony::ExtensionManager()->notifyMembers('SectionPreCreate', '/blueprints/sections/',
859
                            array('meta' => &$meta, 'fields' => &$fields));
860
861
                        if (!$section_id = SectionManager::add($meta)) {
862
                            $this->pageAlert(__('An unknown database occurred while attempting to create the section.'),
863
                                Alert::ERROR);
864
                        }
865
866
                        // We are editing a Section
867
                    } else {
868
869
                        /**
870
                         * Just prior to updating the Section settings. Use with caution as
871
                         * there is no additional processing to ensure that Field's or Section's
872
                         * are unique.
873
                         *
874
                         * @delegate SectionPreEdit
875
                         * @since Symphony 2.2
876
                         * @param string $context
877
                         * '/blueprints/sections/'
878
                         * @param integer $section_id
879
                         *  The Section ID that is about to be edited.
880
                         * @param array $meta
881
                         *  The section's settings, passed by reference
882
                         * @param array $fields
883
                         *  An associative array of the fields that will be saved to this
884
                         *  section with the key being the position in the Section Editor
885
                         *  and the value being a Field object, passed by reference
886
                         */
887
                        Symphony::ExtensionManager()->notifyMembers('SectionPreEdit', '/blueprints/sections/',
888
                            array('section_id' => $section_id, 'meta' => &$meta, 'fields' => &$fields));
889
890
                        if (!SectionManager::edit($section_id, $meta)) {
891
                            $canProceed = false;
892
                            $this->pageAlert(__('An unknown database occurred while attempting to create the section.'),
893
                                Alert::ERROR);
894
                        }
895
                    }
896
897
                    if ($section_id && $canProceed) {
898
                        if ($edit) {
899
                            // Delete missing CF's
900
                            $id_list = array();
901
902
                            if (is_array($fields) && !empty($fields)) {
903
                                foreach ($fields as $position => $data) {
904
                                    if (isset($data['id'])) {
905
                                        $id_list[] = (int)$data['id'];
906
                                    }
907
                                }
908
                            }
909
910
                            $q = Database::addPlaceholders($id_list);
911
                            $missing_cfs = Symphony::Database()->fetchCol('id', "
912
                            SELECT `id` 
913
                            FROM `tbl_fields` 
914
                            WHERE `parent_section` = ? AND `id` NOT IN (" . $q . ")",
915
                                array_merge(array($section_id), $id_list)
916
                            );
917
918
                            if (is_array($missing_cfs) && !empty($missing_cfs)) {
919
                                foreach ($missing_cfs as $id) {
920
                                    FieldManager::delete($id);
921
                                }
922
                            }
923
                        }
924
925
                        // Save each custom field
926
                        if (is_array($fields) && !empty($fields)) {
927
                            foreach ($fields as $position => $data) {
928
                                $field = FieldManager::create($data['type']);
929
                                $field->setFromPOST($data);
930
                                $field->set('sortorder', (string)$position);
931
                                $field->set('parent_section', $section_id);
932
933
                                $newField = !(boolean)$field->get('id');
934
935
                                $field->commit();
936
                                $field_id = $field->get('id');
937
938
                                if ($field_id) {
939
                                    if ($newField) {
940
                                        /**
941
                                         * After creation of a Field.
942
                                         *
943
                                         * @delegate FieldPostCreate
944
                                         * @param string $context
945
                                         * '/blueprints/sections/'
946
                                         * @param Field $field
947
                                         *  The Field object, passed by reference
948
                                         * @param array $data
949
                                         *  The settings for ths `$field`, passed by reference
950
                                         */
951
                                        Symphony::ExtensionManager()->notifyMembers('FieldPostCreate',
952
                                            '/blueprints/sections/', array('field' => &$field, 'data' => &$data));
953
                                    } else {
954
                                        /**
955
                                         * After editing of a Field.
956
                                         *
957
                                         * @delegate FieldPostEdit
958
                                         * @param string $context
959
                                         * '/blueprints/sections/'
960
                                         * @param Field $field
961
                                         *  The Field object, passed by reference
962
                                         * @param array $data
963
                                         *  The settings for ths `$field`, passed by reference
964
                                         */
965
                                        Symphony::ExtensionManager()->notifyMembers('FieldPostEdit',
966
                                            '/blueprints/sections/', array('field' => &$field, 'data' => &$data));
967
                                    }
968
                                }
969
                            }
970
                        }
971
972
                        if (!$edit) {
973
                            /**
974
                             * After the Section has been created, and all the Field's have been
975
                             * created for this section, but just before the redirect
976
                             *
977
                             * @delegate SectionPostCreate
978
                             * @since Symphony 2.2
979
                             * @param string $context
980
                             * '/blueprints/sections/'
981
                             * @param integer $section_id
982
                             *  The newly created Section ID.
983
                             */
984
                            Symphony::ExtensionManager()->notifyMembers('SectionPostCreate', '/blueprints/sections/',
985
                                array('section_id' => $section_id));
986
987
                            redirect(SYMPHONY_URL . "/blueprints/sections/edit/$section_id/created/");
988
                        } else {
989
                            /**
990
                             * After the Section has been updated, and all the Field's have been
991
                             * updated for this section, but just before the redirect
992
                             *
993
                             * @delegate SectionPostEdit
994
                             * @since Symphony 2.2
995
                             * @param string $context
996
                             * '/blueprints/sections/'
997
                             * @param integer $section_id
998
                             *  The edited Section ID.
999
                             */
1000
                            Symphony::ExtensionManager()->notifyMembers('SectionPostEdit', '/blueprints/sections/',
1001
                                array('section_id' => $section_id));
1002
1003
                            redirect(SYMPHONY_URL . "/blueprints/sections/edit/$section_id/saved/");
1004
                        }
1005
                    }
1006
                }
1007
            }
1008
1009
            if (@array_key_exists("delete", $_POST['action'])) {
1010
                $section_id = array($this->_context['id']);
1011
1012
                /**
1013
                 * Just prior to calling the Section Manager's delete function
1014
                 *
1015
                 * @delegate SectionPreDelete
1016
                 * @since Symphony 2.2
1017
                 * @param string $context
1018
                 * '/blueprints/sections/'
1019
                 * @param array $section_ids
1020
                 *  An array of Section ID's passed by reference
1021
                 */
1022
                Symphony::ExtensionManager()->notifyMembers('SectionPreDelete', '/blueprints/sections/',
1023
                    array('section_ids' => &$section_id));
1024
1025
                foreach ($section_id as $section) {
1026
                    SectionManager::delete($section);
1027
                }
1028
1029
                redirect(SYMPHONY_URL . '/blueprints/sections/');
1030
            }
1031
        }
1032
    }
1033