1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @package content |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* The Publish page is where the majority of an Authors time will |
9
|
|
|
* be spent in Symphony with adding, editing and removing entries |
10
|
|
|
* from Sections. This Page controls the entries table as well as |
11
|
|
|
* the Entry creation screens. |
12
|
|
|
*/ |
13
|
|
|
class contentPublish extends AdministrationPage |
14
|
|
|
{ |
15
|
|
|
public $_errors = array(); |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* The Pages page has /action/id/flag/ context. |
19
|
|
|
* eg. /edit/1/saved/ |
20
|
|
|
* |
21
|
|
|
* @param array $context |
22
|
|
|
* @param array $parts |
23
|
|
|
* @return array |
24
|
|
|
*/ |
25
|
|
|
public function parseContext(array &$context, array $parts) |
26
|
|
|
{ |
27
|
|
|
// Order is important! |
28
|
|
|
$params = array_fill_keys(array('section_handle', 'page', 'entry_id', 'flag'), null); |
29
|
|
|
$params['section_handle'] = $parts[1]; |
30
|
|
|
|
31
|
|
|
if (isset($parts[2])) { |
32
|
|
|
$extras = preg_split('/\//', $parts[2], -1, PREG_SPLIT_NO_EMPTY); |
33
|
|
|
list($params['page'], $params['entry_id'], $params['flag']) = $extras; |
34
|
|
|
$params['entry_id'] = (int)$params['entry_id']; |
35
|
|
|
} else { |
36
|
|
|
$params['page'] = 'index'; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
$context = array_filter($params); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
public function sort(&$sort, &$order, $params) |
43
|
|
|
{ |
44
|
|
|
$section = $params['current-section']; |
45
|
|
|
|
46
|
|
|
// If `?unsort` is appended to the URL, then sorting is reverted |
47
|
|
|
// to 'none', aka. by 'entry-id'. |
48
|
|
|
if ($params['unsort']) { |
49
|
|
|
$section->setSortingField('id', false); |
50
|
|
|
$section->setSortingOrder('desc'); |
51
|
|
|
|
52
|
|
|
redirect(Administration::instance()->getCurrentPageURL()); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
// By default, sorting information are retrieved from |
56
|
|
|
// the filesystem and stored inside the `Configuration` object |
57
|
|
|
if (is_null($sort) && is_null($order)) { |
58
|
|
|
$sort = $section->getSortingField(); |
59
|
|
|
$order = $section->getSortingOrder(); |
60
|
|
|
|
61
|
|
|
// Set the sorting in the `EntryManager` for subsequent use |
62
|
|
|
EntryManager::setFetchSorting($sort, $order); |
63
|
|
|
} else { |
64
|
|
|
$sort = General::sanitize($sort); |
65
|
|
|
|
66
|
|
|
// Ensure that this field is infact sortable, otherwise |
67
|
|
|
// fallback to IDs |
68
|
|
|
if (($field = FieldManager::fetch($sort)) instanceof Field && !$field->isSortable()) { |
69
|
|
|
$sort = $section->getDefaultSortingField(); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
// If the sort order or direction differs from what is saved, |
73
|
|
|
// update the config file and reload the page |
74
|
|
|
if ($sort !== $section->getSortingField() || $order !== $section->getSortingOrder()) { |
75
|
|
|
$section->setSortingField($sort, false); |
76
|
|
|
$section->setSortingOrder($order); |
77
|
|
|
|
78
|
|
View Code Duplication |
if ($params['filters']) { |
79
|
|
|
$params['filters'] = '?' . trim($params['filters'], '&'); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
redirect(Administration::instance()->getCurrentPageURL() . $params['filters']); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// If the sort order or direction remains the same, reload the page |
86
|
|
|
if ($sort === $section->getSortingField() && $order === $section->getSortingOrder()) { |
87
|
|
View Code Duplication |
if ($params['filters']) { |
88
|
|
|
$params['filters'] = '?' . trim($params['filters'], '&'); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
redirect(Administration::instance()->getCurrentPageURL() . $params['filters']); |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
} |
95
|
|
|
|
96
|
|
View Code Duplication |
public function build(array $context = array()) |
97
|
|
|
{ |
98
|
|
|
$section_id = SectionManager::fetchIDFromHandle($context['section_handle']); |
99
|
|
|
|
100
|
|
|
if ($section_id) { |
101
|
|
|
$context['associations'] = array( |
102
|
|
|
'parent' => SectionManager::fetchParentAssociations($section_id), |
103
|
|
|
'child' => SectionManager::fetchChildAssociations($section_id) |
104
|
|
|
); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
return parent::build($context); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
public function action() |
111
|
|
|
{ |
112
|
|
|
$this->__switchboard('action'); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
public function __switchboard($type = 'view') |
116
|
|
|
{ |
117
|
|
|
$function = ($type === 'action' ? '__action' : '__view') . ucfirst($this->_context['page']); |
118
|
|
|
|
119
|
|
|
if (!method_exists($this, $function)) { |
120
|
|
|
// If there is no action function, just return without doing anything |
121
|
|
|
if ($type === 'action') { |
122
|
|
|
return; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
Administration::instance()->errorPageNotFound(); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
// Is this request allowed by server? |
129
|
|
|
if ($this->isRequestValid() === false) { |
130
|
|
|
$this->pageAlert(__('This request exceeds the maximum allowed request size of %s specified by your host.', |
131
|
|
|
array( |
132
|
|
|
ini_get('post_max_size') |
133
|
|
|
)), |
134
|
|
|
Alert::ERROR |
135
|
|
|
); |
136
|
|
|
} |
137
|
|
|
$this->$function(); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
public function view() |
141
|
|
|
{ |
142
|
|
|
$this->__switchboard(); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
public function __viewIndex() |
146
|
|
|
{ |
147
|
|
|
if (!$section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle'])) { |
148
|
|
|
Administration::instance()->throwCustomError( |
149
|
|
|
__('The Section, %s, could not be found.', |
150
|
|
|
array('<code>' . $this->_context['section_handle'] . '</code>')), |
151
|
|
|
__('Unknown Section'), |
152
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
153
|
|
|
); |
154
|
|
|
} elseif (!is_writable(CONFIG)) { |
155
|
|
|
$this->pageAlert(__('The Symphony configuration file, %s, is not writable. The sort order cannot be modified.', |
156
|
|
|
array('<code>/manifest/config.php</code>')), Alert::NOTICE); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
$section = SectionManager::fetch($section_id); |
160
|
|
|
|
161
|
|
|
$this->setPageType('table'); |
162
|
|
|
$this->setTitle(__('%1$s – %2$s', array($section->get('name'), __('Symphony')))); |
163
|
|
|
|
164
|
|
|
$filters = array(); |
165
|
|
|
$filter_querystring = $prepopulate_querystring = $where = $joins = null; |
166
|
|
|
$current_page = (isset($_REQUEST['pg']) && is_numeric($_REQUEST['pg']) ? max(1, |
167
|
|
|
intval($_REQUEST['pg'])) : 1); |
168
|
|
|
|
169
|
|
|
if (isset($_REQUEST['filter'])) { |
170
|
|
|
// legacy implementation, convert single filter to an array |
171
|
|
|
// split string in the form ?filter=handle:value |
172
|
|
|
if (!is_array($_REQUEST['filter'])) { |
173
|
|
|
list($field_handle, $filter_value) = explode(':', $_REQUEST['filter'], 2); |
174
|
|
|
$filters[$field_handle] = rawurldecode($filter_value); |
175
|
|
|
} else { |
176
|
|
|
$filters = $_REQUEST['filter']; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
foreach ($filters as $handle => $value) { |
180
|
|
|
// Handle multiple values through filtering. RE: #2290 |
181
|
|
|
if ((is_array($value) && empty($value)) || trim($value) === '') { |
182
|
|
|
continue; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
View Code Duplication |
if (!is_array($value)) { |
186
|
|
|
$filter_type = Datasource::determineFilterType($value); |
187
|
|
|
$value = preg_split('/' . ($filter_type === Datasource::FILTER_AND ? '\+' : '(?<!\\\\),') . '\s*/', |
188
|
|
|
$value, -1, PREG_SPLIT_NO_EMPTY); |
189
|
|
|
$value = array_map('trim', $value); |
190
|
|
|
$value = array_map(array('Datasource', 'removeEscapedCommas'), $value); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
// Handle date meta data #2003 |
194
|
|
|
$handle = Symphony::Database()->cleanValue($handle); |
195
|
|
|
if (in_array($handle, array('system:creation-date', 'system:modification-date'))) { |
196
|
|
|
$date_joins = ''; |
197
|
|
|
$date_where = ''; |
198
|
|
|
$date = new FieldDate(); |
199
|
|
|
$date->buildDSRetrievalSQL($value, $date_joins, $date_where, |
200
|
|
|
($filter_type === Datasource::FILTER_AND ? true : false)); |
|
|
|
|
201
|
|
|
|
202
|
|
|
// Replace the date field where with the `creation_date` or `modification_date`. |
203
|
|
|
$date_where = preg_replace('/`t\d+`.date/', |
204
|
|
|
($field_id !== 'system:modification-date') ? '`e`.creation_date_gmt' : '`e`.modification_date_gmt', |
|
|
|
|
205
|
|
|
$date_where); |
206
|
|
|
$where .= $date_where; |
207
|
|
|
} else { |
208
|
|
|
// Handle normal fields |
209
|
|
|
$field_id = FieldManager::fetchFieldIDFromElementName( |
210
|
|
|
$handle, |
211
|
|
|
$section->get('id') |
212
|
|
|
); |
213
|
|
|
|
214
|
|
|
$field = FieldManager::fetch($field_id); |
215
|
|
|
if ($field instanceof Field) { |
216
|
|
|
$field->buildDSRetrievalSQL($value, $joins, $where, |
217
|
|
|
($filter_type === Datasource::FILTER_AND ? true : false)); |
218
|
|
|
|
219
|
|
|
$value = implode(',', $value); |
220
|
|
|
$encoded_value = rawurlencode($value); |
221
|
|
|
$filter_querystring .= sprintf("filter[%s]=%s&", $handle, $encoded_value); |
222
|
|
|
|
223
|
|
|
// Some fields require that prepopulation be done via ID. RE: #2331 |
224
|
|
|
if (!is_numeric($value) && method_exists($field, 'fetchIDfromValue')) { |
225
|
|
|
$encoded_value = $field->fetchIDfromValue($value); |
|
|
|
|
226
|
|
|
} |
227
|
|
|
$prepopulate_querystring .= sprintf("prepopulate[%d]=%s&", $field_id, $encoded_value); |
228
|
|
|
} else { |
229
|
|
|
unset($filters[$handle]); |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
$filter_querystring = preg_replace("/&$/", '', $filter_querystring); |
235
|
|
|
$prepopulate_querystring = preg_replace("/&$/", '', $prepopulate_querystring); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
Sortable::initialize($this, $entries, $sort, $order, array( |
239
|
|
|
'current-section' => $section, |
240
|
|
|
'filters' => ($filter_querystring ? "&" . $filter_querystring : ''), |
241
|
|
|
'unsort' => isset($_REQUEST['unsort']) |
242
|
|
|
)); |
243
|
|
|
|
244
|
|
|
$this->Form->setAttribute('action', |
245
|
|
|
Administration::instance()->getCurrentPageURL() . '?pg=' . $current_page . ($filter_querystring ? "&" . $filter_querystring : '')); |
246
|
|
|
|
247
|
|
|
// Build filtering interface |
248
|
|
|
$this->createFilteringInterface(); |
249
|
|
|
|
250
|
|
|
$subheading_buttons = array( |
251
|
|
|
Widget::Anchor(__('Create New'), |
252
|
|
|
Administration::instance()->getCurrentPageURL() . 'new/' . ($prepopulate_querystring ? '?' . $prepopulate_querystring : ''), |
253
|
|
|
__('Create a new entry'), 'create button', null, array('accesskey' => 'c')) |
254
|
|
|
); |
255
|
|
|
|
256
|
|
|
// Only show the Edit Section button if the Author is a developer. #938 ^BA |
257
|
|
|
if (Symphony::Author()->isDeveloper()) { |
258
|
|
|
array_unshift($subheading_buttons, |
259
|
|
|
Widget::Anchor(__('Edit Section'), SYMPHONY_URL . '/blueprints/sections/edit/' . $section_id . '/', |
260
|
|
|
__('Edit Section Configuration'), 'button')); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
$this->appendSubheading($section->get('name'), $subheading_buttons); |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Allows adjustments to be made to the SQL where and joins statements |
267
|
|
|
* before they are used to fetch the entries for the page |
268
|
|
|
* |
269
|
|
|
* @delegate AdjustPublishFiltering |
270
|
|
|
* @since Symphony 2.3.3 |
271
|
|
|
* @param string $context |
272
|
|
|
* '/publish/' |
273
|
|
|
* @param integer $section_id |
274
|
|
|
* An array of the current columns, passed by reference |
275
|
|
|
* @param string $where |
276
|
|
|
* The current where statement, or null if not set |
277
|
|
|
* @param string $joins |
278
|
|
|
*/ |
279
|
|
|
Symphony::ExtensionManager()->notifyMembers('AdjustPublishFiltering', '/publish/', |
280
|
|
|
array('section-id' => $section_id, 'where' => &$where, 'joins' => &$joins)); |
281
|
|
|
|
282
|
|
|
// Check that the filtered query fails that the filter is dropped and an |
283
|
|
|
// error is logged. #841 ^BA |
284
|
|
|
try { |
285
|
|
|
$entries = EntryManager::fetchByPage($current_page, $section_id, |
286
|
|
|
Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'), $where, $joins, true); |
287
|
|
|
} catch (DatabaseException $ex) { |
288
|
|
|
$this->pageAlert(__('An error occurred while retrieving filtered entries. Showing all entries instead.'), |
289
|
|
|
Alert::ERROR); |
290
|
|
|
$filter_querystring = null; |
291
|
|
|
Symphony::Log()->warning(sprintf( |
292
|
|
|
'%s - %s%s%s', |
293
|
|
|
$section->get('name') . ' Publish Index', |
294
|
|
|
$ex->getMessage(), |
295
|
|
|
($ex->getFile() ? " in file " . $ex->getFile() : null), |
296
|
|
|
($ex->getLine() ? " on line " . $ex->getLine() : null) |
297
|
|
|
)); |
298
|
|
|
$entries = EntryManager::fetchByPage($current_page, $section_id, |
299
|
|
|
Symphony::Configuration()->get('pagination_maximum_rows', 'symphony')); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
// Flag filtering |
303
|
|
|
if (isset($_REQUEST['filter'])) { |
304
|
|
|
$filter_stats = new XMLElement('p', '<span>– ' . __('%d of %d entries (filtered)', |
305
|
|
|
array($entries['total-entries'], EntryManager::fetchCount($section_id))) . '</span>', |
306
|
|
|
array('class' => 'inactive')); |
307
|
|
|
} else { |
308
|
|
|
$filter_stats = new XMLElement('p', |
309
|
|
|
'<span>– ' . __('%d entries', array($entries['total-entries'])) . '</span>', |
310
|
|
|
array('class' => 'inactive')); |
311
|
|
|
} |
312
|
|
|
$this->Breadcrumbs->appendChild($filter_stats); |
313
|
|
|
|
314
|
|
|
// Build table |
315
|
|
|
$visible_columns = $section->fetchVisibleColumns(); |
316
|
|
|
$columns = array(); |
317
|
|
|
|
318
|
|
|
if (is_array($visible_columns) && !empty($visible_columns)) { |
319
|
|
|
foreach ($visible_columns as $column) { |
320
|
|
|
$columns[] = array( |
321
|
|
|
'label' => $column->get('label'), |
322
|
|
|
'sortable' => $column->isSortable(), |
323
|
|
|
'handle' => $column->get('id'), |
324
|
|
|
'attrs' => array( |
325
|
|
|
'id' => 'field-' . $column->get('id'), |
326
|
|
|
'class' => 'field-' . $column->get('type') |
327
|
|
|
) |
328
|
|
|
); |
329
|
|
|
} |
330
|
|
|
} else { |
331
|
|
|
$columns[] = array( |
332
|
|
|
'label' => __('ID'), |
333
|
|
|
'sortable' => true, |
334
|
|
|
'handle' => 'id' |
335
|
|
|
); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
$aTableHead = Sortable::buildTableHeaders($columns, $sort, $order, |
339
|
|
|
($filter_querystring) ? "&" . $filter_querystring : ''); |
340
|
|
|
|
341
|
|
|
$child_sections = array(); |
342
|
|
|
$associated_sections = $section->fetchChildAssociations(true); |
343
|
|
|
|
344
|
|
|
if (is_array($associated_sections) && !empty($associated_sections)) { |
345
|
|
|
foreach ($associated_sections as $key => $as) { |
346
|
|
|
$child_sections[$key] = SectionManager::fetch($as['child_section_id']); |
347
|
|
|
$aTableHead[] = array($child_sections[$key]->get('name'), 'col'); |
348
|
|
|
} |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* Allows the creation of custom table columns for each entry. Called |
353
|
|
|
* after all the Section Visible columns have been added as well |
354
|
|
|
* as the Section Associations |
355
|
|
|
* |
356
|
|
|
* @delegate AddCustomPublishColumn |
357
|
|
|
* @since Symphony 2.2 |
358
|
|
|
* @param string $context |
359
|
|
|
* '/publish/' |
360
|
|
|
* @param array $tableHead |
361
|
|
|
* An array of the current columns, passed by reference |
362
|
|
|
* @param integer $section_id |
363
|
|
|
* The current Section ID |
364
|
|
|
*/ |
365
|
|
|
Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumn', '/publish/', |
366
|
|
|
array('tableHead' => &$aTableHead, 'section_id' => $section->get('id'))); |
367
|
|
|
|
368
|
|
|
// Table Body |
369
|
|
|
$aTableBody = array(); |
370
|
|
|
|
371
|
|
|
if (!is_array($entries['records']) || empty($entries['records'])) { |
372
|
|
|
$aTableBody = array( |
373
|
|
|
Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', null, count($aTableHead))), |
374
|
|
|
'odd') |
375
|
|
|
); |
376
|
|
|
} else { |
377
|
|
|
$field_pool = array(); |
378
|
|
|
|
379
|
|
|
if (is_array($visible_columns) && !empty($visible_columns)) { |
380
|
|
|
foreach ($visible_columns as $column) { |
381
|
|
|
$field_pool[$column->get('id')] = $column; |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
$link_column = array_reverse($visible_columns); |
386
|
|
|
$link_column = end($link_column); |
387
|
|
|
reset($visible_columns); |
388
|
|
|
|
389
|
|
|
foreach ($entries['records'] as $entry) { |
390
|
|
|
$tableData = array(); |
391
|
|
|
|
392
|
|
|
// Setup each cell |
393
|
|
|
if (!is_array($visible_columns) || empty($visible_columns)) { |
394
|
|
|
$tableData[] = Widget::TableData(Widget::Anchor($entry->get('id'), |
395
|
|
|
Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/')); |
396
|
|
|
} else { |
397
|
|
|
$link = Widget::Anchor( |
398
|
|
|
'', |
399
|
|
|
Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/' . ($filter_querystring ? '?' . $prepopulate_querystring : ''), |
400
|
|
|
$entry->get('id'), |
401
|
|
|
'content' |
402
|
|
|
); |
403
|
|
|
|
404
|
|
|
foreach ($visible_columns as $position => $column) { |
405
|
|
|
$data = $entry->getData($column->get('id')); |
406
|
|
|
$field = $field_pool[$column->get('id')]; |
407
|
|
|
|
408
|
|
|
$value = $field->prepareTableValue($data, ($column === $link_column) ? $link : null, |
409
|
|
|
$entry->get('id')); |
410
|
|
|
|
411
|
|
|
if (!is_object($value) && (strlen(trim($value)) === 0 || $value === __('None'))) { |
412
|
|
|
$value = ($position === 0 ? $link->generate() : __('None')); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
if ($value === __('None')) { |
416
|
|
|
$tableData[] = Widget::TableData($value, |
417
|
|
|
'inactive field-' . $column->get('type') . ' field-' . $column->get('id')); |
418
|
|
|
} else { |
419
|
|
|
$tableData[] = Widget::TableData($value, |
420
|
|
|
'field-' . $column->get('type') . ' field-' . $column->get('id')); |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
unset($field); |
424
|
|
|
} |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
if (is_array($child_sections) && !empty($child_sections)) { |
428
|
|
|
foreach ($child_sections as $key => $as) { |
429
|
|
|
$field = FieldManager::fetch((int)$associated_sections[$key]['child_section_field_id']); |
430
|
|
|
$parent_section_field_id = (int)$associated_sections[$key]['parent_section_field_id']; |
431
|
|
|
|
432
|
|
|
if (!is_null($parent_section_field_id)) { |
433
|
|
|
$search_value = $field->fetchAssociatedEntrySearchValue( |
434
|
|
|
$entry->getData($parent_section_field_id), |
435
|
|
|
$parent_section_field_id, |
436
|
|
|
$entry->get('id') |
437
|
|
|
); |
438
|
|
|
} else { |
439
|
|
|
$search_value = $entry->get('id'); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
if (!is_array($search_value)) { |
443
|
|
|
$associated_entry_count = $field->fetchAssociatedEntryCount($search_value); |
444
|
|
|
|
445
|
|
|
$tableData[] = Widget::TableData( |
446
|
|
|
Widget::Anchor( |
447
|
|
|
sprintf('%d →', max(0, intval($associated_entry_count))), |
448
|
|
|
sprintf( |
449
|
|
|
'%s/publish/%s/?filter[%s]=%s', |
450
|
|
|
SYMPHONY_URL, |
451
|
|
|
$as->get('handle'), |
452
|
|
|
$field->get('element_name'), |
453
|
|
|
rawurlencode($search_value) |
454
|
|
|
), |
455
|
|
|
$entry->get('id'), |
456
|
|
|
'content' |
457
|
|
|
) |
458
|
|
|
); |
459
|
|
|
} |
460
|
|
|
} |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Allows Extensions to inject custom table data for each Entry |
465
|
|
|
* into the Publish Index |
466
|
|
|
* |
467
|
|
|
* @delegate AddCustomPublishColumnData |
468
|
|
|
* @since Symphony 2.2 |
469
|
|
|
* @param string $context |
470
|
|
|
* '/publish/' |
471
|
|
|
* @param array $tableData |
472
|
|
|
* An array of `Widget::TableData`, passed by reference |
473
|
|
|
* @param integer $section_id |
474
|
|
|
* The current Section ID |
475
|
|
|
* @param Entry $entry_id |
476
|
|
|
* The entry object, please note that this is by error and this will |
477
|
|
|
* be removed in Symphony 2.4. The entry object is available in |
478
|
|
|
* the 'entry' key as of Symphony 2.3.1. |
479
|
|
|
* @param Entry $entry |
480
|
|
|
* The entry object for this row |
481
|
|
|
*/ |
482
|
|
|
Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumnData', '/publish/', array( |
483
|
|
|
'tableData' => &$tableData, |
484
|
|
|
'section_id' => $section->get('id'), |
485
|
|
|
'entry_id' => $entry, |
486
|
|
|
'entry' => $entry |
487
|
|
|
)); |
488
|
|
|
|
489
|
|
|
$tableData[count($tableData) - 1]->appendChild(Widget::Label(__('Select Entry %d', |
490
|
|
|
array($entry->get('id'))), null, 'accessible', null, array( |
491
|
|
|
'for' => 'entry-' . $entry->get('id') |
492
|
|
|
))); |
493
|
|
|
$tableData[count($tableData) - 1]->appendChild(Widget::Input('items[' . $entry->get('id') . ']', |
494
|
|
|
null, 'checkbox', array( |
495
|
|
|
'id' => 'entry-' . $entry->get('id') |
496
|
|
|
))); |
497
|
|
|
|
498
|
|
|
// Add a row to the body array, assigning each cell to the row |
499
|
|
|
$aTableBody[] = Widget::TableRow($tableData, null, 'id-' . $entry->get('id')); |
500
|
|
|
} |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
$table = Widget::Table( |
504
|
|
|
Widget::TableHead($aTableHead), |
505
|
|
|
null, |
506
|
|
|
Widget::TableBody($aTableBody), |
507
|
|
|
'selectable', |
508
|
|
|
null, |
509
|
|
|
array( |
510
|
|
|
'role' => 'directory', |
511
|
|
|
'aria-labelledby' => 'symphony-subheading', |
512
|
|
|
'data-interactive' => 'data-interactive' |
513
|
|
|
) |
514
|
|
|
); |
515
|
|
|
|
516
|
|
|
$this->Form->appendChild($table); |
517
|
|
|
|
518
|
|
|
$tableActions = new XMLElement('div'); |
519
|
|
|
$tableActions->setAttribute('class', 'actions'); |
520
|
|
|
|
521
|
|
|
$options = array( |
522
|
|
|
array(null, false, __('With Selected...')), |
523
|
|
|
array( |
524
|
|
|
'delete', |
525
|
|
|
false, |
526
|
|
|
__('Delete'), |
527
|
|
|
'confirm', |
528
|
|
|
null, |
529
|
|
|
array( |
530
|
|
|
'data-message' => __('Are you sure you want to delete the selected entries?') |
531
|
|
|
) |
532
|
|
|
) |
533
|
|
|
); |
534
|
|
|
|
535
|
|
|
$toggable_fields = $section->fetchToggleableFields(); |
536
|
|
|
|
537
|
|
|
if (is_array($toggable_fields) && !empty($toggable_fields)) { |
538
|
|
|
$index = 2; |
539
|
|
|
|
540
|
|
|
foreach ($toggable_fields as $field) { |
541
|
|
|
$toggle_states = $field->getToggleStates(); |
542
|
|
|
|
543
|
|
|
if (is_array($toggle_states)) { |
544
|
|
|
$options[$index] = array( |
545
|
|
|
'label' => __('Set %s', array($field->get('label'))), |
546
|
|
|
'options' => array() |
547
|
|
|
); |
548
|
|
|
|
549
|
|
|
foreach ($toggle_states as $value => $state) { |
550
|
|
|
$options[$index]['options'][] = array( |
551
|
|
|
'toggle-' . $field->get('id') . '-' . $value, |
552
|
|
|
false, |
553
|
|
|
$state |
554
|
|
|
); |
555
|
|
|
} |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
$index++; |
559
|
|
|
} |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Allows an extension to modify the existing options for this page's |
564
|
|
|
* With Selected menu. If the `$options` parameter is an empty array, |
565
|
|
|
* the 'With Selected' menu will not be rendered. |
566
|
|
|
* |
567
|
|
|
* @delegate AddCustomActions |
568
|
|
|
* @since Symphony 2.3.2 |
569
|
|
|
* @param string $context |
570
|
|
|
* '/publish/' |
571
|
|
|
* @param array $options |
572
|
|
|
* An array of arrays, where each child array represents an option |
573
|
|
|
* in the With Selected menu. Options should follow the same format |
574
|
|
|
* expected by `Widget::__SelectBuildOption`. Passed by reference. |
575
|
|
|
*/ |
576
|
|
|
Symphony::ExtensionManager()->notifyMembers('AddCustomActions', '/publish/', array( |
577
|
|
|
'options' => &$options |
578
|
|
|
)); |
579
|
|
|
|
580
|
|
|
if (!empty($options)) { |
581
|
|
|
$tableActions->appendChild(Widget::Apply($options)); |
582
|
|
|
$this->Form->appendChild($tableActions); |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
if ($entries['total-pages'] > 1) { |
586
|
|
|
$ul = new XMLElement('ul'); |
587
|
|
|
$ul->setAttribute('class', 'page'); |
588
|
|
|
|
589
|
|
|
// First |
590
|
|
|
$li = new XMLElement('li'); |
591
|
|
|
|
592
|
|
|
if ($current_page > 1) { |
593
|
|
|
$li->appendChild(Widget::Anchor(__('First'), |
594
|
|
|
Administration::instance()->getCurrentPageURL() . '?pg=1' . ($filter_querystring ? "&" . $filter_querystring : ''))); |
595
|
|
|
} else { |
596
|
|
|
$li->setValue(__('First')); |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
$ul->appendChild($li); |
600
|
|
|
|
601
|
|
|
// Previous |
602
|
|
|
$li = new XMLElement('li'); |
603
|
|
|
|
604
|
|
View Code Duplication |
if ($current_page > 1) { |
605
|
|
|
$li->appendChild(Widget::Anchor(__('← Previous'), |
606
|
|
|
Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page - 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); |
607
|
|
|
} else { |
608
|
|
|
$li->setValue(__('← Previous')); |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
$ul->appendChild($li); |
612
|
|
|
|
613
|
|
|
// Summary |
614
|
|
|
$li = new XMLElement('li'); |
615
|
|
|
|
616
|
|
|
$li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array( |
617
|
|
|
$entries['start'], |
618
|
|
|
($current_page !== $entries['total-pages']) ? $current_page * Symphony::Configuration()->get('pagination_maximum_rows', |
619
|
|
|
'symphony') : $entries['total-entries'], |
620
|
|
|
$entries['total-entries'] |
621
|
|
|
))); |
622
|
|
|
|
623
|
|
|
$pgform = Widget::Form(Administration::instance()->getCurrentPageURL(), 'get', 'paginationform'); |
624
|
|
|
|
625
|
|
|
$pgmax = max($current_page, $entries['total-pages']); |
626
|
|
|
$pgform->appendChild(Widget::Input('pg', null, 'text', array( |
627
|
|
|
'data-active' => __('Go to page …'), |
628
|
|
|
'data-inactive' => __('Page %1$s of %2$s', array((string)$current_page, $pgmax)), |
629
|
|
|
'data-max' => $pgmax |
630
|
|
|
))); |
631
|
|
|
|
632
|
|
|
$li->appendChild($pgform); |
633
|
|
|
$ul->appendChild($li); |
634
|
|
|
|
635
|
|
|
// Next |
636
|
|
|
$li = new XMLElement('li'); |
637
|
|
|
|
638
|
|
View Code Duplication |
if ($current_page < $entries['total-pages']) { |
639
|
|
|
$li->appendChild(Widget::Anchor(__('Next →'), |
640
|
|
|
Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page + 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); |
641
|
|
|
} else { |
642
|
|
|
$li->setValue(__('Next →')); |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
$ul->appendChild($li); |
646
|
|
|
|
647
|
|
|
// Last |
648
|
|
|
$li = new XMLElement('li'); |
649
|
|
|
|
650
|
|
View Code Duplication |
if ($current_page < $entries['total-pages']) { |
651
|
|
|
$li->appendChild(Widget::Anchor(__('Last'), |
652
|
|
|
Administration::instance()->getCurrentPageURL() . '?pg=' . $entries['total-pages'] . ($filter_querystring ? "&" . $filter_querystring : ''))); |
653
|
|
|
} else { |
654
|
|
|
$li->setValue(__('Last')); |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
$ul->appendChild($li); |
658
|
|
|
|
659
|
|
|
$this->Contents->appendChild($ul); |
660
|
|
|
} |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* Append filtering interface |
665
|
|
|
*/ |
666
|
|
|
public function createFilteringInterface() |
667
|
|
|
{ |
668
|
|
|
//Check if section has filtering enabled |
669
|
|
|
$context = $this->getContext(); |
670
|
|
|
$handle = $context['section_handle']; |
671
|
|
|
$section_id = SectionManager::fetchIDFromHandle($handle); |
672
|
|
|
$section = SectionManager::fetch($section_id); |
673
|
|
|
$filter = $section->get('filter'); |
674
|
|
|
$count = EntryManager::fetchCount($section_id); |
675
|
|
|
|
676
|
|
|
if ($filter !== 'no' && $count > 1) { |
677
|
|
|
$drawer = Widget::Drawer('filtering-' . $section_id, __('Filter Entries'), |
678
|
|
|
$this->createFilteringDrawer($section)); |
|
|
|
|
679
|
|
|
$drawer->addClass('drawer-filtering'); |
680
|
|
|
$this->insertDrawer($drawer); |
681
|
|
|
} |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
/** |
685
|
|
|
* Create filtering drawer |
686
|
|
|
* |
687
|
|
|
* @param Section $section |
688
|
|
|
* @return XMLElement |
689
|
|
|
*/ |
690
|
|
|
public function createFilteringDrawer(Section $section) |
691
|
|
|
{ |
692
|
|
|
$this->filteringForm = Widget::Form(null, 'get', 'filtering'); |
|
|
|
|
693
|
|
|
$this->createFilteringDuplicator($section); |
694
|
|
|
|
695
|
|
|
return $this->filteringForm; |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
public function createFilteringDuplicator($section) |
699
|
|
|
{ |
700
|
|
|
$div = new XMLElement('div'); |
701
|
|
|
$div->setAttribute('class', 'frame filters-duplicator'); |
702
|
|
|
$div->setAttribute('data-interactive', 'data-interactive'); |
703
|
|
|
|
704
|
|
|
$ol = new XMLElement('ol'); |
705
|
|
|
$ol->setAttribute('data-add', __('Add filter')); |
706
|
|
|
$ol->setAttribute('data-remove', __('Clear filter')); |
707
|
|
|
$ol->setAttribute('data-empty', __('No filters applied yet.')); |
708
|
|
|
|
709
|
|
|
$this->createFieldFilters($ol, $section); |
710
|
|
|
$this->createSystemDateFilters($ol); |
711
|
|
|
|
712
|
|
|
$div->appendChild($ol); |
713
|
|
|
$this->filteringForm->appendChild($div); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
private function createFieldFilters(&$wrapper, $section) |
717
|
|
|
{ |
718
|
|
|
$filters = $_GET['filter']; |
719
|
|
|
|
720
|
|
|
foreach ($section->fetchFilterableFields() as $field) { |
721
|
|
|
if (!$field->canPublishFilter()) { |
722
|
|
|
continue; |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
$filter = $filters[$field->get('element_name')]; |
726
|
|
|
|
727
|
|
|
// Filter data |
728
|
|
|
$data = array(); |
729
|
|
|
$data['type'] = $field->get('element_name'); |
730
|
|
|
$data['name'] = $field->get('label'); |
731
|
|
|
$data['filter'] = $filter; |
732
|
|
|
$data['instance'] = 'unique'; |
733
|
|
|
$data['search'] = $field->fetchSuggestionTypes(); |
734
|
|
|
$data['operators'] = $field->fetchFilterableOperators(); |
735
|
|
|
$data['comparisons'] = $this->createFilterComparisons($data); |
736
|
|
|
$data['query'] = $this->getFilterQuery($data); |
737
|
|
|
$data['field-id'] = $field->get('id'); |
738
|
|
|
|
739
|
|
|
// Add existing filter |
740
|
|
|
if (isset($filter)) { |
741
|
|
|
$this->createFilter($wrapper, $data); |
742
|
|
|
} |
743
|
|
|
|
744
|
|
|
// Add filter template |
745
|
|
|
$data['instance'] = 'unique template'; |
746
|
|
|
$data['query'] = ''; |
747
|
|
|
$this->createFilter($wrapper, $data); |
748
|
|
|
} |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
private function createFilterComparisons($data) |
752
|
|
|
{ |
753
|
|
|
// Default comparison |
754
|
|
|
$comparisons = array(); |
755
|
|
|
|
756
|
|
|
// Custom field comparisons |
757
|
|
|
foreach ($data['operators'] as $operator) { |
758
|
|
|
$filter = trim($operator['filter']); |
759
|
|
|
|
760
|
|
|
$comparisons[] = array( |
761
|
|
|
$filter, |
762
|
|
|
(!empty($filter) && strpos($data['filter'], $filter) === 0), |
763
|
|
|
__($operator['title']) |
764
|
|
|
); |
765
|
|
|
} |
766
|
|
|
|
767
|
|
|
return $comparisons; |
768
|
|
|
} |
769
|
|
|
|
770
|
|
|
private function getFilterQuery($data) |
771
|
|
|
{ |
772
|
|
|
$query = $data['filter']; |
773
|
|
|
|
774
|
|
|
foreach ($data['operators'] as $operator) { |
775
|
|
|
$filter = trim($operator['filter']); |
776
|
|
|
|
777
|
|
|
if (!empty($filter) && strpos($data['filter'], $filter) === 0) { |
778
|
|
|
$query = substr($data['filter'], strlen($filter)); |
779
|
|
|
} |
780
|
|
|
} |
781
|
|
|
|
782
|
|
|
return (string)$query; |
783
|
|
|
} |
784
|
|
|
|
785
|
|
|
private function createFilter(&$wrapper, $data) |
786
|
|
|
{ |
787
|
|
|
$li = new XMLElement('li'); |
788
|
|
|
$li->setAttribute('class', $data['instance']); |
789
|
|
|
$li->setAttribute('data-type', $data['type']); |
790
|
|
|
|
791
|
|
|
// Header |
792
|
|
|
$li->appendChild(new XMLElement('header', $data['name'], array( |
793
|
|
|
'data-name' => $data['name'] |
794
|
|
|
))); |
795
|
|
|
|
796
|
|
|
// Settings |
797
|
|
|
$div = new XMLElement('div', null, array('class' => 'two columns')); |
798
|
|
|
|
799
|
|
|
// Comparisons |
800
|
|
|
$label = Widget::Label(); |
801
|
|
|
$label->setAttribute('class', 'column secondary'); |
802
|
|
|
|
803
|
|
|
$select = Widget::Select($data['type'] . '-comparison', $data['comparisons'], array( |
804
|
|
|
'class' => 'comparison' |
805
|
|
|
)); |
806
|
|
|
|
807
|
|
|
$label->appendChild($select); |
808
|
|
|
$div->appendChild($label); |
809
|
|
|
|
810
|
|
|
// Query |
811
|
|
|
$label = Widget::Label(); |
812
|
|
|
$label->setAttribute('class', 'column primary'); |
813
|
|
|
|
814
|
|
|
$input = Widget::Input($data['type'], $data['query'], 'text', array( |
815
|
|
|
'placeholder' => __('Type and hit enter to apply filter…'), |
816
|
|
|
'autocomplete' => 'off' |
817
|
|
|
)); |
818
|
|
|
$input->setAttribute('class', 'filter'); |
819
|
|
|
$label->appendChild($input); |
820
|
|
|
|
821
|
|
|
$this->createFilterSuggestions($label, $data); |
822
|
|
|
|
823
|
|
|
$div->appendChild($label); |
824
|
|
|
$li->appendChild($div); |
825
|
|
|
$wrapper->appendChild($li); |
826
|
|
|
} |
827
|
|
|
|
828
|
|
|
private function createFilterSuggestions(&$wrapper, $data) |
829
|
|
|
{ |
830
|
|
|
$ul = new XMLElement('ul'); |
831
|
|
|
$ul->setAttribute('class', 'suggestions'); |
832
|
|
|
$ul->setAttribute('data-field-id', $data['field-id']); |
833
|
|
|
$ul->setAttribute('data-associated-ids', '0'); |
834
|
|
|
$ul->setAttribute('data-search-types', implode($data['search'], ',')); |
835
|
|
|
|
836
|
|
|
// Add help text for each filter operator |
837
|
|
|
foreach ($data['operators'] as $operator) { |
838
|
|
|
$this->createFilterHelp($ul, $operator); |
839
|
|
|
} |
840
|
|
|
|
841
|
|
|
$wrapper->appendChild($ul); |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
private function createFilterHelp(&$wrapper, $operator) |
845
|
|
|
{ |
846
|
|
|
if (empty($operator['help'])) { |
847
|
|
|
return; |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
$li = new XMLElement('li', __('Comparison mode') . ': ' . $operator['help'], array( |
851
|
|
|
'class' => 'help', |
852
|
|
|
'data-comparison' => trim($operator['filter']) |
853
|
|
|
)); |
854
|
|
|
|
855
|
|
|
$wrapper->appendChild($li); |
856
|
|
|
} |
857
|
|
|
|
858
|
|
|
private function createSystemDateFilters(&$wrapper) |
859
|
|
|
{ |
860
|
|
|
$filters = $_GET['filter']; |
861
|
|
|
$dateField = new FieldDate; |
862
|
|
|
|
863
|
|
|
$fields = array( |
864
|
|
|
array( |
865
|
|
|
'type' => 'system:creation-date', |
866
|
|
|
'label' => __('System Creation Date') |
867
|
|
|
), |
868
|
|
|
array( |
869
|
|
|
'type' => 'system:modification-date', |
870
|
|
|
'label' => __('System Modification Date') |
871
|
|
|
) |
872
|
|
|
); |
873
|
|
|
|
874
|
|
|
foreach ($fields as $field) { |
875
|
|
|
$filter = $filters[$field['type']]; |
876
|
|
|
|
877
|
|
|
// Filter data |
878
|
|
|
$data = array(); |
879
|
|
|
$data['type'] = $field['type']; |
880
|
|
|
$data['name'] = $field['label']; |
881
|
|
|
$data['filter'] = $filter; |
882
|
|
|
$data['instance'] = 'unique'; |
883
|
|
|
$data['search'] = $dateField->fetchSuggestionTypes(); |
884
|
|
|
$data['operators'] = $dateField->fetchFilterableOperators(); |
885
|
|
|
$data['comparisons'] = $this->createFilterComparisons($data); |
886
|
|
|
$data['query'] = $this->getFilterQuery($data); |
887
|
|
|
|
888
|
|
|
// Add existing filter |
889
|
|
|
if (isset($filter)) { |
890
|
|
|
$this->createFilter($wrapper, $data); |
891
|
|
|
} |
892
|
|
|
|
893
|
|
|
// Add filter template |
894
|
|
|
$data['instance'] = 'unique template'; |
895
|
|
|
$data['query'] = ''; |
896
|
|
|
$this->createFilter($wrapper, $data); |
897
|
|
|
} |
898
|
|
|
} |
899
|
|
|
|
900
|
|
|
public function __actionIndex() |
|
|
|
|
901
|
|
|
{ |
902
|
|
|
$checked = (is_array($_POST['items'])) ? array_keys($_POST['items']) : null; |
903
|
|
|
|
904
|
|
|
if (is_array($checked) && !empty($checked)) { |
905
|
|
|
/** |
906
|
|
|
* Extensions can listen for any custom actions that were added |
907
|
|
|
* through `AddCustomPreferenceFieldsets` or `AddCustomActions` |
908
|
|
|
* delegates. |
909
|
|
|
* |
910
|
|
|
* @delegate CustomActions |
911
|
|
|
* @since Symphony 2.3.2 |
912
|
|
|
* @param string $context |
913
|
|
|
* '/publish/' |
914
|
|
|
* @param array $checked |
915
|
|
|
* An array of the selected rows. The value is usually the ID of the |
916
|
|
|
* the associated object. |
917
|
|
|
*/ |
918
|
|
|
Symphony::ExtensionManager()->notifyMembers('CustomActions', '/publish/', array( |
919
|
|
|
'checked' => $checked |
920
|
|
|
)); |
921
|
|
|
|
922
|
|
|
switch ($_POST['with-selected']) { |
923
|
|
|
case 'delete': |
924
|
|
|
/** |
925
|
|
|
* Prior to deletion of entries. An array of Entry ID's is provided which |
926
|
|
|
* can be manipulated. This delegate was renamed from `Delete` to `EntryPreDelete` |
927
|
|
|
* in Symphony 2.3. |
928
|
|
|
* |
929
|
|
|
* @delegate EntryPreDelete |
930
|
|
|
* @param string $context |
931
|
|
|
* '/publish/' |
932
|
|
|
* @param array $entry_id |
933
|
|
|
* An array of Entry ID's passed by reference |
934
|
|
|
*/ |
935
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreDelete', '/publish/', |
936
|
|
|
array('entry_id' => &$checked)); |
937
|
|
|
|
938
|
|
|
EntryManager::delete($checked); |
939
|
|
|
|
940
|
|
|
/** |
941
|
|
|
* After the deletion of entries, this delegate provides an array of Entry ID's |
942
|
|
|
* that were deleted. |
943
|
|
|
* |
944
|
|
|
* @since Symphony 2.3 |
945
|
|
|
* @delegate EntryPostDelete |
946
|
|
|
* @param string $context |
947
|
|
|
* '/publish/' |
948
|
|
|
* @param array $entry_id |
949
|
|
|
* An array of Entry ID's that were deleted. |
950
|
|
|
*/ |
951
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPostDelete', '/publish/', |
952
|
|
|
array('entry_id' => $checked)); |
953
|
|
|
|
954
|
|
|
redirect($_SERVER['REQUEST_URI']); |
955
|
|
|
break; |
956
|
|
|
default: |
957
|
|
|
list($option, $field_id, $value) = explode('-', $_POST['with-selected'], 3); |
958
|
|
|
|
959
|
|
|
if ($option === 'toggle') { |
960
|
|
|
$field = FieldManager::fetch($field_id); |
961
|
|
|
$fields = array($field->get('element_name') => $value); |
962
|
|
|
|
963
|
|
|
$section = SectionManager::fetch($field->get('parent_section')); |
964
|
|
|
|
965
|
|
|
foreach ($checked as $entry_id) { |
966
|
|
|
$entry = EntryManager::fetch($entry_id); |
967
|
|
|
$existing_data = $entry[0]->getData($field_id); |
968
|
|
|
$entry[0]->setData($field_id, |
969
|
|
|
$field->toggleFieldData(is_array($existing_data) ? $existing_data : array(), $value, |
970
|
|
|
$entry_id)); |
971
|
|
|
|
972
|
|
|
/** |
973
|
|
|
* Just prior to editing of an Entry |
974
|
|
|
* |
975
|
|
|
* @delegate EntryPreEdit |
976
|
|
|
* @param string $context |
977
|
|
|
* '/publish/edit/' |
978
|
|
|
* @param Section $section |
979
|
|
|
* @param Entry $entry |
980
|
|
|
* @param array $fields |
981
|
|
|
*/ |
982
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreEdit', '/publish/edit/', array( |
983
|
|
|
'section' => $section, |
984
|
|
|
'entry' => &$entry[0], |
985
|
|
|
'fields' => $fields |
986
|
|
|
)); |
987
|
|
|
|
988
|
|
|
$entry[0]->commit(); |
989
|
|
|
|
990
|
|
|
/** |
991
|
|
|
* Editing an entry. Entry object is provided. |
992
|
|
|
* |
993
|
|
|
* @delegate EntryPostEdit |
994
|
|
|
* @param string $context |
995
|
|
|
* '/publish/edit/' |
996
|
|
|
* @param Section $section |
997
|
|
|
* @param Entry $entry |
998
|
|
|
* @param array $fields |
999
|
|
|
*/ |
1000
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPostEdit', '/publish/edit/', array( |
1001
|
|
|
'section' => $section, |
1002
|
|
|
'entry' => $entry[0], |
1003
|
|
|
'fields' => $fields |
1004
|
|
|
)); |
1005
|
|
|
} |
1006
|
|
|
|
1007
|
|
|
redirect($_SERVER['REQUEST_URI']); |
1008
|
|
|
} |
1009
|
|
|
} |
1010
|
|
|
} |
1011
|
|
|
} |
1012
|
|
|
|
1013
|
|
|
public function __viewNew() |
|
|
|
|
1014
|
|
|
{ |
1015
|
|
View Code Duplication |
if (!$section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle'])) { |
1016
|
|
|
Administration::instance()->throwCustomError( |
1017
|
|
|
__('The Section, %s, could not be found.', |
1018
|
|
|
array('<code>' . $this->_context['section_handle'] . '</code>')), |
1019
|
|
|
__('Unknown Section'), |
1020
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
1021
|
|
|
); |
1022
|
|
|
} |
1023
|
|
|
|
1024
|
|
|
$section = SectionManager::fetch($section_id); |
1025
|
|
|
|
1026
|
|
|
$this->setPageType('form'); |
1027
|
|
|
$this->setTitle(__('%1$s – %2$s', array($section->get('name'), __('Symphony')))); |
1028
|
|
|
|
1029
|
|
|
// Ensure errored entries still maintain any prepopulated values [#2211] |
1030
|
|
|
$this->Form->setAttribute('action', $this->Form->getAttribute('action') . $this->getPrepopulateString()); |
1031
|
|
|
$this->Form->setAttribute('enctype', 'multipart/form-data'); |
1032
|
|
|
|
1033
|
|
|
$sidebar_fields = $section->fetchFields(null, 'sidebar'); |
1034
|
|
|
$main_fields = $section->fetchFields(null, 'main'); |
1035
|
|
|
|
1036
|
|
View Code Duplication |
if (!empty($sidebar_fields) && !empty($main_fields)) { |
1037
|
|
|
$this->Form->setAttribute('class', 'two columns'); |
1038
|
|
|
} else { |
1039
|
|
|
$this->Form->setAttribute('class', 'columns'); |
1040
|
|
|
} |
1041
|
|
|
|
1042
|
|
|
// Only show the Edit Section button if the Author is a developer. #938 ^BA |
1043
|
|
|
if (Symphony::Author()->isDeveloper()) { |
1044
|
|
|
$this->appendSubheading(__('Untitled'), |
1045
|
|
|
Widget::Anchor(__('Edit Section'), SYMPHONY_URL . '/blueprints/sections/edit/' . $section_id . '/', |
1046
|
|
|
__('Edit Section Configuration'), 'button') |
1047
|
|
|
); |
1048
|
|
|
} else { |
1049
|
|
|
$this->appendSubheading(__('Untitled')); |
1050
|
|
|
} |
1051
|
|
|
|
1052
|
|
|
// Build filtered breadcrumb [#1378} |
1053
|
|
|
$this->insertBreadcrumbs(array( |
1054
|
|
|
Widget::Anchor($section->get('name'), |
1055
|
|
|
SYMPHONY_URL . '/publish/' . $this->_context['section_handle'] . '/' . $this->getFilterString()), |
1056
|
|
|
)); |
1057
|
|
|
|
1058
|
|
|
$this->Form->appendChild(Widget::Input('MAX_FILE_SIZE', |
1059
|
|
|
Symphony::Configuration()->get('max_upload_size', 'admin'), 'hidden')); |
1060
|
|
|
|
1061
|
|
|
// If there is post data floating around, due to errors, create an entry object |
1062
|
|
|
if (isset($_POST['fields'])) { |
1063
|
|
|
$entry = EntryManager::create(); |
1064
|
|
|
$entry->set('section_id', $section_id); |
1065
|
|
|
$entry->setDataFromPost($_POST['fields'], $error, true); |
1066
|
|
|
|
1067
|
|
|
// Brand new entry, so need to create some various objects |
1068
|
|
|
} else { |
1069
|
|
|
$entry = EntryManager::create(); |
1070
|
|
|
$entry->set('section_id', $section_id); |
1071
|
|
|
} |
1072
|
|
|
|
1073
|
|
|
// Check if there is a field to prepopulate |
1074
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1075
|
|
|
foreach ($_REQUEST['prepopulate'] as $field_id => $value) { |
1076
|
|
|
$this->Form->prependChild(Widget::Input( |
1077
|
|
|
"prepopulate[{$field_id}]", |
1078
|
|
|
rawurlencode($value), |
1079
|
|
|
'hidden' |
1080
|
|
|
)); |
1081
|
|
|
|
1082
|
|
|
// The actual pre-populating should only happen if there is not existing fields post data |
1083
|
|
|
if (!isset($_POST['fields']) && $field = FieldManager::fetch($field_id)) { |
1084
|
|
|
$entry->setData( |
1085
|
|
|
$field->get('id'), |
1086
|
|
|
$field->processRawFieldData($value, $error, $message, true) |
|
|
|
|
1087
|
|
|
); |
1088
|
|
|
} |
1089
|
|
|
} |
1090
|
|
|
} |
1091
|
|
|
|
1092
|
|
|
$primary = new XMLElement('fieldset'); |
1093
|
|
|
$primary->setAttribute('class', 'primary column'); |
1094
|
|
|
|
1095
|
|
|
if ((!is_array($main_fields) || empty($main_fields)) && (!is_array($sidebar_fields) || empty($sidebar_fields))) { |
1096
|
|
|
$message = __('Fields must be added to this section before an entry can be created.'); |
1097
|
|
|
|
1098
|
|
View Code Duplication |
if (Symphony::Author()->isDeveloper()) { |
1099
|
|
|
$message .= ' <a href="' . SYMPHONY_URL . '/blueprints/sections/edit/' . $section->get('id') . '/" accesskey="c">' |
1100
|
|
|
. __('Add fields') |
1101
|
|
|
. '</a>'; |
1102
|
|
|
} |
1103
|
|
|
|
1104
|
|
|
$this->pageAlert($message, Alert::ERROR); |
1105
|
|
|
} else { |
1106
|
|
View Code Duplication |
if (is_array($main_fields) && !empty($main_fields)) { |
1107
|
|
|
foreach ($main_fields as $field) { |
1108
|
|
|
$primary->appendChild($this->__wrapFieldWithDiv($field, $entry)); |
1109
|
|
|
} |
1110
|
|
|
|
1111
|
|
|
$this->Form->appendChild($primary); |
1112
|
|
|
} |
1113
|
|
|
|
1114
|
|
View Code Duplication |
if (is_array($sidebar_fields) && !empty($sidebar_fields)) { |
1115
|
|
|
$sidebar = new XMLElement('fieldset'); |
1116
|
|
|
$sidebar->setAttribute('class', 'secondary column'); |
1117
|
|
|
|
1118
|
|
|
foreach ($sidebar_fields as $field) { |
1119
|
|
|
$sidebar->appendChild($this->__wrapFieldWithDiv($field, $entry)); |
1120
|
|
|
} |
1121
|
|
|
|
1122
|
|
|
$this->Form->appendChild($sidebar); |
1123
|
|
|
} |
1124
|
|
|
|
1125
|
|
|
$div = new XMLElement('div'); |
1126
|
|
|
$div->setAttribute('class', 'actions'); |
1127
|
|
|
$div->appendChild(Widget::Input('action[save]', __('Create Entry'), 'submit', |
1128
|
|
|
array('accesskey' => 's'))); |
1129
|
|
|
|
1130
|
|
|
$this->Form->appendChild($div); |
1131
|
|
|
|
1132
|
|
|
// Create a Drawer for Associated Sections |
1133
|
|
|
$this->prepareAssociationsDrawer($section); |
|
|
|
|
1134
|
|
|
} |
1135
|
|
|
} |
1136
|
|
|
|
1137
|
|
|
/** |
1138
|
|
|
* If this entry is being prepopulated, this function will return the prepopulated |
1139
|
|
|
* fields and values as a query string. |
1140
|
|
|
* |
1141
|
|
|
* @since Symphony 2.5.2 |
1142
|
|
|
* @return string |
1143
|
|
|
*/ |
1144
|
|
|
public function getPrepopulateString() |
1145
|
|
|
{ |
1146
|
|
|
$prepopulate_querystring = ''; |
1147
|
|
|
|
1148
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1149
|
|
|
foreach ($_REQUEST['prepopulate'] as $field_id => $value) { |
1150
|
|
|
$prepopulate_querystring .= sprintf("prepopulate[%s]=%s&", $field_id, rawurldecode($value)); |
1151
|
|
|
} |
1152
|
|
|
$prepopulate_querystring = trim($prepopulate_querystring, '&'); |
1153
|
|
|
} |
1154
|
|
|
|
1155
|
|
|
// This is to prevent the value being interpreted as an additional GET |
1156
|
|
|
// parameter. eg. prepopulate[cat]=Minx&June, would come through as: |
1157
|
|
|
// $_GET['cat'] = Minx |
1158
|
|
|
// $_GET['June'] = '' |
1159
|
|
|
$prepopulate_querystring = preg_replace("/&$/", '', $prepopulate_querystring); |
1160
|
|
|
|
1161
|
|
|
return $prepopulate_querystring ? '?' . $prepopulate_querystring : null; |
1162
|
|
|
} |
1163
|
|
|
|
1164
|
|
|
/** |
1165
|
|
|
* If the entry is being prepopulated, we may want to filter other views by this entry's |
1166
|
|
|
* value. This function will create that filter query string. |
1167
|
|
|
* |
1168
|
|
|
* @since Symphony 2.5.2 |
1169
|
|
|
* @return string |
1170
|
|
|
*/ |
1171
|
|
|
public function getFilterString() |
1172
|
|
|
{ |
1173
|
|
|
$filter_querystring = ''; |
1174
|
|
|
|
1175
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1176
|
|
|
foreach ($_REQUEST['prepopulate'] as $field_id => $value) { |
1177
|
|
|
$handle = FieldManager::fetchHandleFromID($field_id); |
1178
|
|
|
|
1179
|
|
|
//This is in case it is an Association so the filter reads the text value instead of the ID |
1180
|
|
|
$field = FieldManager::fetch($field_id); |
1181
|
|
|
if ($field instanceof Field) { |
1182
|
|
|
if (method_exists($field, 'fetchValueFromID')) { |
1183
|
|
|
$value = $field->fetchValueFromID($value); |
|
|
|
|
1184
|
|
|
} |
1185
|
|
|
} |
1186
|
|
|
|
1187
|
|
|
$filter_querystring .= sprintf("filter[%s]=%s&", $handle, rawurldecode($value)); |
1188
|
|
|
} |
1189
|
|
|
$filter_querystring = trim($filter_querystring, '&'); |
1190
|
|
|
} |
1191
|
|
|
|
1192
|
|
|
// This is to prevent the value being interpreted as an additional GET |
1193
|
|
|
// parameter. eg. filter[cat]=Minx&June, would come through as: |
1194
|
|
|
// $_GET['cat'] = Minx |
1195
|
|
|
// $_GET['June'] = '' |
1196
|
|
|
$filter_querystring = preg_replace("/&$/", '', $filter_querystring); |
1197
|
|
|
|
1198
|
|
|
return $filter_querystring ? '?' . $filter_querystring : null; |
1199
|
|
|
} |
1200
|
|
|
|
1201
|
|
|
/** |
1202
|
|
|
* Given a Field and Entry object, this function will wrap |
1203
|
|
|
* the Field's displayPublishPanel result with a div that |
1204
|
|
|
* contains some contextual information such as the Field ID, |
1205
|
|
|
* the Field handle and whether it is required or not. |
1206
|
|
|
* |
1207
|
|
|
* @param Field $field |
1208
|
|
|
* @param Entry $entry |
1209
|
|
|
* @return XMLElement |
1210
|
|
|
*/ |
1211
|
|
|
private function __wrapFieldWithDiv(Field $field, Entry $entry) |
1212
|
|
|
{ |
1213
|
|
|
$is_hidden = $this->isFieldHidden($field); |
1214
|
|
|
$div = new XMLElement('div', null, array( |
1215
|
|
|
'id' => 'field-' . $field->get('id'), |
1216
|
|
|
'class' => 'field field-' . $field->handle() . ($field->get('required') === 'yes' ? ' required' : '') . ($is_hidden === true ? ' irrelevant' : '') |
1217
|
|
|
)); |
1218
|
|
|
|
1219
|
|
|
$field->setAssociationContext($div); |
1220
|
|
|
|
1221
|
|
|
$field->displayPublishPanel( |
1222
|
|
|
$div, $entry->getData($field->get('id')), |
1223
|
|
|
(isset($this->_errors[$field->get('id')]) ? $this->_errors[$field->get('id')] : null), |
1224
|
|
|
null, null, (is_numeric($entry->get('id')) ? $entry->get('id') : null) |
1225
|
|
|
); |
1226
|
|
|
|
1227
|
|
|
/** |
1228
|
|
|
* Allows developers modify the field before it is rendered in the publish |
1229
|
|
|
* form. Passes the `Field` object, `Entry` object, the `XMLElement` div and |
1230
|
|
|
* any errors for the entire `Entry`. Only the `$div` element |
1231
|
|
|
* will be altered before appending to the page, the rest are read only. |
1232
|
|
|
* |
1233
|
|
|
* @since Symphony 2.5.0 |
1234
|
|
|
* @delegate ModifyFieldPublishWidget |
1235
|
|
|
* @param string $context |
1236
|
|
|
* '/backend/' |
1237
|
|
|
* @param Field $field |
1238
|
|
|
* @param Entry $entry |
1239
|
|
|
* @param array $errors |
1240
|
|
|
* @param Widget $widget |
1241
|
|
|
*/ |
1242
|
|
|
Symphony::ExtensionManager()->notifyMembers('ModifyFieldPublishWidget', '/backend/', array( |
1243
|
|
|
'field' => $field, |
1244
|
|
|
'entry' => $entry, |
1245
|
|
|
'errors' => $this->_errors, |
1246
|
|
|
'widget' => &$div |
1247
|
|
|
)); |
1248
|
|
|
|
1249
|
|
|
return $div; |
1250
|
|
|
} |
1251
|
|
|
|
1252
|
|
|
/** |
1253
|
|
|
* Check whether the given `$field` will be hidden because it's been |
1254
|
|
|
* prepopulated. |
1255
|
|
|
* |
1256
|
|
|
* @param Field $field |
1257
|
|
|
* @return boolean |
1258
|
|
|
*/ |
1259
|
|
|
public function isFieldHidden(Field $field) |
1260
|
|
|
{ |
1261
|
|
|
if ($field->get('hide_when_prepopulated') === 'yes') { |
1262
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1263
|
|
|
foreach ($_REQUEST['prepopulate'] as $field_id => $value) { |
1264
|
|
|
if ($field_id === $field->get('id')) { |
1265
|
|
|
return true; |
1266
|
|
|
} |
1267
|
|
|
} |
1268
|
|
|
} |
1269
|
|
|
} |
1270
|
|
|
|
1271
|
|
|
return false; |
1272
|
|
|
} |
1273
|
|
|
|
1274
|
|
|
/** |
1275
|
|
|
* Prepare a Drawer to visualize section associations |
1276
|
|
|
* |
1277
|
|
|
* @param Section $section The current Section object |
1278
|
|
|
* @throws InvalidArgumentException |
1279
|
|
|
* @throws Exception |
1280
|
|
|
*/ |
1281
|
|
|
private function prepareAssociationsDrawer($section) |
1282
|
|
|
{ |
1283
|
|
|
$entry_id = (!is_null($this->_context['entry_id'])) ? $this->_context['entry_id'] : null; |
1284
|
|
|
$show_entries = Symphony::Configuration()->get('association_maximum_rows', 'symphony'); |
1285
|
|
|
|
1286
|
|
|
if (is_null($entry_id) && !isset($_GET['prepopulate']) || is_null($show_entries) || $show_entries === 0) { |
1287
|
|
|
return; |
1288
|
|
|
} |
1289
|
|
|
|
1290
|
|
|
$parent_associations = SectionManager::fetchParentAssociations($section->get('id'), true); |
|
|
|
|
1291
|
|
|
$child_associations = SectionManager::fetchChildAssociations($section->get('id'), true); |
|
|
|
|
1292
|
|
|
$content = null; |
1293
|
|
|
$drawer_position = 'vertical-right'; |
1294
|
|
|
|
1295
|
|
|
/** |
1296
|
|
|
* Prepare Associations Drawer from an Extension |
1297
|
|
|
* |
1298
|
|
|
* @since Symphony 2.3.3 |
1299
|
|
|
* @delegate PrepareAssociationsDrawer |
1300
|
|
|
* @param string $context |
1301
|
|
|
* '/publish/' |
1302
|
|
|
* @param integer $entry_id |
1303
|
|
|
* The entry ID or null |
1304
|
|
|
* @param array $parent_associations |
1305
|
|
|
* Array of Sections |
1306
|
|
|
* @param array $child_associations |
1307
|
|
|
* Array of Sections |
1308
|
|
|
* @param string $drawer_position |
1309
|
|
|
* The position of the Drawer, defaults to `vertical-right`. Available |
1310
|
|
|
* values of `vertical-left, `vertical-right` and `horizontal` |
1311
|
|
|
*/ |
1312
|
|
|
Symphony::ExtensionManager()->notifyMembers('PrepareAssociationsDrawer', '/publish/', array( |
1313
|
|
|
'entry_id' => $entry_id, |
1314
|
|
|
'parent_associations' => &$parent_associations, |
1315
|
|
|
'child_associations' => &$child_associations, |
1316
|
|
|
'content' => &$content, |
1317
|
|
|
'drawer-position' => &$drawer_position |
1318
|
|
|
)); |
1319
|
|
|
|
1320
|
|
|
// If there are no associations, return now. |
1321
|
|
|
if ( |
1322
|
|
|
(is_null($parent_associations) || empty($parent_associations)) |
1323
|
|
|
&& |
1324
|
|
|
(is_null($child_associations) || empty($child_associations)) |
1325
|
|
|
) { |
1326
|
|
|
return; |
1327
|
|
|
} |
1328
|
|
|
|
1329
|
|
|
if (!($content instanceof XMLElement)) { |
1330
|
|
|
$content = new XMLElement('div', null, array('class' => 'content')); |
1331
|
|
|
$content->setSelfClosingTag(false); |
1332
|
|
|
|
1333
|
|
|
// Process Parent Associations |
1334
|
|
|
if (!is_null($parent_associations) && !empty($parent_associations)) { |
1335
|
|
|
foreach ($parent_associations as $as) { |
|
|
|
|
1336
|
|
|
if ($field = FieldManager::fetch($as['parent_section_field_id'])) { |
1337
|
|
|
if (isset($_GET['prepopulate'])) { |
1338
|
|
|
$prepopulate_field = key($_GET['prepopulate']); |
1339
|
|
|
} |
1340
|
|
|
|
1341
|
|
|
// get associated entries if entry exists, |
1342
|
|
|
if ($entry_id) { |
1343
|
|
|
$entry_ids = $field->findParentRelatedEntries($as['child_section_field_id'], $entry_id); |
1344
|
|
|
|
1345
|
|
|
// get prepopulated entry otherwise |
1346
|
|
|
} elseif (isset($_GET['prepopulate'])) { |
1347
|
|
|
$entry_ids = array(intval(current($_GET['prepopulate']))); |
1348
|
|
|
} else { |
1349
|
|
|
$entry_ids = array(); |
1350
|
|
|
} |
1351
|
|
|
|
1352
|
|
|
// Use $schema for perf reasons |
1353
|
|
|
$schema = array($field->get('element_name')); |
1354
|
|
|
$where = (!empty($entry_ids)) ? sprintf(' AND `e`.`id` IN (%s)', |
1355
|
|
|
implode(', ', $entry_ids)) : null; |
1356
|
|
|
$entries = (!empty($entry_ids) || isset($_GET['prepopulate']) && $field->get('id') === $prepopulate_field) |
|
|
|
|
1357
|
|
|
? EntryManager::fetchByPage(1, $as['parent_section_id'], $show_entries, $where, null, |
1358
|
|
|
false, false, true, $schema) |
1359
|
|
|
: array(); |
1360
|
|
|
$has_entries = !empty($entries) && $entries['total-entries'] !== 0; |
1361
|
|
|
|
1362
|
|
|
if ($has_entries) { |
1363
|
|
|
$element = new XMLElement('section', null, array('class' => 'association parent')); |
1364
|
|
|
$header = new XMLElement('header'); |
1365
|
|
|
$header->appendChild(new XMLElement('p', __('Linked to %s in', |
1366
|
|
|
array('<a class="association-section" href="' . SYMPHONY_URL . '/publish/' . $as['handle'] . '/">' . $as['name'] . '</a>')))); |
1367
|
|
|
$element->appendChild($header); |
1368
|
|
|
|
1369
|
|
|
$ul = new XMLElement('ul', null, array( |
1370
|
|
|
'class' => 'association-links', |
1371
|
|
|
'data-section-id' => $as['child_section_id'], |
1372
|
|
|
'data-association-ids' => implode(', ', $entry_ids) |
1373
|
|
|
)); |
1374
|
|
|
|
1375
|
|
|
foreach ($entries['records'] as $e) { |
1376
|
|
|
// let the field create the mark up |
1377
|
|
|
$li = $field->prepareAssociationsDrawerXMLElement($e, $as); |
1378
|
|
|
// add it to the unordered list |
1379
|
|
|
$ul->appendChild($li); |
1380
|
|
|
} |
1381
|
|
|
|
1382
|
|
|
$element->appendChild($ul); |
1383
|
|
|
$content->appendChild($element); |
1384
|
|
|
} |
1385
|
|
|
} |
1386
|
|
|
} |
1387
|
|
|
} |
1388
|
|
|
|
1389
|
|
|
// Process Child Associations |
1390
|
|
|
if (!is_null($child_associations) && !empty($child_associations)) { |
1391
|
|
|
foreach ($child_associations as $as) { |
|
|
|
|
1392
|
|
|
// Get the related section |
1393
|
|
|
$child_section = SectionManager::fetch($as['child_section_id']); |
1394
|
|
|
|
1395
|
|
|
if (!($child_section instanceof Section)) { |
1396
|
|
|
continue; |
1397
|
|
|
} |
1398
|
|
|
|
1399
|
|
|
// Get the visible field instance (using the sorting field, this is more flexible than visibleColumns()) |
1400
|
|
|
// Get the link field instance |
1401
|
|
|
$visible_field = current($child_section->fetchVisibleColumns()); |
1402
|
|
|
$relation_field = FieldManager::fetch($as['child_section_field_id']); |
1403
|
|
|
|
1404
|
|
|
// Get entries, using $schema for performance reasons. |
1405
|
|
|
$entry_ids = $relation_field->findRelatedEntries($entry_id, $as['parent_section_field_id']); |
1406
|
|
|
$schema = $visible_field ? array($visible_field->get('element_name')) : array(); |
1407
|
|
|
$where = sprintf(' AND `e`.`id` IN (%s)', implode(', ', $entry_ids)); |
1408
|
|
|
|
1409
|
|
|
$entries = (!empty($entry_ids)) ? EntryManager::fetchByPage(1, $as['child_section_id'], |
1410
|
|
|
$show_entries, $where, null, false, false, true, $schema) : array(); |
1411
|
|
|
$has_entries = !empty($entries) && $entries['total-entries'] !== 0; |
1412
|
|
|
|
1413
|
|
|
// Build the HTML of the relationship |
1414
|
|
|
$element = new XMLElement('section', null, array('class' => 'association child')); |
1415
|
|
|
$header = new XMLElement('header'); |
1416
|
|
|
$filter = '?filter[' . $relation_field->get('element_name') . ']=' . $entry_id; |
1417
|
|
|
$prepopulate = '?prepopulate[' . $as['child_section_field_id'] . ']=' . $entry_id; |
1418
|
|
|
|
1419
|
|
|
// Create link with filter or prepopulate |
1420
|
|
|
$link = SYMPHONY_URL . '/publish/' . $as['handle'] . '/' . $filter; |
1421
|
|
|
$a = new XMLElement('a', $as['name'], array( |
1422
|
|
|
'class' => 'association-section', |
1423
|
|
|
'href' => $link |
1424
|
|
|
)); |
1425
|
|
|
|
1426
|
|
|
// Create new entries |
1427
|
|
|
$create = new XMLElement('a', __('Create New'), array( |
1428
|
|
|
'class' => 'button association-new', |
1429
|
|
|
'href' => SYMPHONY_URL . '/publish/' . $as['handle'] . '/new/' . $prepopulate |
1430
|
|
|
)); |
1431
|
|
|
|
1432
|
|
|
// Display existing entries |
1433
|
|
|
if ($has_entries) { |
1434
|
|
|
$header->appendChild(new XMLElement('p', __('Links in %s', array($a->generate())))); |
1435
|
|
|
|
1436
|
|
|
$ul = new XMLElement('ul', null, array( |
1437
|
|
|
'class' => 'association-links', |
1438
|
|
|
'data-section-id' => $as['child_section_id'], |
1439
|
|
|
'data-association-ids' => implode(', ', $entry_ids) |
1440
|
|
|
)); |
1441
|
|
|
|
1442
|
|
|
foreach ($entries['records'] as $key => $e) { |
1443
|
|
|
// let the first visible field create the mark up |
1444
|
|
|
if ($visible_field) { |
1445
|
|
|
$li = $visible_field->prepareAssociationsDrawerXMLElement($e, $as, $prepopulate); |
1446
|
|
|
} // or use the system:id if no visible field exists. |
1447
|
|
|
else { |
1448
|
|
|
$li = Field::createAssociationsDrawerXMLElement($e->get('id'), $e, $as, |
1449
|
|
|
$prepopulate); |
1450
|
|
|
} |
1451
|
|
|
|
1452
|
|
|
// add it to the unordered list |
1453
|
|
|
$ul->appendChild($li); |
1454
|
|
|
} |
1455
|
|
|
|
1456
|
|
|
$element->appendChild($ul); |
1457
|
|
|
|
1458
|
|
|
// If we are only showing 'some' of the entries, then show this on the UI |
1459
|
|
|
if ($entries['total-entries'] > $show_entries) { |
1460
|
|
|
$pagination = new XMLElement('li', null, array( |
1461
|
|
|
'class' => 'association-more', |
1462
|
|
|
'data-current-page' => '1', |
1463
|
|
|
'data-total-pages' => ceil($entries['total-entries'] / $show_entries), |
1464
|
|
|
'data-total-entries' => $entries['total-entries'] |
1465
|
|
|
)); |
1466
|
|
|
$counts = new XMLElement('a', __('Show more entries'), array( |
1467
|
|
|
'href' => $link |
1468
|
|
|
)); |
1469
|
|
|
|
1470
|
|
|
$pagination->appendChild($counts); |
1471
|
|
|
$ul->appendChild($pagination); |
1472
|
|
|
} |
1473
|
|
|
|
1474
|
|
|
// No entries |
1475
|
|
|
} else { |
1476
|
|
|
$element->setAttribute('class', 'association child empty'); |
1477
|
|
|
$header->appendChild(new XMLElement('p', __('No links in %s', array($a->generate())))); |
1478
|
|
|
} |
1479
|
|
|
|
1480
|
|
|
$header->appendChild($create); |
1481
|
|
|
$element->prependChild($header); |
1482
|
|
|
$content->appendChild($element); |
1483
|
|
|
} |
1484
|
|
|
} |
1485
|
|
|
} |
1486
|
|
|
|
1487
|
|
|
$drawer = Widget::Drawer('section-associations', __('Show Associations'), $content); |
1488
|
|
|
$this->insertDrawer($drawer, $drawer_position, 'prepend'); |
1489
|
|
|
} |
1490
|
|
|
|
1491
|
|
|
public function __actionNew() |
|
|
|
|
1492
|
|
|
{ |
1493
|
|
|
if (array_key_exists('save', $_POST['action']) || array_key_exists("done", $_POST['action'])) { |
1494
|
|
|
$section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle']); |
1495
|
|
|
|
1496
|
|
|
if (!$section = SectionManager::fetch($section_id)) { |
1497
|
|
|
Administration::instance()->throwCustomError( |
1498
|
|
|
__('The Section, %s, could not be found.', |
1499
|
|
|
array('<code>' . $this->_context['section_handle'] . '</code>')), |
1500
|
|
|
__('Unknown Section'), |
1501
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
1502
|
|
|
); |
1503
|
|
|
} |
1504
|
|
|
|
1505
|
|
|
$entry = EntryManager::create(); |
1506
|
|
|
$entry->set('author_id', Symphony::Author()->get('id')); |
1507
|
|
|
$entry->set('section_id', $section_id); |
1508
|
|
|
$entry->set('creation_date', DateTimeObj::get('c')); |
1509
|
|
|
$entry->set('modification_date', DateTimeObj::get('c')); |
1510
|
|
|
|
1511
|
|
|
$fields = $_POST['fields']; |
1512
|
|
|
|
1513
|
|
|
// Combine FILES and POST arrays, indexed by their custom field handles |
1514
|
|
|
if (isset($_FILES['fields'])) { |
1515
|
|
|
$filedata = General::processFilePostData($_FILES['fields']); |
1516
|
|
|
|
1517
|
|
|
foreach ($filedata as $handle => $data) { |
1518
|
|
|
if (!isset($fields[$handle])) { |
1519
|
|
|
$fields[$handle] = $data; |
1520
|
|
|
} elseif (isset($data['error']) && $data['error'] === UPLOAD_ERR_NO_FILE) { |
1521
|
|
|
$fields[$handle] = null; |
1522
|
|
|
} else { |
1523
|
|
|
foreach ($data as $ii => $d) { |
1524
|
|
|
if (isset($d['error']) && $d['error'] === UPLOAD_ERR_NO_FILE) { |
1525
|
|
|
$fields[$handle][$ii] = null; |
1526
|
|
|
} elseif (is_array($d) && !empty($d)) { |
1527
|
|
|
foreach ($d as $key => $val) { |
1528
|
|
|
$fields[$handle][$ii][$key] = $val; |
1529
|
|
|
} |
1530
|
|
|
} |
1531
|
|
|
} |
1532
|
|
|
} |
1533
|
|
|
} |
1534
|
|
|
} |
1535
|
|
|
|
1536
|
|
|
// Initial checks to see if the Entry is ok |
1537
|
|
|
if (Entry::__ENTRY_FIELD_ERROR__ === $entry->checkPostData($fields, $this->_errors)) { |
1538
|
|
|
$this->pageAlert(__('Some errors were encountered while attempting to save.'), Alert::ERROR); |
1539
|
|
|
|
1540
|
|
|
// Secondary checks, this will actually process the data and attempt to save |
1541
|
|
View Code Duplication |
} elseif (Entry::__ENTRY_OK__ !== $entry->setDataFromPost($fields, $errors)) { |
1542
|
|
|
foreach ($errors as $field_id => $message) { |
|
|
|
|
1543
|
|
|
$this->pageAlert($message, Alert::ERROR); |
1544
|
|
|
} |
1545
|
|
|
|
1546
|
|
|
// Everything is awesome. Dance. |
1547
|
|
|
} else { |
1548
|
|
|
/** |
1549
|
|
|
* Just prior to creation of an Entry |
1550
|
|
|
* |
1551
|
|
|
* @delegate EntryPreCreate |
1552
|
|
|
* @param string $context |
1553
|
|
|
* '/publish/new/' |
1554
|
|
|
* @param Section $section |
1555
|
|
|
* @param Entry $entry |
1556
|
|
|
* @param array $fields |
1557
|
|
|
*/ |
1558
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreCreate', '/publish/new/', |
1559
|
|
|
array('section' => $section, 'entry' => &$entry, 'fields' => &$fields)); |
1560
|
|
|
|
1561
|
|
|
// Check to see if the dancing was premature |
1562
|
|
|
if (!$entry->commit()) { |
1563
|
|
|
$this->pageAlert(null, Alert::ERROR); |
1564
|
|
|
} else { |
1565
|
|
|
/** |
1566
|
|
|
* Creation of an Entry. New Entry object is provided. |
1567
|
|
|
* |
1568
|
|
|
* @delegate EntryPostCreate |
1569
|
|
|
* @param string $context |
1570
|
|
|
* '/publish/new/' |
1571
|
|
|
* @param Section $section |
1572
|
|
|
* @param Entry $entry |
1573
|
|
|
* @param array $fields |
1574
|
|
|
*/ |
1575
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPostCreate', '/publish/new/', |
1576
|
|
|
array('section' => $section, 'entry' => $entry, 'fields' => $fields)); |
1577
|
|
|
|
1578
|
|
|
$prepopulate_querystring = $this->getPrepopulateString(); |
1579
|
|
|
redirect(sprintf( |
1580
|
|
|
'%s/publish/%s/edit/%d/created/%s', |
1581
|
|
|
SYMPHONY_URL, |
1582
|
|
|
$this->_context['section_handle'], |
1583
|
|
|
$entry->get('id'), |
1584
|
|
|
(!empty($prepopulate_querystring) ? $prepopulate_querystring : null) |
1585
|
|
|
)); |
1586
|
|
|
} |
1587
|
|
|
} |
1588
|
|
|
} |
1589
|
|
|
} |
1590
|
|
|
|
1591
|
|
|
public function __viewEdit() |
|
|
|
|
1592
|
|
|
{ |
1593
|
|
View Code Duplication |
if (!$section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle'])) { |
1594
|
|
|
Administration::instance()->throwCustomError( |
1595
|
|
|
__('The Section, %s, could not be found.', |
1596
|
|
|
array('<code>' . $this->_context['section_handle'] . '</code>')), |
1597
|
|
|
__('Unknown Section'), |
1598
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
1599
|
|
|
); |
1600
|
|
|
} |
1601
|
|
|
|
1602
|
|
|
$section = SectionManager::fetch($section_id); |
1603
|
|
|
$entry_id = intval($this->_context['entry_id']); |
1604
|
|
|
$base = '/publish/' . $this->_context['section_handle'] . '/'; |
1605
|
|
|
$new_link = $base . 'new/'; |
1606
|
|
|
$filter_link = $base; |
1607
|
|
|
|
1608
|
|
|
EntryManager::setFetchSorting('id', 'DESC'); |
1609
|
|
|
|
1610
|
|
View Code Duplication |
if (!$existingEntry = EntryManager::fetch($entry_id)) { |
1611
|
|
|
Administration::instance()->throwCustomError( |
1612
|
|
|
__('Unknown Entry'), |
1613
|
|
|
__('The Entry, %s, could not be found.', array($entry_id)), |
1614
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
1615
|
|
|
); |
1616
|
|
|
} |
1617
|
|
|
$existingEntry = $existingEntry[0]; |
1618
|
|
|
|
1619
|
|
|
// If there is post data floating around, due to errors, create an entry object |
1620
|
|
|
if (isset($_POST['fields'])) { |
1621
|
|
|
$fields = $_POST['fields']; |
1622
|
|
|
|
1623
|
|
|
$entry = EntryManager::create(); |
1624
|
|
|
$entry->set('id', $entry_id); |
1625
|
|
|
$entry->set('author_id', $existingEntry->get('author_id')); |
1626
|
|
|
$entry->set('section_id', $existingEntry->get('section_id')); |
1627
|
|
|
$entry->set('creation_date', $existingEntry->get('creation_date')); |
1628
|
|
|
$entry->set('modification_date', $existingEntry->get('modification_date')); |
1629
|
|
|
$entry->setDataFromPost($fields, $errors, true); |
1630
|
|
|
|
1631
|
|
|
// Editing an entry, so need to create some various objects |
1632
|
|
|
} else { |
1633
|
|
|
$entry = $existingEntry; |
1634
|
|
|
$fields = array(); |
1635
|
|
|
|
1636
|
|
|
if (!$section) { |
1637
|
|
|
$section = SectionManager::fetch($entry->get('section_id')); |
1638
|
|
|
} |
1639
|
|
|
} |
1640
|
|
|
|
1641
|
|
|
/** |
1642
|
|
|
* Just prior to rendering of an Entry edit form. |
1643
|
|
|
* |
1644
|
|
|
* @delegate EntryPreRender |
1645
|
|
|
* @param string $context |
1646
|
|
|
* '/publish/edit/' |
1647
|
|
|
* @param Section $section |
1648
|
|
|
* @param Entry $entry |
1649
|
|
|
* @param array $fields |
1650
|
|
|
*/ |
1651
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreRender', '/publish/edit/', array( |
1652
|
|
|
'section' => $section, |
1653
|
|
|
'entry' => &$entry, |
1654
|
|
|
'fields' => $fields |
1655
|
|
|
)); |
1656
|
|
|
|
1657
|
|
|
// Iterate over the `prepopulate` parameters to build a URL |
1658
|
|
|
// to remember this state for Create New, View all Entries and |
1659
|
|
|
// Breadcrumb links. If `prepopulate` doesn't exist, this will |
1660
|
|
|
// just use the standard pages (ie. no filtering) |
1661
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1662
|
|
|
$new_link .= $this->getPrepopulateString(); |
1663
|
|
|
$filter_link .= $this->getFilterString(); |
1664
|
|
|
} |
1665
|
|
|
|
1666
|
|
|
if (isset($this->_context['flag'])) { |
1667
|
|
|
// These flags are only relevant if there are no errors |
1668
|
|
|
if (empty($this->_errors)) { |
1669
|
|
|
$time = Widget::Time(); |
1670
|
|
|
|
1671
|
|
|
switch ($this->_context['flag']) { |
1672
|
|
|
case 'saved': |
1673
|
|
|
$message = __('Entry updated at %s.', array($time->generate())); |
1674
|
|
|
break; |
1675
|
|
|
case 'created': |
1676
|
|
|
$message = __('Entry created at %s.', array($time->generate())); |
1677
|
|
|
} |
1678
|
|
|
|
1679
|
|
|
$this->pageAlert( |
1680
|
|
|
$message |
|
|
|
|
1681
|
|
|
. ' <a href="' . SYMPHONY_URL . $new_link . '" accesskey="c">' |
1682
|
|
|
. __('Create another?') |
1683
|
|
|
. '</a> <a href="' . SYMPHONY_URL . $filter_link . '" accesskey="a">' |
1684
|
|
|
. __('View all Entries') |
1685
|
|
|
. '</a>', |
1686
|
|
|
Alert::SUCCESS |
1687
|
|
|
); |
1688
|
|
|
} |
1689
|
|
|
} |
1690
|
|
|
|
1691
|
|
|
// Determine the page title |
1692
|
|
|
$field_id = Symphony::Database()->fetchVar('id', 0, " |
1693
|
|
|
SELECT `id` |
1694
|
|
|
FROM `tbl_fields` |
1695
|
|
|
WHERE `parent_section` = ? |
1696
|
|
|
ORDER BY `sortorder` LIMIT 1", |
1697
|
|
|
array($section->get('id')) |
1698
|
|
|
); |
1699
|
|
|
if (!is_null($field_id)) { |
1700
|
|
|
$field = FieldManager::fetch($field_id); |
1701
|
|
|
} |
1702
|
|
|
|
1703
|
|
|
if ($field) { |
1704
|
|
|
$title = $field->prepareReadableValue($existingEntry->getData($field->get('id')), $entry_id, true); |
|
|
|
|
1705
|
|
|
} else { |
1706
|
|
|
$title = ''; |
1707
|
|
|
} |
1708
|
|
|
|
1709
|
|
|
if (trim($title) === '') { |
1710
|
|
|
$title = __('Untitled'); |
1711
|
|
|
} |
1712
|
|
|
|
1713
|
|
|
// Check if there is a field to prepopulate |
1714
|
|
|
if (isset($_REQUEST['prepopulate'])) { |
1715
|
|
|
foreach ($_REQUEST['prepopulate'] as $field_id => $value) { |
1716
|
|
|
$this->Form->prependChild(Widget::Input( |
1717
|
|
|
"prepopulate[{$field_id}]", |
1718
|
|
|
rawurlencode($value), |
1719
|
|
|
'hidden' |
1720
|
|
|
)); |
1721
|
|
|
} |
1722
|
|
|
} |
1723
|
|
|
|
1724
|
|
|
$this->setPageType('form'); |
1725
|
|
|
$this->Form->setAttribute('enctype', 'multipart/form-data'); |
1726
|
|
|
$this->setTitle(__('%1$s – %2$s – %3$s', array($title, $section->get('name'), __('Symphony')))); |
1727
|
|
|
|
1728
|
|
|
$sidebar_fields = $section->fetchFields(null, 'sidebar'); |
1729
|
|
|
$main_fields = $section->fetchFields(null, 'main'); |
1730
|
|
|
|
1731
|
|
View Code Duplication |
if (!empty($sidebar_fields) && !empty($main_fields)) { |
1732
|
|
|
$this->Form->setAttribute('class', 'two columns'); |
1733
|
|
|
} else { |
1734
|
|
|
$this->Form->setAttribute('class', 'columns'); |
1735
|
|
|
} |
1736
|
|
|
|
1737
|
|
|
// Only show the Edit Section button if the Author is a developer. #938 ^BA |
1738
|
|
|
if (Symphony::Author()->isDeveloper()) { |
1739
|
|
|
$this->appendSubheading($title, |
1740
|
|
|
Widget::Anchor(__('Edit Section'), SYMPHONY_URL . '/blueprints/sections/edit/' . $section_id . '/', |
1741
|
|
|
__('Edit Section Configuration'), 'button')); |
1742
|
|
|
} else { |
1743
|
|
|
$this->appendSubheading($title); |
1744
|
|
|
} |
1745
|
|
|
|
1746
|
|
|
$this->insertBreadcrumbs(array( |
1747
|
|
|
Widget::Anchor($section->get('name'), SYMPHONY_URL . (isset($filter_link) ? $filter_link : $base)), |
1748
|
|
|
)); |
1749
|
|
|
|
1750
|
|
|
$this->Form->appendChild(Widget::Input('MAX_FILE_SIZE', |
1751
|
|
|
Symphony::Configuration()->get('max_upload_size', 'admin'), 'hidden')); |
1752
|
|
|
|
1753
|
|
|
$primary = new XMLElement('fieldset'); |
1754
|
|
|
$primary->setAttribute('class', 'primary column'); |
1755
|
|
|
|
1756
|
|
|
if ((!is_array($main_fields) || empty($main_fields)) && (!is_array($sidebar_fields) || empty($sidebar_fields))) { |
1757
|
|
|
$message = __('Fields must be added to this section before an entry can be created.'); |
1758
|
|
|
|
1759
|
|
View Code Duplication |
if (Symphony::Author()->isDeveloper()) { |
1760
|
|
|
$message .= ' <a href="' . SYMPHONY_URL . '/blueprints/sections/edit/' . $section->get('id') . '/" accesskey="c">' |
1761
|
|
|
. __('Add fields') |
1762
|
|
|
. '</a>'; |
1763
|
|
|
} |
1764
|
|
|
|
1765
|
|
|
$this->pageAlert($message, Alert::ERROR); |
1766
|
|
|
} else { |
1767
|
|
View Code Duplication |
if (is_array($main_fields) && !empty($main_fields)) { |
1768
|
|
|
foreach ($main_fields as $field) { |
1769
|
|
|
$primary->appendChild($this->__wrapFieldWithDiv($field, $entry)); |
1770
|
|
|
} |
1771
|
|
|
|
1772
|
|
|
$this->Form->appendChild($primary); |
1773
|
|
|
} |
1774
|
|
|
|
1775
|
|
View Code Duplication |
if (is_array($sidebar_fields) && !empty($sidebar_fields)) { |
1776
|
|
|
$sidebar = new XMLElement('fieldset'); |
1777
|
|
|
$sidebar->setAttribute('class', 'secondary column'); |
1778
|
|
|
|
1779
|
|
|
foreach ($sidebar_fields as $field) { |
1780
|
|
|
$sidebar->appendChild($this->__wrapFieldWithDiv($field, $entry)); |
1781
|
|
|
} |
1782
|
|
|
|
1783
|
|
|
$this->Form->appendChild($sidebar); |
1784
|
|
|
} |
1785
|
|
|
|
1786
|
|
|
$div = new XMLElement('div'); |
1787
|
|
|
$div->setAttribute('class', 'actions'); |
1788
|
|
|
$div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', |
1789
|
|
|
array('accesskey' => 's'))); |
1790
|
|
|
|
1791
|
|
|
$button = new XMLElement('button', __('Delete')); |
1792
|
|
|
$button->setAttributeArray(array( |
1793
|
|
|
'name' => 'action[delete]', |
1794
|
|
|
'class' => 'button confirm delete', |
1795
|
|
|
'title' => __('Delete this entry'), |
1796
|
|
|
'type' => 'submit', |
1797
|
|
|
'accesskey' => 'd', |
1798
|
|
|
'data-message' => __('Are you sure you want to delete this entry?') |
1799
|
|
|
)); |
1800
|
|
|
$div->appendChild($button); |
1801
|
|
|
|
1802
|
|
|
$this->Form->appendChild($div); |
1803
|
|
|
|
1804
|
|
|
// Create a Drawer for Associated Sections |
1805
|
|
|
$this->prepareAssociationsDrawer($section); |
|
|
|
|
1806
|
|
|
} |
1807
|
|
|
} |
1808
|
|
|
|
1809
|
|
|
public function __actionEdit() |
|
|
|
|
1810
|
|
|
{ |
1811
|
|
|
$entry_id = intval($this->_context['entry_id']); |
1812
|
|
|
|
1813
|
|
|
if (@array_key_exists('save', $_POST['action']) || @array_key_exists("done", $_POST['action'])) { |
1814
|
|
View Code Duplication |
if (!$ret = EntryManager::fetch($entry_id)) { |
1815
|
|
|
Administration::instance()->throwCustomError( |
1816
|
|
|
__('The Entry, %s, could not be found.', array($entry_id)), |
1817
|
|
|
__('Unknown Entry'), |
1818
|
|
|
Page::HTTP_STATUS_NOT_FOUND |
1819
|
|
|
); |
1820
|
|
|
} |
1821
|
|
|
|
1822
|
|
|
$entry = $ret[0]; |
1823
|
|
|
|
1824
|
|
|
$section = SectionManager::fetch($entry->get('section_id')); |
1825
|
|
|
|
1826
|
|
|
$post = General::getPostData(); |
1827
|
|
|
$fields = $post['fields']; |
1828
|
|
|
|
1829
|
|
|
// Initial checks to see if the Entry is ok |
1830
|
|
|
if (Entry::__ENTRY_FIELD_ERROR__ === $entry->checkPostData($fields, $this->_errors)) { |
1831
|
|
|
$this->pageAlert(__('Some errors were encountered while attempting to save.'), Alert::ERROR); |
1832
|
|
|
|
1833
|
|
|
// Secondary checks, this will actually process the data and attempt to save |
1834
|
|
View Code Duplication |
} elseif (Entry::__ENTRY_OK__ !== $entry->setDataFromPost($fields, $errors)) { |
|
|
|
|
1835
|
|
|
foreach ($errors as $field_id => $message) { |
1836
|
|
|
$this->pageAlert($message, Alert::ERROR); |
1837
|
|
|
} |
1838
|
|
|
|
1839
|
|
|
// Everything is awesome. Dance. |
1840
|
|
|
} else { |
1841
|
|
|
/** |
1842
|
|
|
* Just prior to editing of an Entry. |
1843
|
|
|
* |
1844
|
|
|
* @delegate EntryPreEdit |
1845
|
|
|
* @param string $context |
1846
|
|
|
* '/publish/edit/' |
1847
|
|
|
* @param Section $section |
1848
|
|
|
* @param Entry $entry |
1849
|
|
|
* @param array $fields |
1850
|
|
|
*/ |
1851
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreEdit', '/publish/edit/', |
1852
|
|
|
array('section' => $section, 'entry' => &$entry, 'fields' => $fields)); |
1853
|
|
|
|
1854
|
|
|
// Check to see if the dancing was premature |
1855
|
|
|
if (!$entry->commit()) { |
1856
|
|
|
$this->pageAlert(null, Alert::ERROR); |
1857
|
|
|
} else { |
1858
|
|
|
/** |
1859
|
|
|
* Just after the editing of an Entry |
1860
|
|
|
* |
1861
|
|
|
* @delegate EntryPostEdit |
1862
|
|
|
* @param string $context |
1863
|
|
|
* '/publish/edit/' |
1864
|
|
|
* @param Section $section |
1865
|
|
|
* @param Entry $entry |
1866
|
|
|
* @param array $fields |
1867
|
|
|
*/ |
1868
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPostEdit', '/publish/edit/', |
1869
|
|
|
array('section' => $section, 'entry' => $entry, 'fields' => $fields)); |
1870
|
|
|
|
1871
|
|
|
redirect(sprintf( |
1872
|
|
|
'%s/publish/%s/edit/%d/saved/%s', |
1873
|
|
|
SYMPHONY_URL, |
1874
|
|
|
$this->_context['section_handle'], |
1875
|
|
|
$entry->get('id'), |
1876
|
|
|
$this->getPrepopulateString() |
1877
|
|
|
)); |
1878
|
|
|
} |
1879
|
|
|
} |
1880
|
|
|
} elseif (@array_key_exists('delete', $_POST['action']) && is_numeric($entry_id)) { |
1881
|
|
|
/** |
1882
|
|
|
* Prior to deletion of entries. An array of Entry ID's is provided which |
1883
|
|
|
* can be manipulated. This delegate was renamed from `Delete` to `EntryPreDelete` |
1884
|
|
|
* in Symphony 2.3. |
1885
|
|
|
* |
1886
|
|
|
* @delegate EntryPreDelete |
1887
|
|
|
* @param string $context |
1888
|
|
|
* '/publish/' |
1889
|
|
|
* @param array $entry_id |
1890
|
|
|
* An array of Entry ID's passed by reference |
1891
|
|
|
*/ |
1892
|
|
|
$checked = array($entry_id); |
1893
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPreDelete', '/publish/', |
1894
|
|
|
array('entry_id' => &$checked)); |
1895
|
|
|
|
1896
|
|
|
EntryManager::delete($checked); |
1897
|
|
|
|
1898
|
|
|
/** |
1899
|
|
|
* After the deletion of entries, this delegate provides an array of Entry ID's |
1900
|
|
|
* that were deleted. |
1901
|
|
|
* |
1902
|
|
|
* @since Symphony 2.3 |
1903
|
|
|
* @delegate EntryPostDelete |
1904
|
|
|
* @param string $context |
1905
|
|
|
* '/publish/' |
1906
|
|
|
* @param array $entry_id |
1907
|
|
|
* An array of Entry ID's that were deleted. |
1908
|
|
|
*/ |
1909
|
|
|
Symphony::ExtensionManager()->notifyMembers('EntryPostDelete', '/publish/', |
1910
|
|
|
array('entry_id' => $checked)); |
1911
|
|
|
|
1912
|
|
|
redirect(SYMPHONY_URL . '/publish/' . $this->_context['section_handle'] . '/'); |
1913
|
|
|
} |
1914
|
|
|
} |
1915
|
|
|
} |
1916
|
|
|
|
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: