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.
Passed
Pull Request — master (#2835)
by
unknown
06:01
created

contentBlueprintsPages   F

Complexity

Total Complexity 128

Size/Duplication

Total Lines 955
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 955
rs 1.263
wmc 128

10 Methods

Rating   Name   Duplication   Size   Complexity  
D __viewIndex() 0 144 19
B __actionIndex() 0 26 5
F __viewEdit() 0 311 42
F __actionEdit() 0 264 39
C __actionDelete() 0 79 8
A __viewNew() 0 3 1
B __actionTemplate() 0 48 6
B insertBreadcrumbsUsingPageIdentifier() 0 41 6
A __actionNew() 0 3 1
A __compare_pages() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like contentBlueprintsPages 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 contentBlueprintsPages, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @package content
5
 */
6
7
/**
8
 * Developers can create new Frontend pages from this class. It provides
9
 * an index view of all the pages in this Symphony install as well as the
10
 * forms for the creation/editing of a Page
11
 */
12
13
class contentBlueprintsPages extends AdministrationPage
14
{
15
    public $_errors = array();
16
    protected $_hilights = array();
17
18
    public function insertBreadcrumbsUsingPageIdentifier($page_id, $preserve_last = true)
19
    {
20
        if ($page_id == 0) {
21
            return $this->insertBreadcrumbs(
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->insertBreadcrumbs...'/blueprints/pages/'))) targeting AdministrationPage::insertBreadcrumbs() 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...
22
                array(Widget::Anchor(__('Pages'), SYMPHONY_URL . '/blueprints/pages/'))
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...
23
            );
24
        }
25
26
        $pages = PageManager::resolvePage($page_id, 'handle');
27
28
        foreach ($pages as &$page) {
29
            // If we are viewing the Page Editor, the Breadcrumbs should link
30
            // to the parent's Page Editor.
31
            if ($this->_context[0] == 'edit') {
32
                $page = Widget::Anchor(
33
                    PageManager::fetchTitleFromHandle($page),
34
                    SYMPHONY_URL . '/blueprints/pages/edit/' . PageManager::fetchIDFromHandle($page) . '/'
35
                );
36
37
                // If the pages index is nested, the Breadcrumb should link to the
38
                // Pages Index filtered by parent
39
            } elseif (Symphony::Configuration()->get('pages_table_nest_children', 'symphony') == 'yes') {
40
                $page = Widget::Anchor(
41
                    PageManager::fetchTitleFromHandle($page),
42
                    SYMPHONY_URL . '/blueprints/pages/?parent=' . PageManager::fetchIDFromHandle($page)
43
                );
44
45
                // If there is no nesting on the Pages Index, the breadcrumb is
46
                // not a link, just plain text
47
            } else {
48
                $page = new XMLElement('span', PageManager::fetchTitleFromHandle($page));
49
            }
50
        }
51
52
        if (!$preserve_last) {
53
            array_pop($pages);
54
        }
55
56
        $this->insertBreadcrumbs(array_merge(
57
            array(Widget::Anchor(__('Pages'), SYMPHONY_URL . '/blueprints/pages/')),
58
            $pages
59
        ));
60
    }
61
62
    public function __viewIndex()
63
    {
64
        $this->setPageType('table');
65
        $this->setTitle(__('%1$s &ndash; %2$s', array(__('Pages'), __('Symphony'))));
66
67
        $nesting = Symphony::Configuration()->get('pages_table_nest_children', 'symphony') == 'yes';
68
69
        if ($nesting && isset($_GET['parent']) && is_numeric($_GET['parent'])) {
70
            $parent = PageManager::fetchPageByID((int)$_GET['parent'], array('title', 'id'));
71
        }
72
73
        $this->appendSubheading(isset($parent) ? $parent['title'] : __('Pages'), Widget::Anchor(
74
            __('Create New'), Administration::instance()->getCurrentPageURL() . 'new/' . ($nesting && isset($parent) ? "?parent={$parent['id']}" : null),
75
            __('Create a new page'), 'create button', null, array('accesskey' => 'c')
76
        ));
77
78
        if (isset($parent)) {
79
            $this->insertBreadcrumbsUsingPageIdentifier($parent['id'], false);
80
        }
81
82
        $aTableHead = array(
83
            array(__('Name'), 'col'),
84
            array(__('Template'), 'col'),
85
            array('<abbr title="' . __('Universal Resource Locator') . '">' . __('URL') . '</abbr>', 'col'),
86
            array(__('Parameters'), 'col'),
87
            array(__('Type'), 'col')
88
        );
89
        $aTableBody = array();
90
91
        $pagesQuery = (new PageManager)->select()->includeTypes();
92
        if ($nesting) {
93
            $aTableHead[] = array(__('Children'), 'col');
94
            $pagesQuery->where(['parent' => isset($parent) ? $parent['id'] : null]);
95
        }
96
97
        $pages = $pagesQuery->execute()->rows();
98
99
        if (empty($pages)) {
100
            $aTableBody = array(Widget::TableRow(array(
101
                Widget::TableData(__('None found.'), 'inactive', null, count($aTableHead))
102
            ), 'odd'));
103
        } else {
104
            foreach ($pages as $page) {
105
                $class = array();
106
107
                $page_title = ($nesting ? $page['title'] : PageManager::resolvePageTitle($page['id']));
108
                $page_url = URL . '/' . PageManager::resolvePagePath($page['id']) . '/';
0 ignored issues
show
Bug introduced by
The constant URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
109
                $page_edit_url = Administration::instance()->getCurrentPageURL() . 'edit/' . $page['id'] . '/';
110
                $page_template = PageManager::createFilePath($page['path'], $page['handle']);
111
112
                $col_title = Widget::TableData(Widget::Anchor($page_title, $page_edit_url, $page['handle']));
113
                $col_title->appendChild(Widget::Label(__('Select Page %s', array($page_title)), null, 'accessible', null, array(
114
                    'for' => 'page-' . $page['id']
115
                )));
116
                $col_title->appendChild(Widget::Input('items['.$page['id'].']', 'on', 'checkbox', array(
117
                    'id' => 'page-' . $page['id']
118
                )));
119
120
                $col_template = Widget::TableData($page_template . '.xsl');
121
122
                $col_url = Widget::TableData(Widget::Anchor($page_url, $page_url));
123
124
                if ($page['params']) {
125
                    $col_params = Widget::TableData(trim($page['params'], '/'));
126
                } else {
127
                    $col_params = Widget::TableData(__('None'), 'inactive');
128
                }
129
130
                if (!empty($page['type'])) {
131
                    $col_types = Widget::TableData(implode(', ', $page['type']));
132
                } else {
133
                    $col_types = Widget::TableData(__('None'), 'inactive');
134
                }
135
136
                if (in_array($page['id'], $this->_hilights)) {
137
                    $class[] = 'failed';
138
                }
139
140
                $columns = array($col_title, $col_template, $col_url, $col_params, $col_types);
141
142
                if ($nesting) {
143
                    if (PageManager::hasChildPages($page['id'])) {
144
                        $col_children = Widget::TableData(
145
                            Widget::Anchor(PageManager::getChildPagesCount($page['id']) . ' &rarr;',
146
                            SYMPHONY_URL . '/blueprints/pages/?parent=' . $page['id'])
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...
147
                        );
148
                    } else {
149
                        $col_children = Widget::TableData(__('None'), 'inactive');
150
                    }
151
152
                    $columns[] = $col_children;
153
                }
154
155
                $aTableBody[] = Widget::TableRow(
156
                    $columns,
157
                    implode(' ', $class)
158
                );
159
            }
160
        }
161
162
        $table = Widget::Table(
163
            Widget::TableHead($aTableHead), null,
164
            Widget::TableBody($aTableBody), 'orderable selectable',
165
            null, array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive')
166
        );
167
168
        $this->Form->appendChild($table);
169
170
        $version = new XMLElement('p', 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), array(
171
            'id' => 'version'
172
        ));
173
        $this->Form->appendChild($version);
174
175
        $tableActions = new XMLElement('div');
176
        $tableActions->setAttribute('class', 'actions');
177
178
        $options = array(
179
            array(null, false, __('With Selected...')),
180
            array('delete', false, __('Delete'), 'confirm', null, array(
181
                'data-message' => __('Are you sure you want to delete the selected pages?')
182
            ))
183
        );
184
185
        /**
186
         * Allows an extension to modify the existing options for this page's
187
         * With Selected menu. If the `$options` parameter is an empty array,
188
         * the 'With Selected' menu will not be rendered.
189
         *
190
         * @delegate AddCustomActions
191
         * @since Symphony 2.3.2
192
         * @param string $context
193
         * '/blueprints/pages/'
194
         * @param array $options
195
         *  An array of arrays, where each child array represents an option
196
         *  in the With Selected menu. Options should follow the same format
197
         *  expected by `Widget::__SelectBuildOption`. Passed by reference.
198
         */
199
        Symphony::ExtensionManager()->notifyMembers('AddCustomActions', '/blueprints/pages/', array(
200
            'options' => &$options
201
        ));
202
203
        if (!empty($options)) {
204
            $tableActions->appendChild(Widget::Apply($options));
205
            $this->Form->appendChild($tableActions);
206
        }
207
    }
208
209
    public function __viewNew()
210
    {
211
        $this->__viewEdit();
212
    }
213
214
    public function __viewEdit()
215
    {
216
        $this->setPageType('form');
217
        $fields = array("title"=>null, "handle"=>null, "parent"=>null, "params"=>null, "type"=>null, "data_sources"=>null);
218
        $existing = $fields;
219
        $canonical_link = '/blueprints/pages/';
220
        $nesting = (Symphony::Configuration()->get('pages_table_nest_children', 'symphony') == 'yes');
221
222
        // Verify page exists:
223
        if ($this->_context[0] === 'edit') {
224
            if (!$page_id = (int)$this->_context[1]) {
225
                redirect(SYMPHONY_URL . '/blueprints/pages/');
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...
226
            }
227
228
            $existing = PageManager::fetchPageByID($page_id);
229
            $canonical_link .= 'edit/' . $page_id . '/';
230
231
            if (!$existing) {
232
                Administration::instance()->errorPageNotFound();
233
            } else {
234
                $existing['type'] = PageManager::fetchPageTypes($page_id);
235
            }
236
        } else {
237
            $canonical_link .= 'new/';
238
        }
239
240
        // Status message:
241
        if (isset($this->_context[2])) {
242
            $flag = $this->_context[2];
243
            $parent_link_suffix = $message = '';
244
            $time = Widget::Time();
245
246
            if (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) {
247
                $parent_link_suffix = "?parent=" . $_REQUEST['parent'];
248
            } elseif ($nesting && isset($existing) && !is_null($existing['parent'])) {
249
                $parent_link_suffix = '?parent=' . $existing['parent'];
250
            }
251
252
            switch ($flag) {
253
                case 'saved':
254
                    $message = __('Page updated at %s.', array($time->generate()));
255
                    break;
256
                case 'created':
257
                    $message = __('Page created at %s.', array($time->generate()));
258
            }
259
260
            $this->pageAlert(
261
                $message
262
                . ' <a href="' . SYMPHONY_URL . '/blueprints/pages/new/' . $parent_link_suffix . '" accesskey="c">'
263
                . __('Create another?')
264
                . '</a> <a href="' . SYMPHONY_URL . '/blueprints/pages/" accesskey="a">'
265
                . __('View all Pages')
266
                . '</a>',
267
                Alert::SUCCESS
268
            );
269
        }
270
271
        // Find values:
272
        if (isset($_POST['fields'])) {
273
            $fields = $_POST['fields'];
274
        } elseif ($this->_context[0] == 'edit') {
275
            $fields = $existing;
276
277
            if (!is_null($fields['type'])) {
278
                $fields['type'] = implode(', ', $fields['type']);
279
            }
280
281
            $fields['data_sources'] = preg_split('/,/i', $fields['data_sources'], -1, PREG_SPLIT_NO_EMPTY);
282
            $fields['events'] = preg_split('/,/i', $fields['events'], -1, PREG_SPLIT_NO_EMPTY);
283
        } elseif (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) {
284
            $fields['parent'] = $_REQUEST['parent'];
285
            $canonical_link .= '?parent=' . urlencode($_REQUEST['parent']);
286
        }
287
288
        $title = $fields['title'];
289
290
        if (trim($title) == '') {
291
            $title = $existing['title'];
292
        }
293
294
        $this->setTitle(__(
295
            ($title ? '%1$s &ndash; %2$s &ndash; %3$s' : '%2$s &ndash; %3$s'),
296
            array(
297
                $title,
298
                __('Pages'),
299
                __('Symphony')
300
            )
301
        ));
302
        $this->addElementToHead(new XMLElement('link', null, array(
303
            'rel' => 'canonical',
304
            'href' => SYMPHONY_URL . $canonical_link,
305
        )));
306
307
        $page_id = isset($page_id) ? $page_id : null;
308
309
        if (!empty($title)) {
310
            $page_url = URL . '/' . PageManager::resolvePagePath($page_id) . '/';
0 ignored issues
show
Bug introduced by
The constant URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
311
312
            $this->appendSubheading($title, array(
313
                Widget::Anchor(__('View Page'), $page_url, __('View Page on Frontend'), 'button', null, array('target' => '_blank', 'accesskey' => 'v'))
314
            ));
315
        } else {
316
            $this->appendSubheading(!empty($title) ? $title : __('Untitled'));
317
        }
318
319
        if (isset($page_id)) {
320
            $this->insertBreadcrumbsUsingPageIdentifier($page_id, false);
321
        } else {
322
            $_GET['parent'] = isset($_GET['parent']) ? $_GET['parent'] : null;
323
            $this->insertBreadcrumbsUsingPageIdentifier((int)$_GET['parent'], true);
324
        }
325
326
        // Title --------------------------------------------------------------
327
328
        $fieldset = new XMLElement('fieldset');
329
        $fieldset->setAttribute('class', 'settings');
330
        $fieldset->appendChild(new XMLElement('legend', __('Page Settings')));
331
332
        $label = Widget::Label(__('Name'));
333
        $label->appendChild(Widget::Input(
334
            'fields[title]', General::sanitize($fields['title'])
335
        ));
336
337
        if (isset($this->_errors['title'])) {
338
            $label = Widget::Error($label, $this->_errors['title']);
339
        }
340
341
        $fieldset->appendChild($label);
342
343
        // Handle -------------------------------------------------------------
344
345
        $group = new XMLElement('div');
346
        $group->setAttribute('class', 'two columns');
347
        $column = new XMLElement('div');
348
        $column->setAttribute('class', 'column');
349
350
        $label = Widget::Label(__('Handle'));
351
        $label->appendChild(Widget::Input(
352
            'fields[handle]', $fields['handle']
353
        ));
354
355
        if (isset($this->_errors['handle'])) {
356
            $label = Widget::Error($label, $this->_errors['handle']);
357
        }
358
359
        $column->appendChild($label);
360
361
        // Parent ---------------------------------------------------------
362
363
        $label = Widget::Label(__('Parent Page'));
364
365
        $pages = (new PageManager)
366
            ->select(['id'])
367
            ->where(['id' => ['!=' => General::intval($page_id)]])
368
            ->sort('title')
369
            ->execute()
370
            ->rows();
371
372
        $options = array(
373
            array('', false, '/')
374
        );
375
376
        if (!empty($pages)) {
377
            foreach ($pages as $page) {
378
                $options[] = array(
379
                    $page['id'], $fields['parent'] == $page['id'],
380
                    '/' . PageManager::resolvePagePath($page['id'])
381
                );
382
            }
383
384
            usort($options, array($this, '__compare_pages'));
385
        }
386
387
        $label->appendChild(Widget::Select(
388
            'fields[parent]', $options
389
        ));
390
        $column->appendChild($label);
391
        $group->appendChild($column);
392
393
        // Parameters ---------------------------------------------------------
394
395
        $column = new XMLElement('div');
396
        $column->setAttribute('class', 'column');
397
398
        $label = Widget::Label(__('Parameters'));
399
        $label->appendChild(Widget::Input(
400
            'fields[params]', $fields['params'], 'text', array('placeholder' => 'param1/param2')
401
        ));
402
        $column->appendChild($label);
403
404
        // Type -----------------------------------------------------------
405
406
        $label = Widget::Label(__('Type'));
407
        $label->appendChild(Widget::Input('fields[type]', $fields['type']));
408
409
        if (isset($this->_errors['type'])) {
410
            $label = Widget::Error($label, $this->_errors['type']);
411
        }
412
413
        $column->appendChild($label);
414
415
        $tags = new XMLElement('ul');
416
        $tags->setAttribute('class', 'tags');
417
        $tags->setAttribute('data-interactive', 'data-interactive');
418
419
        $types = PageManager::fetchAvailablePageTypes();
420
421
        foreach ($types as $type) {
422
            $tags->appendChild(new XMLElement('li', $type));
423
        }
424
425
        $column->appendChild($tags);
426
        $group->appendChild($column);
427
        $fieldset->appendChild($group);
428
        $this->Form->appendChild($fieldset);
429
430
        // Events -------------------------------------------------------------
431
432
        $fieldset = new XMLElement('fieldset');
433
        $fieldset->setAttribute('class', 'settings');
434
        $fieldset->appendChild(new XMLElement('legend', __('Page Resources')));
435
436
        $group = new XMLElement('div');
437
        $group->setAttribute('class', 'two columns');
438
439
        $label = Widget::Label(__('Events'));
440
        $label->setAttribute('class', 'column');
441
442
        $events = ResourceManager::fetch(ResourceManager::RESOURCE_TYPE_EVENT, array(), array(), 'name ASC');
443
        $options = array();
444
445
        if (is_array($events) && !empty($events)) {
446
            if (!isset($fields['events'])) {
447
                $fields['events'] = array();
448
            }
449
450
            foreach ($events as $name => $about) {
451
                $options[] = array(
452
                    $name, in_array($name, $fields['events']), $about['name']
453
                );
454
            }
455
        }
456
457
        $label->appendChild(Widget::Select('fields[events][]', $options, array('multiple' => 'multiple')));
458
        $group->appendChild($label);
459
460
        // Data Sources -------------------------------------------------------
461
462
        $label = Widget::Label(__('Data Sources'));
463
        $label->setAttribute('class', 'column');
464
465
        $datasources = ResourceManager::fetch(ResourceManager::RESOURCE_TYPE_DS, array(), array(), 'name ASC');
466
        $options = array();
467
468
        if (is_array($datasources) && !empty($datasources)) {
469
            if (!isset($fields['data_sources'])) {
470
                $fields['data_sources'] = array();
471
            }
472
473
            foreach ($datasources as $name => $about) {
474
                $options[] = array(
475
                    $name, in_array($name, $fields['data_sources']), $about['name']
476
                );
477
            }
478
        }
479
480
        $label->appendChild(Widget::Select('fields[data_sources][]', $options, array('multiple' => 'multiple')));
481
        $group->appendChild($label);
482
        $fieldset->appendChild($group);
483
        $this->Form->appendChild($fieldset);
484
485
        // Controls -----------------------------------------------------------
486
487
        /**
488
         * After all Page related Fields have been added to the DOM, just before the
489
         * actions.
490
         *
491
         * @delegate AppendPageContent
492
         * @param string $context
493
         *  '/blueprints/pages/'
494
         * @param XMLElement $form
495
         * @param array $fields
496
         * @param array $errors
497
         */
498
        Symphony::ExtensionManager()->notifyMembers(
499
            'AppendPageContent',
500
            '/blueprints/pages/',
501
            array(
502
                'form'        => &$this->Form,
503
                'fields'    => &$fields,
504
                'errors'    => $this->_errors
505
            )
506
        );
507
508
        $div = new XMLElement('div');
509
        $div->setAttribute('class', 'actions');
510
        $div->appendChild(Widget::Input(
511
            'action[save]', ($this->_context[0] == 'edit' ? __('Save Changes') : __('Create Page')),
512
            'submit', array('accesskey' => 's')
513
        ));
514
515
        if ($this->_context[0] == 'edit') {
516
            $button = new XMLElement('button', __('Delete'));
517
            $button->setAttributeArray(array('name' => 'action[delete]', 'class' => 'button confirm delete', 'title' => __('Delete this page'), 'accesskey' => 'd', 'data-message' => __('Are you sure you want to delete this page?')));
518
            $div->appendChild($button);
519
        }
520
521
        $this->Form->appendChild($div);
522
523
        if (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) {
524
            $this->Form->appendChild(new XMLElement('input', null, array('type' => 'hidden', 'name' => 'parent', 'value' => $_REQUEST['parent'])));
525
        }
526
    }
527
528
    public function __compare_pages($a, $b)
529
    {
530
        return strnatcasecmp($a[2], $b[2]);
531
    }
532
533
    public function __actionIndex()
534
    {
535
        $checked = (is_array($_POST['items'])) ? array_keys($_POST['items']) : null;
536
537
        if (is_array($checked) && !empty($checked)) {
538
            /**
539
             * Extensions can listen for any custom actions that were added
540
             * through `AddCustomPreferenceFieldsets` or `AddCustomActions`
541
             * delegates.
542
             *
543
             * @delegate CustomActions
544
             * @since Symphony 2.3.2
545
             * @param string $context
546
             *  '/blueprints/pages/'
547
             * @param array $checked
548
             *  An array of the selected rows. The value is usually the ID of the
549
             *  the associated object.
550
             */
551
            Symphony::ExtensionManager()->notifyMembers('CustomActions', '/blueprints/pages/', array(
552
                'checked' => $checked
553
            ));
554
555
            switch ($_POST['with-selected']) {
556
                case 'delete':
557
                    $this->__actionDelete($checked, SYMPHONY_URL . '/blueprints/pages/');
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...
558
                    break;
559
            }
560
        }
561
    }
562
563
    public function __actionTemplate()
564
    {
565
        $filename = $this->_context[1] . '.xsl';
566
        $file_abs = PAGES . '/' . $filename;
0 ignored issues
show
Bug introduced by
The constant PAGES was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
567
        $fields = $_POST['fields'];
568
        $this->_errors = array();
569
570
        if (!isset($fields['body']) || trim($fields['body']) == '') {
571
            $this->_errors['body'] = __('This is a required field.');
572
        } elseif (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) {
573
            $this->_errors['body'] = __('This document is not well formed.') . ' ' . __('The following error was returned:') . ' <code>' . $errors[0]['message'] . '</code>';
574
        }
575
576
        if (empty($this->_errors)) {
577
            /**
578
             * Just before a Page Template is about to written to disk
579
             *
580
             * @delegate PageTemplatePreEdit
581
             * @since Symphony 2.2.2
582
             * @param string $context
583
             * '/blueprints/pages/template/'
584
             * @param string $file
585
             *  The path to the Page Template file
586
             * @param string $contents
587
             *  The contents of the `$fields['body']`, passed by reference
588
             */
589
            Symphony::ExtensionManager()->notifyMembers('PageTemplatePreEdit', '/blueprints/pages/template/', array('file' => $file_abs, 'contents' => &$fields['body']));
590
591
            if (!PageManager::writePageFiles($file_abs, $fields['body'])) {
592
                $this->pageAlert(
593
                    __('Page Template could not be written to disk.')
594
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/pages</code>')),
595
                    Alert::ERROR
596
                );
597
            } else {
598
                /**
599
                 * Just after a Page Template has been edited and written to disk
600
                 *
601
                 * @delegate PageTemplatePostEdit
602
                 * @since Symphony 2.2.2
603
                 * @param string $context
604
                 * '/blueprints/pages/template/'
605
                 * @param string $file
606
                 *  The path to the Page Template file
607
                 */
608
                Symphony::ExtensionManager()->notifyMembers('PageTemplatePostEdit', '/blueprints/pages/template/', array('file' => $file_abs));
609
610
                redirect(SYMPHONY_URL . '/blueprints/pages/template/' . $this->_context[1] . '/saved/');
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...
611
            }
612
        }
613
    }
614
615
    public function __actionNew()
616
    {
617
        $this->__actionEdit();
618
    }
619
620
    public function __actionEdit()
621
    {
622
        if ($this->_context[0] != 'new' && !$page_id = (integer)$this->_context[1]) {
623
            redirect(SYMPHONY_URL . '/blueprints/pages/');
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...
624
        }
625
626
        $parent_link_suffix = null;
627
628
        if (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) {
629
            $parent_link_suffix = '?parent=' . $_REQUEST['parent'];
630
        }
631
632
        if (@array_key_exists('delete', $_POST['action'])) {
633
            $this->__actionDelete($page_id, SYMPHONY_URL  . '/blueprints/pages/' . $parent_link_suffix);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $page_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
634
        }
635
636
        if (@array_key_exists('save', $_POST['action'])) {
637
            $fields = $_POST['fields'];
638
            $this->_errors = array();
639
640
            if (!isset($fields['title']) || trim($fields['title']) == '') {
641
                $this->_errors['title'] = __('This is a required field');
642
            }
643
644
            if (trim($fields['type']) != '' && preg_match('/(index|404|403)/i', $fields['type'])) {
645
                $types = preg_split('/\s*,\s*/', strtolower($fields['type']), -1, PREG_SPLIT_NO_EMPTY);
646
647
                if (in_array('index', $types) && PageManager::hasPageTypeBeenUsed($page_id, 'index')) {
0 ignored issues
show
Bug introduced by
It seems like $types can also be of type false; however, parameter $haystack of in_array() does only seem to accept array, 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

647
                if (in_array('index', /** @scrutinizer ignore-type */ $types) && PageManager::hasPageTypeBeenUsed($page_id, 'index')) {
Loading history...
648
                    $this->_errors['type'] = __('An index type page already exists.');
649
                } elseif (in_array('404', $types) && PageManager::hasPageTypeBeenUsed($page_id, '404')) {
650
                    $this->_errors['type'] = __('A 404 type page already exists.');
651
                } elseif (in_array('403', $types) && PageManager::hasPageTypeBeenUsed($page_id, '403')) {
652
                    $this->_errors['type'] = __('A 403 type page already exists.');
653
                }
654
            }
655
656
            if (trim($fields['handle']) == '') {
657
                $fields['handle'] = $fields['title'];
658
            }
659
660
            $fields['handle'] = PageManager::createHandle($fields['handle']);
661
662
            if (empty($fields['handle']) && !isset($this->_errors['title'])) {
663
                $this->_errors['handle'] = __('Please ensure handle contains at least one Latin-based character.');
664
            }
665
666
            /**
667
             * Just after the Symphony validation has run, allows Developers
668
             * to run custom validation logic on a Page
669
             *
670
             * @delegate PagePostValidate
671
             * @since Symphony 2.2
672
             * @param string $context
673
             * '/blueprints/pages/'
674
             * @param array $fields
675
             *  The `$_POST['fields']` array. This should be read-only and not changed
676
             *  through this delegate.
677
             * @param array $errors
678
             *  An associative array of errors, with the key matching a key in the
679
             *  `$fields` array, and the value being the string of the error. `$errors`
680
             *  is passed by reference.
681
             */
682
            Symphony::ExtensionManager()->notifyMembers('PagePostValidate', '/blueprints/pages/', array('fields' => $fields, 'errors' => &$errors));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $errors seems to be never defined.
Loading history...
683
684
            if (empty($this->_errors)) {
685
686
                if ($fields['params']) {
687
                    $fields['params'] = trim(preg_replace('@\/{2,}@', '/', $fields['params']), '/');
688
                }
689
690
                // Clean up type list
691
                $types = preg_split('/\s*,\s*/', $fields['type'], -1, PREG_SPLIT_NO_EMPTY);
692
                $types = @array_map('trim', $types);
0 ignored issues
show
Bug introduced by
It seems like $types can also be of type false; however, parameter $arr1 of array_map() does only seem to accept array, 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

692
                $types = @array_map('trim', /** @scrutinizer ignore-type */ $types);
Loading history...
693
                unset($fields['type']);
694
695
                $fields['parent'] = ($fields['parent'] != __('None') ? $fields['parent'] : null);
696
                $fields['data_sources'] = is_array($fields['data_sources']) ? implode(',', $fields['data_sources']) : null;
697
                $fields['events'] = is_array($fields['events']) ? implode(',', $fields['events']) : null;
698
                $fields['path'] = null;
699
700
                if ($fields['parent']) {
701
                    $fields['path'] = PageManager::resolvePagePath((integer)$fields['parent']);
702
                }
703
704
                // Check for duplicates:
705
                $current = PageManager::fetchPageByID($page_id);
706
707
                if (empty($current)) {
708
                    $fields['sortorder'] = PageManager::fetchNextSortOrder();
709
                }
710
711
                $pageQuery = (new PageManager)
712
                    ->select()
713
                    ->handle($fields['handle'])
714
                    ->path($fields['path'])
715
                    ->limit(1);
716
717
                if (!empty($current)) {
718
                    $pageQuery->where(['id' => ['!=' => General::intval($current)]]);
719
                }
720
721
                $duplicate = $pageQuery->execute()->next();
722
723
                // If duplicate
724
                if ($duplicate) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $duplicate of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
725
                    $this->_errors['handle'] = __('A page with that handle already exists');
726
727
                    // Create or move files:
728
                } else {
729
                    // New page?
730
                    if (empty($current)) {
731
                        $file_created = PageManager::createPageFiles(
732
                            $fields['path'],
733
                            $fields['handle']
734
                        );
735
736
                        // Existing page, potentially rename files
737
                    } else {
738
                        $file_created = PageManager::createPageFiles(
739
                            $fields['path'],
740
                            $fields['handle'],
741
                            $current['path'],
742
                            $current['handle']
743
                        );
744
                    }
745
746
                    // If the file wasn't created, it's usually permissions related
747
                    if (!$file_created) {
748
                        return $this->pageAlert(
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->pageAlert(__('Pag...code>')), Alert::ERROR) targeting AdministrationPage::pageAlert() 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...
749
                            __('Page Template could not be written to disk.')
750
                            . ' ' . __('Please check permissions on %s.', array('<code>/workspace/pages</code>')),
751
                            Alert::ERROR
752
                        );
753
                    }
754
755
                    // Insert the new data:
756
                    if (empty($current)) {
757
                        /**
758
                         * Just prior to creating a new Page record in `tbl_pages`, provided
759
                         * with the `$fields` associative array. Use with caution, as no
760
                         * duplicate page checks are run after this delegate has fired
761
                         *
762
                         * @delegate PagePreCreate
763
                         * @since Symphony 2.2
764
                         * @param string $context
765
                         * '/blueprints/pages/'
766
                         * @param array $fields
767
                         *  The `$_POST['fields']` array passed by reference
768
                         */
769
                        Symphony::ExtensionManager()->notifyMembers('PagePreCreate', '/blueprints/pages/', array('fields' => &$fields));
770
771
                        if (!$page_id = PageManager::add($fields)) {
772
                            $this->pageAlert(
773
                                __('Unknown errors occurred while attempting to save.')
774
                                . '<a href="' . SYMPHONY_URL . '/system/log/">'
775
                                . __('Check your activity log')
776
                                . '</a>.',
777
                                Alert::ERROR
778
                            );
779
                        } else {
780
                            /**
781
                             * Just after the creation of a new page in `tbl_pages`
782
                             *
783
                             * @delegate PagePostCreate
784
                             * @since Symphony 2.2
785
                             * @param string $context
786
                             * '/blueprints/pages/'
787
                             * @param integer $page_id
788
                             *  The ID of the newly created Page
789
                             * @param array $fields
790
                             *  An associative array of data that was just saved for this page
791
                             */
792
                            Symphony::ExtensionManager()->notifyMembers('PagePostCreate', '/blueprints/pages/', array('page_id' => $page_id, 'fields' => &$fields));
793
794
                            $redirect = "/blueprints/pages/edit/{$page_id}/created/{$parent_link_suffix}";
795
                        }
796
797
                        // Update existing:
798
                    } else {
799
                        /**
800
                         * Just prior to updating a Page record in `tbl_pages`, provided
801
                         * with the `$fields` associative array. Use with caution, as no
802
                         * duplicate page checks are run after this delegate has fired
803
                         *
804
                         * @delegate PagePreEdit
805
                         * @since Symphony 2.2
806
                         * @param string $context
807
                         * '/blueprints/pages/'
808
                         * @param integer $page_id
809
                         *  The ID of the Page that is about to be updated
810
                         * @param array $fields
811
                         *  The `$_POST['fields']` array passed by reference
812
                         */
813
                        Symphony::ExtensionManager()->notifyMembers('PagePreEdit', '/blueprints/pages/', array('page_id' => $page_id, 'fields' => &$fields));
814
815
                        if (!PageManager::edit($page_id, $fields, true)) {
816
                            return $this->pageAlert(
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->pageAlert(__('Unk... '</a>.', Alert::ERROR) targeting AdministrationPage::pageAlert() 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...
817
                                __('Unknown errors occurred while attempting to save.')
818
                                . '<a href="' . SYMPHONY_URL . '/system/log/">'
819
                                . __('Check your activity log')
820
                                . '</a>.',
821
                                Alert::ERROR
822
                            );
823
                        } else {
824
                            /**
825
                             * Just after updating a page in `tbl_pages`
826
                             *
827
                             * @delegate PagePostEdit
828
                             * @since Symphony 2.2
829
                             * @param string $context
830
                             * '/blueprints/pages/'
831
                             * @param integer $page_id
832
                             *  The ID of the Page that was just updated
833
                             * @param array $fields
834
                             *  An associative array of data that was just saved for this page
835
                             */
836
                            Symphony::ExtensionManager()->notifyMembers('PagePostEdit', '/blueprints/pages/', array('page_id' => $page_id, 'fields' => $fields));
837
838
                            $redirect = "/blueprints/pages/edit/{$page_id}/saved/{$parent_link_suffix}";
839
                        }
840
                    }
841
                }
842
843
                // Only proceed if there was no errors saving/creating the page
844
                if (empty($this->_errors)) {
845
                    /**
846
                     * Just before the page's types are saved into `tbl_pages_types`.
847
                     * Use with caution as no further processing is done on the `$types`
848
                     * array to prevent duplicate `$types` from occurring (ie. two index
849
                     * page types). Your logic can use the PageManger::hasPageTypeBeenUsed
850
                     * function to perform this logic.
851
                     *
852
                     * @delegate PageTypePreCreate
853
                     * @since Symphony 2.2
854
                     * @see toolkit.PageManager#hasPageTypeBeenUsed
855
                     * @param string $context
856
                     * '/blueprints/pages/'
857
                     * @param integer $page_id
858
                     *  The ID of the Page that was just created or updated
859
                     * @param array $types
860
                     *  An associative array of the types for this page passed by reference.
861
                     */
862
                    Symphony::ExtensionManager()->notifyMembers('PageTypePreCreate', '/blueprints/pages/', array('page_id' => $page_id, 'types' => &$types));
863
864
                    // Assign page types:
865
                    PageManager::addPageTypesToPage($page_id, $types);
866
867
                    // Find and update children:
868
                    if ($this->_context[0] == 'edit') {
869
                        PageManager::editPageChildren($page_id, $fields['path'] . '/' . $fields['handle']);
870
                    }
871
872
                    if ($redirect) {
873
                        redirect(SYMPHONY_URL . $redirect);
874
                    }
875
                }
876
            }
877
878
            // If there was any errors, either with pre processing or because of a
879
            // duplicate page, return.
880
            if (is_array($this->_errors) && !empty($this->_errors)) {
881
                return $this->pageAlert(
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->pageAlert(__('An ...tails.'), Alert::ERROR) targeting AdministrationPage::pageAlert() 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...
882
                    __('An error occurred while processing this form. See below for details.'),
883
                    Alert::ERROR
884
                );
885
            }
886
        }
887
    }
888
889
    public function __actionDelete($pages, $redirect)
890
    {
891
        $success = true;
892
        $deleted_page_ids = array();
893
894
        if (!is_array($pages)) {
895
            $pages = array($pages);
896
        }
897
898
        /**
899
         * Prior to deleting Pages
900
         *
901
         * @delegate PagePreDelete
902
         * @since Symphony 2.2
903
         * @param string $context
904
         * '/blueprints/pages/'
905
         * @param array $page_ids
906
         *  An array of Page ID's that are about to be deleted, passed
907
         *  by reference
908
         * @param string $redirect
909
         *  The absolute path that the Developer will be redirected to
910
         *  after the Pages are deleted
911
         */
912
        Symphony::ExtensionManager()->notifyMembers('PagePreDelete', '/blueprints/pages/', array('page_ids' => &$pages, 'redirect' => &$redirect));
913
914
        foreach ($pages as $page_id) {
915
            $page = PageManager::fetchPageByID($page_id);
916
917
            if (empty($page)) {
918
                $success = false;
919
                $this->pageAlert(
920
                    __('Page could not be deleted because it does not exist.'),
921
                    Alert::ERROR
922
                );
923
924
                break;
925
            }
926
927
            if (PageManager::hasChildPages($page_id)) {
928
                $this->_hilights[] = $page['id'];
929
                $success = false;
930
                $this->pageAlert(
931
                    __('Page could not be deleted because it has children.'),
932
                    Alert::ERROR
933
                );
934
935
                continue;
936
            }
937
938
            if (!PageManager::deletePageFiles($page['path'], $page['handle'])) {
939
                $this->_hilights[] = $page['id'];
940
                $success = false;
941
                $this->pageAlert(
942
                    __('One or more pages could not be deleted.')
943
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/pages</code>')),
944
                    Alert::ERROR
945
                );
946
947
                continue;
948
            }
949
950
            if (PageManager::delete($page_id, false)) {
951
                $deleted_page_ids[] = $page_id;
952
            }
953
        }
954
955
        if ($success) {
956
            /**
957
             * Fires after all Pages have been deleted
958
             *
959
             * @delegate PagePostDelete
960
             * @since Symphony 2.3
961
             * @param string $context
962
             * '/blueprints/pages/'
963
             * @param array $page_ids
964
             *  The page ID's that were just deleted
965
             */
966
            Symphony::ExtensionManager()->notifyMembers('PagePostDelete', '/blueprints/pages/', array('page_ids' => $deleted_page_ids));
967
            redirect($redirect);
968
        }
969
    }
970
}
971