These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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( |
||
22 | array(Widget::Anchor(__('Pages'), SYMPHONY_URL . '/blueprints/pages/')) |
||
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 – %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)) { |
||
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']) . '/'; |
||
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 | View Code Duplication | if ($page['params']) { |
|
128 | $col_params = Widget::TableData(trim($page['params'], '/')); |
||
129 | } else { |
||
130 | $col_params = Widget::TableData(__('None'), 'inactive'); |
||
131 | } |
||
132 | |||
133 | View Code Duplication | 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']) . ' →', |
||
149 | SYMPHONY_URL . '/blueprints/pages/?parent=' . $page['id']) |
||
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 | |||
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/'); |
||
229 | } |
||
230 | |||
231 | $existing = PageManager::fetchPageByID($page_id); |
||
232 | |||
233 | if (!$existing) { |
||
234 | Administration::instance()->errorPageNotFound(); |
||
235 | } else { |
||
236 | $existing['type'] = PageManager::fetchPageTypes($page_id); |
||
237 | } |
||
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 | View Code Duplication | } elseif (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) { |
|
284 | $fields['parent'] = $_REQUEST['parent']; |
||
285 | } |
||
286 | |||
287 | $title = $fields['title']; |
||
288 | |||
289 | if (trim($title) == '') { |
||
290 | $title = $existing['title']; |
||
291 | } |
||
292 | |||
293 | $this->setTitle(__( |
||
294 | ($title ? '%1$s – %2$s – %3$s' : '%2$s – %3$s'), |
||
295 | array( |
||
296 | $title, |
||
297 | __('Pages'), |
||
298 | __('Symphony') |
||
299 | ) |
||
300 | )); |
||
301 | |||
302 | $page_id = isset($page_id) ? $page_id : null; |
||
303 | |||
304 | if (!empty($title)) { |
||
305 | $page_url = URL . '/' . PageManager::resolvePagePath($page_id) . '/'; |
||
306 | |||
307 | $this->appendSubheading($title, array( |
||
308 | Widget::Anchor(__('View Page'), $page_url, __('View Page on Frontend'), 'button', null, array('target' => '_blank', 'accesskey' => 'v')) |
||
309 | )); |
||
310 | } else { |
||
311 | $this->appendSubheading(!empty($title) ? $title : __('Untitled')); |
||
312 | } |
||
313 | |||
314 | if (isset($page_id)) { |
||
315 | $this->insertBreadcrumbsUsingPageIdentifier($page_id, false); |
||
316 | } else { |
||
317 | $_GET['parent'] = isset($_GET['parent']) ? $_GET['parent'] : null; |
||
318 | $this->insertBreadcrumbsUsingPageIdentifier((int)$_GET['parent'], true); |
||
319 | } |
||
320 | |||
321 | // Title -------------------------------------------------------------- |
||
322 | |||
323 | $fieldset = new XMLElement('fieldset'); |
||
324 | $fieldset->setAttribute('class', 'settings'); |
||
325 | $fieldset->appendChild(new XMLElement('legend', __('Page Settings'))); |
||
326 | |||
327 | $label = Widget::Label(__('Name')); |
||
328 | $label->appendChild(Widget::Input( |
||
329 | 'fields[title]', General::sanitize($fields['title']) |
||
330 | )); |
||
331 | |||
332 | if (isset($this->_errors['title'])) { |
||
333 | $label = Widget::Error($label, $this->_errors['title']); |
||
334 | } |
||
335 | |||
336 | $fieldset->appendChild($label); |
||
337 | |||
338 | // Handle ------------------------------------------------------------- |
||
339 | |||
340 | $group = new XMLElement('div'); |
||
341 | $group->setAttribute('class', 'two columns'); |
||
342 | $column = new XMLElement('div'); |
||
343 | $column->setAttribute('class', 'column'); |
||
344 | |||
345 | $label = Widget::Label(__('Handle')); |
||
346 | $label->appendChild(Widget::Input( |
||
347 | 'fields[handle]', $fields['handle'] |
||
348 | )); |
||
349 | |||
350 | if (isset($this->_errors['handle'])) { |
||
351 | $label = Widget::Error($label, $this->_errors['handle']); |
||
352 | } |
||
353 | |||
354 | $column->appendChild($label); |
||
355 | |||
356 | // Parent --------------------------------------------------------- |
||
357 | |||
358 | $label = Widget::Label(__('Parent Page')); |
||
359 | |||
360 | $where = array( |
||
361 | sprintf('id != %d', $page_id) |
||
362 | ); |
||
363 | $pages = PageManager::fetch(false, array('id'), $where, 'title ASC'); |
||
364 | |||
365 | $options = array( |
||
366 | array('', false, '/') |
||
367 | ); |
||
368 | |||
369 | if (!empty($pages)) { |
||
370 | foreach ($pages as $page) { |
||
371 | $options[] = array( |
||
372 | $page['id'], $fields['parent'] == $page['id'], |
||
373 | '/' . PageManager::resolvePagePath($page['id']) |
||
374 | ); |
||
375 | } |
||
376 | |||
377 | usort($options, array($this, '__compare_pages')); |
||
378 | } |
||
379 | |||
380 | $label->appendChild(Widget::Select( |
||
381 | 'fields[parent]', $options |
||
382 | )); |
||
383 | $column->appendChild($label); |
||
384 | $group->appendChild($column); |
||
385 | |||
386 | // Parameters --------------------------------------------------------- |
||
387 | |||
388 | $column = new XMLElement('div'); |
||
389 | $column->setAttribute('class', 'column'); |
||
390 | |||
391 | $label = Widget::Label(__('Parameters')); |
||
392 | $label->appendChild(Widget::Input( |
||
393 | 'fields[params]', $fields['params'], 'text', array('placeholder' => 'param1/param2') |
||
394 | )); |
||
395 | $column->appendChild($label); |
||
396 | |||
397 | // Type ----------------------------------------------------------- |
||
398 | |||
399 | $label = Widget::Label(__('Type')); |
||
400 | $label->appendChild(Widget::Input('fields[type]', $fields['type'])); |
||
401 | |||
402 | if (isset($this->_errors['type'])) { |
||
403 | $label = Widget::Error($label, $this->_errors['type']); |
||
404 | } |
||
405 | |||
406 | $column->appendChild($label); |
||
407 | |||
408 | $tags = new XMLElement('ul'); |
||
409 | $tags->setAttribute('class', 'tags'); |
||
410 | $tags->setAttribute('data-interactive', 'data-interactive'); |
||
411 | |||
412 | $types = PageManager::fetchAvailablePageTypes(); |
||
413 | |||
414 | foreach ($types as $type) { |
||
415 | $tags->appendChild(new XMLElement('li', $type)); |
||
416 | } |
||
417 | |||
418 | $column->appendChild($tags); |
||
419 | $group->appendChild($column); |
||
420 | $fieldset->appendChild($group); |
||
421 | $this->Form->appendChild($fieldset); |
||
422 | |||
423 | // Events ------------------------------------------------------------- |
||
424 | |||
425 | $fieldset = new XMLElement('fieldset'); |
||
426 | $fieldset->setAttribute('class', 'settings'); |
||
427 | $fieldset->appendChild(new XMLElement('legend', __('Page Resources'))); |
||
428 | |||
429 | $group = new XMLElement('div'); |
||
430 | $group->setAttribute('class', 'two columns'); |
||
431 | |||
432 | $label = Widget::Label(__('Events')); |
||
433 | $label->setAttribute('class', 'column'); |
||
434 | |||
435 | $events = ResourceManager::fetch(ResourceManager::RESOURCE_TYPE_EVENT, array(), array(), 'name ASC'); |
||
436 | $options = array(); |
||
437 | |||
438 | View Code Duplication | if (is_array($events) && !empty($events)) { |
|
439 | if (!isset($fields['events'])) { |
||
440 | $fields['events'] = array(); |
||
441 | } |
||
442 | |||
443 | foreach ($events as $name => $about) { |
||
444 | $options[] = array( |
||
445 | $name, in_array($name, $fields['events']), $about['name'] |
||
446 | ); |
||
447 | } |
||
448 | } |
||
449 | |||
450 | $label->appendChild(Widget::Select('fields[events][]', $options, array('multiple' => 'multiple'))); |
||
451 | $group->appendChild($label); |
||
452 | |||
453 | // Data Sources ------------------------------------------------------- |
||
454 | |||
455 | $label = Widget::Label(__('Data Sources')); |
||
456 | $label->setAttribute('class', 'column'); |
||
457 | |||
458 | $datasources = ResourceManager::fetch(ResourceManager::RESOURCE_TYPE_DS, array(), array(), 'name ASC'); |
||
459 | $options = array(); |
||
460 | |||
461 | View Code Duplication | if (is_array($datasources) && !empty($datasources)) { |
|
462 | if (!isset($fields['data_sources'])) { |
||
463 | $fields['data_sources'] = array(); |
||
464 | } |
||
465 | |||
466 | foreach ($datasources as $name => $about) { |
||
467 | $options[] = array( |
||
468 | $name, in_array($name, $fields['data_sources']), $about['name'] |
||
469 | ); |
||
470 | } |
||
471 | } |
||
472 | |||
473 | $label->appendChild(Widget::Select('fields[data_sources][]', $options, array('multiple' => 'multiple'))); |
||
474 | $group->appendChild($label); |
||
475 | $fieldset->appendChild($group); |
||
476 | $this->Form->appendChild($fieldset); |
||
477 | |||
478 | // Controls ----------------------------------------------------------- |
||
479 | |||
480 | /** |
||
481 | * After all Page related Fields have been added to the DOM, just before the |
||
482 | * actions. |
||
483 | * |
||
484 | * @delegate AppendPageContent |
||
485 | * @param string $context |
||
486 | * '/blueprints/pages/' |
||
487 | * @param XMLElement $form |
||
488 | * @param array $fields |
||
489 | * @param array $errors |
||
490 | */ |
||
491 | Symphony::ExtensionManager()->notifyMembers( |
||
492 | 'AppendPageContent', |
||
493 | '/blueprints/pages/', |
||
494 | array( |
||
495 | 'form' => &$this->Form, |
||
496 | 'fields' => &$fields, |
||
497 | 'errors' => $this->_errors |
||
498 | ) |
||
499 | ); |
||
500 | |||
501 | $div = new XMLElement('div'); |
||
502 | $div->setAttribute('class', 'actions'); |
||
503 | $div->appendChild(Widget::Input( |
||
504 | 'action[save]', ($this->_context[0] == 'edit' ? __('Save Changes') : __('Create Page')), |
||
505 | 'submit', array('accesskey' => 's') |
||
506 | )); |
||
507 | |||
508 | View Code Duplication | if ($this->_context[0] == 'edit') { |
|
509 | $button = new XMLElement('button', __('Delete')); |
||
510 | $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?'))); |
||
511 | $div->appendChild($button); |
||
512 | } |
||
513 | |||
514 | $this->Form->appendChild($div); |
||
515 | |||
516 | if (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) { |
||
517 | $this->Form->appendChild(new XMLElement('input', null, array('type' => 'hidden', 'name' => 'parent', 'value' => $_REQUEST['parent']))); |
||
518 | } |
||
519 | } |
||
520 | |||
521 | public function __compare_pages($a, $b) |
||
522 | { |
||
523 | return strnatcasecmp($a[2], $b[2]); |
||
524 | } |
||
525 | |||
526 | public function __actionIndex() |
||
527 | { |
||
528 | $checked = (is_array($_POST['items'])) ? array_keys($_POST['items']) : null; |
||
529 | |||
530 | if (is_array($checked) && !empty($checked)) { |
||
531 | /** |
||
532 | * Extensions can listen for any custom actions that were added |
||
533 | * through `AddCustomPreferenceFieldsets` or `AddCustomActions` |
||
534 | * delegates. |
||
535 | * |
||
536 | * @delegate CustomActions |
||
537 | * @since Symphony 2.3.2 |
||
538 | * @param string $context |
||
539 | * '/blueprints/pages/' |
||
540 | * @param array $checked |
||
541 | * An array of the selected rows. The value is usually the ID of the |
||
542 | * the associated object. |
||
543 | */ |
||
544 | Symphony::ExtensionManager()->notifyMembers('CustomActions', '/blueprints/pages/', array( |
||
545 | 'checked' => $checked |
||
546 | )); |
||
547 | |||
548 | switch ($_POST['with-selected']) { |
||
549 | case 'delete': |
||
550 | $this->__actionDelete($checked, SYMPHONY_URL . '/blueprints/pages/'); |
||
551 | break; |
||
552 | } |
||
553 | } |
||
554 | } |
||
555 | |||
556 | public function __actionTemplate() |
||
557 | { |
||
558 | $filename = $this->_context[1] . '.xsl'; |
||
559 | $file_abs = PAGES . '/' . $filename; |
||
560 | $fields = $_POST['fields']; |
||
561 | $this->_errors = array(); |
||
562 | |||
563 | if (!isset($fields['body']) || trim($fields['body']) == '') { |
||
564 | $this->_errors['body'] = __('This is a required field.'); |
||
565 | } elseif (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { |
||
566 | $this->_errors['body'] = __('This document is not well formed.') . ' ' . __('The following error was returned:') . ' <code>' . $errors[0]['message'] . '</code>'; |
||
567 | } |
||
568 | |||
569 | if (empty($this->_errors)) { |
||
570 | /** |
||
571 | * Just before a Page Template is about to written to disk |
||
572 | * |
||
573 | * @delegate PageTemplatePreEdit |
||
574 | * @since Symphony 2.2.2 |
||
575 | * @param string $context |
||
576 | * '/blueprints/pages/template/' |
||
577 | * @param string $file |
||
578 | * The path to the Page Template file |
||
579 | * @param string $contents |
||
580 | * The contents of the `$fields['body']`, passed by reference |
||
581 | */ |
||
582 | Symphony::ExtensionManager()->notifyMembers('PageTemplatePreEdit', '/blueprints/pages/template/', array('file' => $file_abs, 'contents' => &$fields['body'])); |
||
583 | |||
584 | if (!PageManager::writePageFiles($file_abs, $fields['body'])) { |
||
585 | $this->pageAlert( |
||
586 | __('Page Template could not be written to disk.') |
||
587 | . ' ' . __('Please check permissions on %s.', array('<code>/workspace/pages</code>')), |
||
588 | Alert::ERROR |
||
589 | ); |
||
590 | } else { |
||
591 | /** |
||
592 | * Just after a Page Template has been edited and written to disk |
||
593 | * |
||
594 | * @delegate PageTemplatePostEdit |
||
595 | * @since Symphony 2.2.2 |
||
596 | * @param string $context |
||
597 | * '/blueprints/pages/template/' |
||
598 | * @param string $file |
||
599 | * The path to the Page Template file |
||
600 | */ |
||
601 | Symphony::ExtensionManager()->notifyMembers('PageTemplatePostEdit', '/blueprints/pages/template/', array('file' => $file_abs)); |
||
602 | |||
603 | redirect(SYMPHONY_URL . '/blueprints/pages/template/' . $this->_context[1] . '/saved/'); |
||
604 | } |
||
605 | } |
||
606 | } |
||
607 | |||
608 | public function __actionNew() |
||
609 | { |
||
610 | $this->__actionEdit(); |
||
611 | } |
||
612 | |||
613 | public function __actionEdit() |
||
614 | { |
||
615 | if ($this->_context[0] != 'new' && !$page_id = (integer)$this->_context[1]) { |
||
616 | redirect(SYMPHONY_URL . '/blueprints/pages/'); |
||
617 | } |
||
618 | |||
619 | $parent_link_suffix = null; |
||
620 | |||
621 | View Code Duplication | if (isset($_REQUEST['parent']) && is_numeric($_REQUEST['parent'])) { |
|
622 | $parent_link_suffix = '?parent=' . $_REQUEST['parent']; |
||
623 | } |
||
624 | |||
625 | if (@array_key_exists('delete', $_POST['action'])) { |
||
626 | $this->__actionDelete($page_id, SYMPHONY_URL . '/blueprints/pages/' . $parent_link_suffix); |
||
627 | } |
||
628 | |||
629 | if (@array_key_exists('save', $_POST['action'])) { |
||
630 | $fields = $_POST['fields']; |
||
631 | $this->_errors = array(); |
||
632 | $autogenerated_handle = false; |
||
633 | |||
634 | View Code Duplication | if (!isset($fields['title']) || trim($fields['title']) == '') { |
|
635 | $this->_errors['title'] = __('This is a required field'); |
||
636 | } |
||
637 | |||
638 | if (trim($fields['type']) != '' && preg_match('/(index|404|403)/i', $fields['type'])) { |
||
639 | $types = preg_split('/\s*,\s*/', strtolower($fields['type']), -1, PREG_SPLIT_NO_EMPTY); |
||
640 | |||
641 | if (in_array('index', $types) && PageManager::hasPageTypeBeenUsed($page_id, 'index')) { |
||
642 | $this->_errors['type'] = __('An index type page already exists.'); |
||
643 | } elseif (in_array('404', $types) && PageManager::hasPageTypeBeenUsed($page_id, '404')) { |
||
644 | $this->_errors['type'] = __('A 404 type page already exists.'); |
||
645 | } elseif (in_array('403', $types) && PageManager::hasPageTypeBeenUsed($page_id, '403')) { |
||
646 | $this->_errors['type'] = __('A 403 type page already exists.'); |
||
647 | } |
||
648 | } |
||
649 | |||
650 | if (trim($fields['handle']) == '') { |
||
651 | $fields['handle'] = $fields['title']; |
||
652 | $autogenerated_handle = true; |
||
653 | } |
||
654 | |||
655 | $fields['handle'] = PageManager::createHandle($fields['handle']); |
||
656 | |||
657 | if (empty($fields['handle']) && !isset($this->_errors['title'])) { |
||
658 | $this->_errors['handle'] = __('Please ensure handle contains at least one Latin-based character.'); |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * Just after the Symphony validation has run, allows Developers |
||
663 | * to run custom validation logic on a Page |
||
664 | * |
||
665 | * @delegate PagePostValidate |
||
666 | * @since Symphony 2.2 |
||
667 | * @param string $context |
||
668 | * '/blueprints/pages/' |
||
669 | * @param array $fields |
||
670 | * The `$_POST['fields']` array. This should be read-only and not changed |
||
671 | * through this delegate. |
||
672 | * @param array $errors |
||
673 | * An associative array of errors, with the key matching a key in the |
||
674 | * `$fields` array, and the value being the string of the error. `$errors` |
||
675 | * is passed by reference. |
||
676 | */ |
||
677 | Symphony::ExtensionManager()->notifyMembers('PagePostValidate', '/blueprints/pages/', array('fields' => $fields, 'errors' => &$errors)); |
||
678 | |||
679 | if (empty($this->_errors)) { |
||
680 | $autogenerated_handle = false; |
||
681 | |||
682 | if ($fields['params']) { |
||
683 | $fields['params'] = trim(preg_replace('@\/{2,}@', '/', $fields['params']), '/'); |
||
684 | } |
||
685 | |||
686 | // Clean up type list |
||
687 | $types = preg_split('/\s*,\s*/', $fields['type'], -1, PREG_SPLIT_NO_EMPTY); |
||
688 | $types = @array_map('trim', $types); |
||
689 | unset($fields['type']); |
||
690 | |||
691 | $fields['parent'] = ($fields['parent'] != __('None') ? $fields['parent'] : null); |
||
692 | $fields['data_sources'] = is_array($fields['data_sources']) ? implode(',', $fields['data_sources']) : null; |
||
693 | $fields['events'] = is_array($fields['events']) ? implode(',', $fields['events']) : null; |
||
694 | $fields['path'] = null; |
||
695 | |||
696 | if ($fields['parent']) { |
||
697 | $fields['path'] = PageManager::resolvePagePath((integer)$fields['parent']); |
||
698 | } |
||
699 | |||
700 | // Check for duplicates: |
||
701 | $current = PageManager::fetchPageByID($page_id); |
||
702 | |||
703 | if (empty($current)) { |
||
704 | $fields['sortorder'] = PageManager::fetchNextSortOrder(); |
||
705 | } |
||
706 | |||
707 | $where = array(); |
||
708 | |||
709 | if (!empty($current)) { |
||
710 | $where[] = "p.id != {$page_id}"; |
||
711 | } |
||
712 | |||
713 | $where[] = "p.handle = '" . $fields['handle'] . "'"; |
||
714 | $where[] = (is_null($fields['path'])) |
||
715 | ? "p.path IS null" |
||
716 | : "p.path = '" . $fields['path'] . "'"; |
||
717 | $duplicate = PageManager::fetch(false, array('*'), $where); |
||
718 | |||
719 | // If duplicate |
||
720 | if (!empty($duplicate)) { |
||
721 | if ($autogenerated_handle) { |
||
722 | $this->_errors['title'] = __('A page with that title already exists'); |
||
723 | } else { |
||
724 | $this->_errors['handle'] = __('A page with that handle already exists'); |
||
725 | } |
||
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 | $redirect = null; |
||
749 | return $this->pageAlert( |
||
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 | View Code Duplication | 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 | View Code Duplication | if (!PageManager::edit($page_id, $fields, true)) { |
|
817 | return $this->pageAlert( |
||
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); |
||
0 ignored issues
–
show
|
|||
867 | |||
868 | // Find and update children: |
||
869 | if ($this->_context[0] == 'edit') { |
||
870 | PageManager::editPageChildren($page_id, $fields['path'] . '/' . $fields['handle']); |
||
0 ignored issues
–
show
It seems like
$page_id defined by \PageManager::add($fields) on line 772 can also be of type false ; however, PageManager::editPageChildren() does only seem to accept integer|null , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new
Loading history...
|
|||
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 | View Code Duplication | if (is_array($this->_errors) && !empty($this->_errors)) { |
|
882 | return $this->pageAlert( |
||
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 |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.