Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like FieldEntry_Relationship often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FieldEntry_Relationship, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class FieldEntry_Relationship extends FieldRelationship |
||
21 | { |
||
22 | /** |
||
23 | * |
||
24 | * Name of the field table |
||
25 | * @var string |
||
26 | */ |
||
27 | const FIELD_TBL_NAME = 'tbl_fields_entry_relationship'; |
||
28 | |||
29 | /** |
||
30 | * |
||
31 | * Current recursive level of output |
||
32 | * @var int |
||
33 | */ |
||
34 | protected $recursiveLevel = 1; |
||
35 | public function getRecursiveLevel() |
||
43 | |||
44 | /** |
||
45 | * |
||
46 | * Parent's maximum recursive level of output |
||
47 | * @var int |
||
48 | */ |
||
49 | protected $recursiveDeepness = null; |
||
50 | public function getRecursiveDeepness() |
||
58 | |||
59 | // cache managers |
||
60 | private $sectionManager; |
||
61 | private $entryManager; |
||
62 | private $sectionInfos; |
||
63 | |||
64 | public $expandIncludableElements = true; |
||
65 | |||
66 | /** |
||
67 | * |
||
68 | * Constructor for the Entry_Relationship Field object |
||
69 | */ |
||
70 | public function __construct() |
||
71 | { |
||
72 | // call the parent constructor |
||
73 | parent::__construct(); |
||
74 | // EQFA |
||
75 | $this->entryQueryFieldAdapter = new EntryQueryEntryrelationshipAdapter($this); |
||
76 | // set the name of the field |
||
77 | $this->_name = __('Entry Relationship'); |
||
78 | // permits to make it required |
||
79 | $this->_required = true; |
||
80 | // permits the make it show in the table columns |
||
81 | $this->_showcolumn = true; |
||
82 | // permits association |
||
83 | $this->_showassociation = true; |
||
84 | // current recursive level |
||
85 | $this->recursiveLevel = 1; |
||
86 | // parent's maximum recursive level of output |
||
87 | $this->recursiveDeepness = null; |
||
88 | // set as orderable |
||
89 | $this->orderable = true; |
||
90 | // set as not required by default |
||
91 | $this->set('required', 'no'); |
||
92 | // show association by default |
||
93 | $this->set('show_association', 'yes'); |
||
94 | // no sections |
||
95 | $this->set('sections', null); |
||
96 | // no max deepness |
||
97 | $this->set('deepness', null); |
||
98 | // no included elements |
||
99 | $this->set('elements', null); |
||
100 | // no modes |
||
101 | $this->set('mode', null); |
||
102 | $this->set('mode_table', null); |
||
103 | $this->set('mode_header', null); |
||
104 | $this->set('mode_footer', null); |
||
105 | // no limit |
||
106 | $this->set('min_entries', null); |
||
107 | $this->set('max_entries', null); |
||
108 | // all permissions |
||
109 | $this->set('allow_new', 'yes'); |
||
110 | $this->set('allow_edit', 'yes'); |
||
111 | $this->set('allow_link', 'yes'); |
||
112 | $this->set('allow_delete', 'no'); |
||
113 | // display options |
||
114 | $this->set('allow_collapse', 'yes'); |
||
115 | $this->set('allow_search', 'no'); |
||
116 | $this->set('show_header', 'yes'); |
||
117 | // cache managers |
||
118 | $this->sectionManager = new SectionManager; |
||
119 | $this->entryManager = new EntryManager; |
||
120 | $this->fieldManager = new FieldManager; |
||
121 | $this->sectionInfos = new SectionsInfos; |
||
122 | } |
||
123 | |||
124 | public function isSortable() |
||
125 | { |
||
126 | return false; |
||
127 | } |
||
128 | |||
129 | public function canFilter() |
||
130 | { |
||
131 | return true; |
||
132 | } |
||
133 | |||
134 | public function canPublishFilter() |
||
135 | { |
||
136 | return true; |
||
137 | } |
||
138 | |||
139 | public function canImport() |
||
140 | { |
||
141 | return false; |
||
142 | } |
||
143 | |||
144 | public function canPrePopulate() |
||
145 | { |
||
146 | return true; |
||
147 | } |
||
148 | |||
149 | public function mustBeUnique() |
||
150 | { |
||
151 | return false; |
||
152 | } |
||
153 | |||
154 | public function allowDatasourceOutputGrouping() |
||
155 | { |
||
156 | return false; |
||
157 | } |
||
158 | |||
159 | public function requiresSQLGrouping() |
||
160 | { |
||
161 | return false; |
||
162 | } |
||
163 | |||
164 | public function allowDatasourceParamOutput() |
||
165 | { |
||
166 | return true; |
||
167 | } |
||
168 | |||
169 | /* ********** INPUT AND FIELD *********** */ |
||
170 | |||
171 | |||
172 | /** |
||
173 | * |
||
174 | * Validates input |
||
175 | * Called before <code>processRawFieldData</code> |
||
176 | * @param $data |
||
177 | * @param $message |
||
178 | * @param $entry_id |
||
179 | */ |
||
180 | public function checkPostFieldData($data, &$message, $entry_id = null) |
||
181 | { |
||
182 | $message = null; |
||
183 | $required = $this->isRequired(); |
||
184 | |||
185 | if ($required && (!is_array($data) || count($data) == 0 || strlen($data['entries']) < 1)) { |
||
186 | $message = __("'%s' is a required field.", array($this->get('label'))); |
||
187 | return self::__MISSING_FIELDS__; |
||
188 | } |
||
189 | |||
190 | $entries = $data['entries']; |
||
191 | |||
192 | if (!is_array($entries)) { |
||
193 | $entries = static::getEntries($data); |
||
194 | } |
||
195 | |||
196 | // enforce limits only if required or it contains data |
||
197 | if ($required || count($entries) > 0) { |
||
198 | if ($this->getInt('min_entries') > 0 && $this->getInt('min_entries') > count($entries)) { |
||
199 | $message = __("'%s' requires a minimum of %s entries.", array($this->get('label'), $this->getInt('min_entries'))); |
||
200 | return self::__INVALID_FIELDS__; |
||
201 | } else if ($this->getInt('max_entries') > 0 && $this->getInt('max_entries') < count($entries)) { |
||
202 | $message = __("'%s' can not contains more than %s entries.", array($this->get('label'), $this->getInt('max_entries'))); |
||
203 | return self::__INVALID_FIELDS__; |
||
204 | } |
||
205 | } |
||
206 | |||
207 | return self::__OK__; |
||
208 | } |
||
209 | |||
210 | |||
211 | /** |
||
212 | * |
||
213 | * Process data before saving into database. |
||
214 | * |
||
215 | * @param array $data |
||
216 | * @param int $status |
||
217 | * @param boolean $simulate |
||
218 | * @param int $entry_id |
||
219 | * |
||
220 | * @return Array - data to be inserted into DB |
||
221 | */ |
||
222 | public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null) |
||
223 | { |
||
224 | $status = self::__OK__; |
||
225 | $entries = null; |
||
226 | |||
227 | if (!is_array($data) && !is_string($data)) { |
||
228 | return null; |
||
229 | } |
||
230 | |||
231 | if (isset($data['entries'])) { |
||
232 | $entries = $data['entries']; |
||
233 | } |
||
234 | else if (is_string($data)) { |
||
235 | $entries = $data; |
||
236 | } |
||
237 | |||
238 | $row = array( |
||
239 | 'entries' => empty($entries) ? null : $entries |
||
240 | ); |
||
241 | |||
242 | // return row |
||
243 | return $row; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * This function permits parsing different field settings values |
||
248 | * |
||
249 | * @param array $settings |
||
250 | * the data array to initialize if necessary. |
||
251 | */ |
||
252 | public function setFromPOST(Array $settings = array()) |
||
253 | { |
||
254 | // call the default behavior |
||
255 | parent::setFromPOST($settings); |
||
256 | |||
257 | // declare a new setting array |
||
258 | $new_settings = array(); |
||
259 | |||
260 | // set new settings |
||
261 | $new_settings['sections'] = is_array($settings['sections']) ? |
||
262 | implode(self::SEPARATOR, $settings['sections']) : |
||
263 | (is_string($settings['sections']) ? $settings['sections'] : null); |
||
264 | |||
265 | $new_settings['show_association'] = $settings['show_association'] == 'yes' ? 'yes' : 'no'; |
||
266 | $new_settings['deepness'] = General::intval($settings['deepness']); |
||
267 | $new_settings['deepness'] = $new_settings['deepness'] < 1 ? null : $new_settings['deepness']; |
||
268 | $new_settings['elements'] = empty($settings['elements']) ? null : $settings['elements']; |
||
269 | $new_settings['mode'] = empty($settings['mode']) ? null : $settings['mode']; |
||
270 | $new_settings['mode_table'] = empty($settings['mode_table']) ? null : $settings['mode_table']; |
||
271 | $new_settings['mode_header'] = empty($settings['mode_header']) ? null : $settings['mode_header']; |
||
272 | $new_settings['mode_footer'] = empty($settings['mode_footer']) ? null : $settings['mode_footer']; |
||
273 | $new_settings['allow_new'] = $settings['allow_new'] == 'yes' ? 'yes' : 'no'; |
||
274 | $new_settings['allow_edit'] = $settings['allow_edit'] == 'yes' ? 'yes' : 'no'; |
||
275 | $new_settings['allow_link'] = $settings['allow_link'] == 'yes' ? 'yes' : 'no'; |
||
276 | $new_settings['allow_delete'] = $settings['allow_delete'] == 'yes' ? 'yes' : 'no'; |
||
277 | $new_settings['allow_collapse'] = $settings['allow_collapse'] == 'yes' ? 'yes' : 'no'; |
||
278 | $new_settings['allow_search'] = $settings['allow_search'] == 'yes' ? 'yes' : 'no'; |
||
279 | $new_settings['show_header'] = $settings['show_header'] == 'yes' ? 'yes' : 'no'; |
||
280 | |||
281 | // save it into the array |
||
282 | $this->setArray($new_settings); |
||
283 | } |
||
284 | |||
285 | |||
286 | /** |
||
287 | * |
||
288 | * Validates the field settings before saving it into the field's table |
||
289 | */ |
||
290 | public function checkFields(Array &$errors, $checkForDuplicates = true) |
||
291 | { |
||
292 | $parent = parent::checkFields($errors, $checkForDuplicates); |
||
293 | if ($parent != self::__OK__) { |
||
294 | return $parent; |
||
295 | } |
||
296 | |||
297 | $sections = $this->get('sections'); |
||
298 | |||
299 | if (empty($sections)) { |
||
300 | $errors['sections'] = __('At least one section must be chosen'); |
||
301 | } |
||
302 | |||
303 | return (!empty($errors) ? self::__ERROR__ : self::__OK__); |
||
304 | } |
||
305 | |||
306 | /** |
||
307 | * |
||
308 | * Save field settings into the field's table |
||
309 | */ |
||
310 | public function commit() |
||
311 | { |
||
312 | // if the default implementation works... |
||
313 | if(!parent::commit()) return false; |
||
314 | |||
315 | $id = $this->get('id'); |
||
316 | |||
317 | // exit if there is no id |
||
318 | if($id == false) return false; |
||
319 | |||
320 | // we are the child, with multiple parents |
||
321 | $child_field_id = $id; |
||
322 | |||
323 | // delete associations, only where we are the child |
||
324 | self::removeSectionAssociation($child_field_id); |
||
325 | |||
326 | $sections = $this->getSelectedSectionsArray(); |
||
327 | |||
328 | foreach ($sections as $key => $sectionId) { |
||
329 | if (empty($sectionId)) { |
||
330 | continue; |
||
331 | } |
||
332 | $parent_section_id = General::intval($sectionId); |
||
333 | if ($parent_section_id < 1) { |
||
334 | // section not found, bail out |
||
335 | continue; |
||
336 | } |
||
337 | $parent_section = $this->sectionManager |
||
338 | ->select() |
||
339 | ->section($parent_section_id) |
||
340 | ->execute() |
||
341 | ->next(); |
||
342 | if (!$parent_section) { |
||
343 | // section not found, bail out |
||
344 | continue; |
||
345 | } |
||
346 | $fields = $parent_section->fetchVisibleColumns(); |
||
347 | if (empty($fields)) { |
||
348 | // no visible field, revert to all |
||
349 | $fields = $parent_section->fetchFields(); |
||
350 | } |
||
351 | if (empty($fields)) { |
||
352 | // no fields found, bail out |
||
353 | continue; |
||
354 | } |
||
355 | $parent_field_id = current($fields)->get('id'); |
||
356 | // create association |
||
357 | SectionManager::createSectionAssociation( |
||
358 | $parent_section_id, |
||
359 | $child_field_id, |
||
360 | $parent_field_id, |
||
361 | $this->get('show_association') == 'yes' |
||
362 | ); |
||
363 | } |
||
364 | |||
365 | // declare an array contains the field's settings |
||
366 | $settings = array( |
||
367 | 'sections' => $this->get('sections'), |
||
368 | 'show_association' => $this->get('show_association'), |
||
369 | 'deepness' => $this->get('deepness'), |
||
370 | 'elements' => $this->get('elements'), |
||
371 | 'mode' => $this->get('mode'), |
||
372 | 'mode_table' => $this->get('mode_table'), |
||
373 | 'mode_header' => $this->get('mode_header'), |
||
374 | 'mode_footer' => $this->get('mode_footer'), |
||
375 | 'min_entries' => $this->get('min_entries'), |
||
376 | 'max_entries' => $this->get('max_entries'), |
||
377 | 'allow_new' => $this->get('allow_new'), |
||
378 | 'allow_edit' => $this->get('allow_edit'), |
||
379 | 'allow_link' => $this->get('allow_link'), |
||
380 | 'allow_delete' => $this->get('allow_delete'), |
||
381 | 'allow_collapse' => $this->get('allow_collapse'), |
||
382 | 'allow_search' => $this->get('allow_search'), |
||
383 | 'show_header' => $this->get('show_header'), |
||
384 | ); |
||
385 | |||
386 | return FieldManager::saveSettings($id, $settings); |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * |
||
391 | * This function allows Fields to cleanup any additional things before it is removed |
||
392 | * from the section. |
||
393 | * @return boolean |
||
394 | */ |
||
395 | public function tearDown() |
||
396 | { |
||
397 | self::removeSectionAssociation($this->get('id')); |
||
398 | return parent::tearDown(); |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * Generates the where filter for searching by entry id |
||
403 | * |
||
404 | * @param string $value |
||
405 | * @param @optional string $col |
||
406 | * @param @optional boolean $andOperation |
||
407 | */ |
||
408 | public function generateWhereFilter($value, $col = 'd', $andOperation = true) |
||
409 | { |
||
410 | $junction = $andOperation ? 'and' : 'or'; |
||
411 | |||
412 | if (!$value) { |
||
413 | return [ |
||
414 | $junction => [ |
||
415 | [$col . '.entries' => 'null'], |
||
416 | ], |
||
417 | ]; |
||
418 | } |
||
419 | |||
420 | return [ |
||
421 | $junction => [ |
||
422 | 'or' => [ |
||
423 | [$col . '.entries' => $value], |
||
424 | [$col . '.entries' => ['like' => $value . ',%']], |
||
425 | [$col . '.entries' => ['like' => '%,' . $value]], |
||
426 | [$col . '.entries' => ['like' => '%,' . $value . ',%']], |
||
427 | ], |
||
428 | ] |
||
429 | ]; |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Fetch the number of associated entries for a particular entry id |
||
434 | * |
||
435 | * @param string $value |
||
436 | */ |
||
437 | public function fetchAssociatedEntryCount($value) |
||
438 | { |
||
439 | if (!$value) { |
||
440 | return 0; |
||
441 | } |
||
442 | |||
443 | $where = $this->generateWhereFilter($value); |
||
444 | |||
445 | $entries = Symphony::Database() |
||
446 | ->select(['*']) |
||
447 | ->from('tbl_entries', 'e') |
||
448 | ->innerJoin('tbl_entries_data_' . $this->get('id'), 'd') |
||
449 | ->on(['e.id' => 'd.entry_id']) |
||
450 | ->where(['e.section_id' => $this->get('parent_section')]) |
||
451 | ->where($where) |
||
452 | ->execute() |
||
453 | ->rows(); |
||
454 | |||
455 | return count($entries); |
||
456 | } |
||
457 | |||
458 | public function fetchAssociatedEntrySearchValue($data, $field_id = null, $parent_entry_id = null) |
||
459 | { |
||
460 | return $parent_entry_id; |
||
461 | } |
||
462 | |||
463 | public function findRelatedEntries($entry_id, $parent_field_id) |
||
464 | { |
||
465 | $entries = $this->entryManager |
||
466 | ->select() |
||
467 | ->section($this->get('parent_section')) |
||
468 | ->filter($this->get('id'), [(string)$entry_id]) |
||
469 | ->schema(['id']) |
||
470 | ->execute() |
||
471 | ->rows(); |
||
472 | |||
473 | return array_map(function ($e) { |
||
474 | return $e['id']; |
||
475 | }, $entries); |
||
476 | } |
||
477 | |||
478 | public function findParentRelatedEntries($parent_field_id, $entry_id) |
||
479 | { |
||
480 | $entry = $this->entryManager |
||
481 | ->select() |
||
482 | ->entry($entry_id) |
||
483 | ->section($this->entryManager->fetchEntrySectionID($entry_id)) |
||
484 | ->includeAllFields() |
||
485 | ->schema(array($this->get('label'))) |
||
486 | ->execute() |
||
487 | ->next(); |
||
488 | |||
489 | if (!$entry) { |
||
490 | return array(); |
||
491 | } |
||
492 | |||
493 | return self::getEntries($entry->getData($this->get('id'))); |
||
494 | } |
||
495 | |||
496 | public function fetchFilterableOperators() |
||
497 | { |
||
498 | return array( |
||
499 | array( |
||
500 | 'title' => 'links to', |
||
501 | 'filter' => ' ', |
||
502 | 'help' => __('Find entries that links to the specified filter') |
||
503 | ), |
||
504 | array( |
||
505 | 'filter' => 'sql: NOT NULL', |
||
506 | 'title' => 'is not empty', |
||
507 | 'help' => __('Find entries with a non-empty value.') |
||
508 | ), |
||
509 | array( |
||
510 | 'filter' => 'sql: NULL', |
||
511 | 'title' => 'is empty', |
||
512 | 'help' => __('Find entries with an empty value.') |
||
513 | ), |
||
514 | array( |
||
515 | 'title' => 'contains', |
||
516 | 'filter' => 'regexp: ', |
||
517 | 'help' => __('Find values that match the given <a href="%s">MySQL regular expressions</a>.', array( |
||
518 | 'https://dev.mysql.com/doc/mysql/en/regexp.html' |
||
519 | )) |
||
520 | ), |
||
521 | array( |
||
522 | 'title' => 'does not contain', |
||
523 | 'filter' => 'not-regexp: ', |
||
524 | 'help' => __('Find values that do not match the given <a href="%s">MySQL regular expressions</a>.', array( |
||
525 | 'https://dev.mysql.com/doc/mysql/en/regexp.html' |
||
526 | )) |
||
527 | ), |
||
528 | ); |
||
529 | } |
||
530 | |||
531 | public function fetchSuggestionTypes() |
||
532 | { |
||
533 | return array('association'); |
||
534 | } |
||
535 | |||
536 | public function fetchIDsfromValue($value) |
||
537 | { |
||
538 | $ids = array(); |
||
539 | $sections = $this->getArray('sections'); |
||
540 | |||
541 | foreach ($sections as $sectionId) { |
||
542 | $section = $this->sectionManager |
||
543 | ->select() |
||
544 | ->section($sectionId) |
||
545 | ->execute() |
||
546 | ->next(); |
||
547 | |||
548 | if (!$section) { |
||
549 | continue; |
||
550 | } |
||
551 | $filterableFields = $section->fetchFilterableFields(); |
||
552 | if (empty($filterableFields)) { |
||
553 | continue; |
||
554 | } |
||
555 | foreach ($filterableFields as $fId => $field) { |
||
556 | $joins = ''; |
||
557 | $where = ''; |
||
558 | if ($field instanceof FieldRelationship) { |
||
559 | continue; |
||
560 | } |
||
561 | $field->buildDSRetrievalSQL(array($value), $joins, $where, false); |
||
562 | |||
563 | if (!empty($fEntries)) { |
||
564 | $ids = array_merge($ids, $fEntries); |
||
565 | break; |
||
566 | } |
||
567 | } |
||
568 | } |
||
569 | |||
570 | return array_map(function ($e) { |
||
571 | return $e['id']; |
||
572 | }, $ids); |
||
573 | } |
||
574 | |||
575 | public function prepareAssociationsDrawerXMLElement(Entry $e, array $parent_association, $prepolutate = '') |
||
576 | { |
||
577 | $currentSection = $this->sectionManager |
||
578 | ->select() |
||
579 | ->section($parent_association['child_section_id']) |
||
580 | ->execute() |
||
581 | ->next(); |
||
582 | $visibleCols = $currentSection->fetchVisibleColumns(); |
||
583 | $outputFieldId = current($visibleCols)->get('id'); |
||
584 | $outputField = $this->fieldManager |
||
585 | ->select() |
||
586 | ->field($outputFieldId) |
||
587 | ->execute() |
||
588 | ->next(); |
||
589 | |||
590 | $value = $outputField->prepareReadableValue($e->getData($outputFieldId), $e->get('id'), true, __('None')); |
||
591 | |||
592 | $li = new XMLElement('li'); |
||
593 | $li->setAttribute('class', 'field-' . $this->get('type')); |
||
594 | $a = new XMLElement('a', strip_tags($value)); |
||
595 | $a->setAttribute('href', SYMPHONY_URL . '/publish/' . $parent_association['handle'] . '/edit/' . $e->get('id') . '/'); |
||
596 | $li->appendChild($a); |
||
597 | |||
598 | return $li; |
||
599 | } |
||
600 | |||
601 | /** |
||
602 | * @param string $joins |
||
603 | * @param string $where |
||
604 | */ |
||
605 | public function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation = false) |
||
606 | { |
||
607 | $field_id = $this->get('id'); |
||
608 | |||
609 | // REGEX filtering is a special case, and will only work on the first item |
||
610 | // in the array. You cannot specify multiple filters when REGEX is involved. |
||
611 | if (self::isFilterRegex($data[0])) { |
||
612 | return $this->buildRegexSQL($data[0], array('entries'), $joins, $where); |
||
613 | } |
||
614 | |||
615 | $this->_key++; |
||
616 | |||
617 | $where .= ' AND (1=' . ($andOperation ? '1' : '0') . ' '; |
||
618 | |||
619 | $joins .= " |
||
620 | INNER JOIN |
||
621 | `tbl_entries_data_{$field_id}` AS `t{$field_id}_{$this->_key}` |
||
622 | ON (`e`.`id` = `t{$field_id}_{$this->_key}`.`entry_id`) |
||
623 | "; |
||
624 | |||
625 | $normalizedValues = array(); |
||
626 | |||
627 | foreach ($data as $value) { |
||
628 | if (!is_numeric($value) && !is_null($value)) { |
||
629 | $normalizedValues = array_merge($normalizedValues, $this->fetchIDsfromValue($value)); |
||
630 | } else { |
||
631 | $normalizedValues[] = $value; |
||
632 | } |
||
633 | } |
||
634 | |||
635 | foreach ($normalizedValues as $value) { |
||
636 | $where .= $this->generateWhereFilter($this->cleanValue($value), "t{$field_id}_{$this->_key}", $andOperation); |
||
637 | } |
||
638 | |||
639 | $where .= ')'; |
||
640 | |||
641 | return true; // this tells the DS Manager that filters are OK!! |
||
642 | } |
||
643 | |||
644 | /* ******* EVENTS ******* */ |
||
645 | |||
646 | public function getExampleFormMarkup() |
||
647 | { |
||
648 | $label = Widget::Label($this->get('label')); |
||
649 | $label->appendChild(Widget::Input('fields['.$this->get('element_name').'][entries]', null, 'hidden')); |
||
650 | |||
651 | return $label; |
||
652 | } |
||
653 | |||
654 | |||
655 | /* ******* DATA SOURCE ******* */ |
||
656 | |||
657 | private function fetchEntry($eId, $elements = array()) |
||
658 | { |
||
659 | return $this->entryManager |
||
660 | ->select() |
||
661 | ->entry($eId) |
||
662 | ->schema($elements) |
||
663 | ->execute() |
||
664 | ->next(); |
||
665 | } |
||
666 | |||
667 | protected function fetchAllIncludableElements() |
||
676 | |||
677 | public function fetchIncludableElements() |
||
704 | |||
705 | /** |
||
706 | * Appends data into the XML tree of a Data Source |
||
707 | * @param $wrapper |
||
708 | * @param $data |
||
709 | */ |
||
710 | public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = null, $entry_id = null) |
||
711 | { |
||
712 | if (!is_array($data) || empty($data)) { |
||
713 | return; |
||
714 | } |
||
715 | |||
716 | // try to find an existing root |
||
717 | $root = null; |
||
718 | $newRoot = false; |
||
719 | foreach (array_reverse($wrapper->getChildren()) as $xmlField) { |
||
720 | if ($xmlField->getName() === $this->get('element_name')) { |
||
721 | $root = $xmlField; |
||
722 | break; |
||
723 | } |
||
724 | } |
||
725 | |||
726 | // root was not found, create one |
||
727 | if (!$root) { |
||
728 | $root = new XMLElement($this->get('element_name')); |
||
729 | $newRoot = true; |
||
730 | } |
||
731 | |||
1023 | |||
1024 | public function getParameterPoolValue(array $data, $entry_id = null) |
||
1029 | |||
1030 | /* ********* Utils *********** */ |
||
1031 | |||
1032 | /** |
||
1033 | * Return true if $fieldName is allowed in $sectionElements |
||
1034 | * @param string $fieldName |
||
1035 | * @param string $sectionElements |
||
1036 | * @return bool |
||
1037 | */ |
||
1038 | public static function isFieldIncluded($fieldName, $sectionElements) |
||
1042 | |||
1043 | public static function getSectionElementName($fieldName, $sectionElements) |
||
1063 | |||
1064 | public static function parseElements($field) |
||
1106 | |||
1107 | public static function extractMode($fieldName, $mode) |
||
1119 | |||
1120 | private function buildSectionSelect($name) |
||
1138 | |||
1139 | View Code Duplication | private function appendSelectionSelect(&$wrapper) |
|
1153 | |||
1154 | private function createEntriesHiddenInput($data) |
||
1164 | |||
1165 | private function createActionBarMenu($sections) |
||
1233 | |||
1234 | /* ********* UI *********** */ |
||
1235 | |||
1236 | /** |
||
1237 | * |
||
1238 | * Builds the UI for the field's settings when creating/editing a section |
||
1239 | * @param XMLElement $wrapper |
||
1240 | * @param array $errors |
||
1241 | */ |
||
1242 | public function displaySettingsPanel(XMLElement &$wrapper, $errors = null) |
||
1374 | |||
1375 | /** |
||
1376 | * |
||
1377 | * Builds the UI for the publish page |
||
1378 | * @param XMLElement $wrapper |
||
1379 | * @param mixed $data |
||
1380 | * @param mixed $flagWithError |
||
1381 | * @param string $fieldnamePrefix |
||
1382 | * @param string $fieldnamePostfix |
||
1383 | */ |
||
1384 | public function displayPublishPanel(XMLElement &$wrapper, $data = null, $flagWithError = null, $fieldnamePrefix = null, $fieldnamePostfix = null, $entry_id = null) |
||
1446 | |||
1447 | /** |
||
1448 | * |
||
1449 | * Return a plain text representation of the field's data |
||
1450 | * @param array $data |
||
1451 | * @param int $entry_id |
||
1452 | */ |
||
1453 | public function prepareTextValue($data, $entry_id = null) |
||
1460 | |||
1461 | /** |
||
1462 | * Format this field value for display as readable text value. |
||
1463 | * |
||
1464 | * @param array $data |
||
1465 | * an associative array of data for this string. At minimum this requires a |
||
1466 | * key of 'value'. |
||
1467 | * @param integer $entry_id (optional) |
||
1468 | * An option entry ID for more intelligent processing. Defaults to null. |
||
1469 | * @param string $defaultValue (optional) |
||
1470 | * The value to use when no plain text representation of the field's data |
||
1471 | * can be made. Defaults to null. |
||
1472 | * @return string |
||
1473 | * the readable text summary of the values of this field instance. |
||
1474 | */ |
||
1475 | public function prepareReadableValue($data, $entry_id = null, $truncate = false, $defaultValue = 'None') |
||
1499 | |||
1500 | /** |
||
1501 | * Format this field value for display in the publish index tables. |
||
1502 | * |
||
1503 | * @param array $data |
||
1504 | * an associative array of data for this string. At minimum this requires a |
||
1505 | * key of 'value'. |
||
1506 | * @param XMLElement $link (optional) |
||
1507 | * an XML link structure to append the content of this to provided it is not |
||
1508 | * null. it defaults to null. |
||
1509 | * @param integer $entry_id (optional) |
||
1510 | * An option entry ID for more intelligent processing. defaults to null |
||
1511 | * @return string |
||
1512 | * the formatted string summary of the values of this field instance. |
||
1513 | */ |
||
1514 | public function prepareTableValue($data, XMLElement $link = null, $entry_id = null) |
||
1557 | |||
1558 | /* ********* SQL Data Definition ************* */ |
||
1559 | |||
1560 | /** |
||
1561 | * |
||
1562 | * Creates table needed for entries of individual fields |
||
1563 | */ |
||
1564 | public function createTable() |
||
1589 | |||
1590 | /** |
||
1591 | * Creates the table needed for the settings of the field |
||
1592 | */ |
||
1593 | public static function createFieldTable() |
||
1690 | |||
1691 | public static function update_102() |
||
1746 | |||
1747 | View Code Duplication | public static function update_103() |
|
1762 | |||
1763 | public static function update_200() |
||
1811 | |||
1812 | View Code Duplication | public static function update_2008() |
|
1827 | |||
1828 | /** |
||
1829 | * |
||
1830 | * Drops the table needed for the settings of the field |
||
1831 | */ |
||
1832 | public static function deleteFieldTable() |
||
1840 | |||
1841 | private static function removeSectionAssociation($child_field_id) |
||
1849 | } |
||
1850 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.