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 (#2843)
by Brendan
04:11
created

contentBlueprintsPages   F

Complexity

Total Complexity 130

Size/Duplication

Total Lines 956
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 956
rs 1.263
wmc 130

10 Methods

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

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

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