GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Field   F
last analyzed

Complexity

Total Complexity 177

Size/Duplication

Total Lines 1981
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 461
c 7
b 0
f 0
dl 0
loc 1981
rs 2
wmc 177

74 Methods

Rating   Name   Duplication   Size   Complexity  
A isFilterSQL() 0 4 2
A fetchSuggestionTypes() 0 3 1
A isFilterRegex() 0 4 3
A prepareTextValue() 0 3 1
A requiresSQLGrouping() 0 3 1
A canToggle() 0 3 1
A canPrePopulate() 0 3 1
A cleanValue() 0 3 1
A __construct() 0 3 2
A fetchAssociatedEntrySearchValue() 0 3 1
A handle() 0 3 1
A remove() 0 3 1
A canShowAssociationColumn() 0 3 1
A set() 0 3 1
A canShowTableColumn() 0 3 1
A isRandomOrder() 0 3 1
A fetchIncludableElements() 0 3 1
A getToggleStates() 0 3 1
A name() 0 3 2
A fetchAssociatedEntryIDs() 0 4 2
A displayPublishPanel() 0 2 1
A createTable() 0 4 1
A canPublishFilter() 0 3 1
A fetchAssociatedEntryCount() 0 2 1
A tearDown() 0 3 1
A allowDatasourceParamOutput() 0 3 1
A allowDatasourceOutputGrouping() 0 3 1
A mustBeUnique() 0 3 1
A requiresTable() 0 3 1
A getParameterPoolValue() 0 3 1
A toggleFieldData() 0 3 1
A canFilter() 0 3 1
A groupRecords() 0 4 1
A isSortable() 0 3 1
A findDefaults() 0 2 1
A createCheckboxSetting() 0 9 1
A prepareReadableValue() 0 16 6
A getExampleFormMarkup() 0 6 1
A tableExists() 0 6 2
C checkFields() 0 38 13
A checkPostFieldData() 0 13 4
B exists() 0 41 7
A buildSummaryBlock() 0 36 3
A appendStatusFooter() 0 10 1
A displaySettingsPanel() 0 21 4
A fetchFilterableOperators() 0 30 1
A displayDatasourceFilterPanel() 0 15 4
A displayFilteringOptions() 0 25 3
A setFromPOST() 0 7 6
A processRawFieldData() 0 6 1
A setArray() 0 8 3
A commit() 0 24 5
A findRelatedEntries() 0 14 2
A prepareAssociationsDrawerXMLElement() 0 17 2
A get() 0 11 3
A buildFilterSQL() 0 32 5
A appendFormattedElement() 0 5 2
A findParentRelatedEntries() 0 14 2
A getAssociationContext() 0 23 5
B appendAssociationInterfaceSelect() 0 50 9
A appendRequiredCheckbox() 0 7 2
A buildSortingSQL() 0 7 2
A buildLocationSelect() 0 16 2
A appendShowAssociationCheckbox() 0 8 2
B buildRegexSQL() 0 39 6
A createAssociationsDrawerXMLElement() 0 7 1
B buildDSRetrievalSQL() 0 49 6
A buildValidationSelect() 0 25 4
A prepareTableValue() 0 11 2
A buildSortingSelectSQL() 0 10 3
A buildFormatterSelect() 0 24 5
A appendShowColumnCheckbox() 0 7 2
A setAssociationContext() 0 12 2
A entryDataCleanup() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like Field often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Field, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package toolkit
4
 */
5
/**
6
 * The Field class represents a Symphony Field object. Fields are the building
7
 * blocks for Sections. All fields instances are unique and can only be used once
8
 * in a Symphony install. Fields have their own field table which records where
9
 * instances of this field type have been used in other sections and their settings.
10
 * They also spinoff other `tbl_entry_data_{id}` tables that actually store data for
11
 * entries particular to this field.
12
 */
13
class Field
14
{
15
    /**
16
     * The desired result when creating a field in the section editor
17
     * @var integer
18
     */
19
    const __OK__ = 100;
20
21
    /**
22
     * If an error occurring when saving a section because of this field,
23
     * this will be returned
24
     * @var integer
25
     */
26
    const __ERROR__ = 150;
27
28
    /**
29
     * When saving a section, if a value that is required is missing,
30
     * this will be returned
31
     * @var integer
32
     */
33
    const __MISSING_FIELDS__ = 200;
34
35
    /**
36
     * If a value for a setting is invalid, this will be returned
37
     * @var integer
38
     */
39
    const __INVALID_FIELDS__ = 220;
40
41
    /**
42
     * If there already is an instance of this field in this section and
43
     * `mustBeUnique()` returns true, this will be returned
44
     * @var integer
45
     * @see mustBeUnique()
46
     */
47
    const __DUPLICATE__ = 300;
48
49
    /**
50
     * Fields can returned this is an error occurred when saving the
51
     * field's settings that doesn't fit another `Field` constant
52
     * @var integer
53
     */
54
    const __ERROR_CUSTOM__ = 400;
55
56
    /**
57
     * If the field name is not a valid QName, this error will be returned
58
     * @var integer
59
     */
60
    const __INVALID_QNAME__ = 500;
61
62
    /**
63
     * Used by the `FieldManager` to return fields that can be toggled
64
     * @var integer
65
     */
66
    const __TOGGLEABLE_ONLY__ = 600;
67
68
    /**
69
     * Used by the `FieldManager` to return fields that can't be toggled
70
     * @var integer
71
     */
72
    const __UNTOGGLEABLE_ONLY__ = 700;
73
74
    /**
75
     * Used by the `FieldManager` to return fields that can be filtered
76
     * @var integer
77
     */
78
    const __FILTERABLE_ONLY__ = 800;
79
80
    /**
81
     * Used by the `FieldManager` to return fields that can't be filtered
82
     * @var integer
83
     */
84
    const __UNFILTERABLE_ONLY__ = 900;
85
86
    /**
87
     * Used by the `FieldManager` to just return all fields
88
     * @var integer
89
     */
90
    const __FIELD_ALL__ = 1000;
91
92
    /**
93
     * Used to manage the joins when this field used in a datasource
94
     * @var integer
95
     */
96
    protected $_key = 0;
97
98
    /**
99
     * An associative array of the settings for this `Field` instance
100
     * @var array
101
     */
102
    protected $_settings = array();
103
104
    /**
105
     * Whether this field is required inherently, defaults to false.
106
     * @var boolean
107
     */
108
    protected $_required = false;
109
110
    /**
111
     * Whether this field can be viewed on the entries table. Note
112
     * that this is not the same variable as the one set when saving
113
     * a field in the section editor, rather just the if the field has
114
     * the ability to be shown. Defaults to true.
115
     * @var boolean
116
     */
117
    protected $_showcolumn = true;
118
119
    /**
120
     * Whether this field has an association that should be shown on
121
     * the Publish Index. This does not mean that it will be, but just
122
     * that this field has the ability too. Defaults to false.
123
     * @var boolean
124
     */
125
    protected $_showassociation = false;
126
127
    /**
128
     * Construct a new instance of this field.
129
     */
130
    public function __construct()
131
    {
132
        $this->_handle = (strtolower(get_class($this)) == 'field' ? 'field' : strtolower(substr(get_class($this), 5)));
0 ignored issues
show
Bug Best Practice introduced by
The property _handle does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
133
    }
134
135
    /**
136
     * Test whether this field can show the table column.
137
     *
138
     * @return boolean
139
     *  true if this can, false otherwise.
140
     */
141
    public function canShowTableColumn()
142
    {
143
        return $this->_showcolumn;
144
    }
145
146
    /**
147
     * Test whether this field can show the association column in
148
     * the Publish Index.
149
     *
150
     * @since Symphony 2.6.0
151
     * @return boolean
152
     *  true if this can, false otherwise.
153
     */
154
    public function canShowAssociationColumn()
155
    {
156
        return $this->_showassociation;
157
    }
158
159
    /**
160
     * Test whether this field can be toggled using the With Selected menu
161
     * on the Publish Index.
162
     *
163
     * @return boolean
164
     *  true if it can be toggled, false otherwise.
165
     */
166
    public function canToggle()
167
    {
168
        return false;
169
    }
170
171
    /**
172
     * Accessor to the toggle states. This default implementation returns
173
     * an empty array.
174
     *
175
     * @return array
176
     *  the array of toggle states.
177
     */
178
    public function getToggleStates()
179
    {
180
        return array();
181
    }
182
183
    /**
184
     * Toggle the field data. This default implementation always returns
185
     * the input data.
186
     *
187
     * @param array $data
188
     *   the data to toggle.
189
     * @param string $newState
190
     *   the new value to set
191
     * @param integer $entry_id (optional)
192
     *   an optional entry ID for more intelligent processing. defaults to null
193
     * @return array
194
     *   the toggled data.
195
     */
196
    public function toggleFieldData(array $data, $newState, $entry_id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $newState is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

196
    public function toggleFieldData(array $data, /** @scrutinizer ignore-unused */ $newState, $entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
197
    {
198
        return $data;
199
    }
200
201
    /**
202
     * Test whether this field can be filtered. This default implementation
203
     * prohibits filtering. Filtering allows the XML output results to be limited
204
     * according to an input parameter. Subclasses should override this if
205
     * filtering is supported.
206
     *
207
     * @return boolean
208
     *  true if this can be filtered, false otherwise.
209
     */
210
    public function canFilter()
211
    {
212
        return false;
213
    }
214
215
    /**
216
     * Test whether this field can be filtered in the publish index. This default
217
     * implementation prohibts filtering. Publish Filtering allows the index view
218
     * to filter results. Subclasses should override this if
219
     * filtering is supported.
220
     *
221
     * @return boolean
222
     *  true if this can be publish-filtered, false otherwise.
223
     */
224
    public function canPublishFilter()
225
    {
226
        return $this->canFilter();
227
    }
228
229
    /**
230
     * Test whether this field can be prepopulated with data. This default
231
     * implementation does not support pre-population and, thus, returns false.
232
     *
233
     * @return boolean
234
     *  true if this can be pre-populated, false otherwise.
235
     */
236
    public function canPrePopulate()
237
    {
238
        return false;
239
    }
240
241
    /**
242
     * Test whether this field can be sorted. This default implementation
243
     * returns false.
244
     *
245
     * @return boolean
246
     *  true if this field is sortable, false otherwise.
247
     */
248
    public function isSortable()
249
    {
250
        return false;
251
    }
252
253
    /**
254
     * Test whether this field must be unique in a section, that is, only one of
255
     * this field's type is allowed per section. This default implementation
256
     * always returns false.
257
     *
258
     * @return boolean
259
     *  true if the content of this field must be unique, false otherwise.
260
     */
261
    public function mustBeUnique()
262
    {
263
        return false;
264
    }
265
266
    /**
267
     * Test whether this field supports data source output grouping. This
268
     * default implementation prohibits grouping. Data-source grouping allows
269
     * clients of this field to group the XML output according to this field.
270
     * Subclasses should override this if grouping is supported.
271
     *
272
     * @return boolean
273
     *  true if this field does support data source grouping, false otherwise.
274
     */
275
    public function allowDatasourceOutputGrouping()
276
    {
277
        return false;
278
    }
279
280
    /**
281
     * Test whether this field requires grouping. If this function returns true
282
     * SQL statements generated in the `EntryManager` will include the `DISTINCT` keyword
283
     * to only return a single row for an entry regardless of how many 'matches' it
284
     * might have. This default implementation returns false.
285
     *
286
     * @return boolean
287
     *  true if this field requires grouping, false otherwise.
288
     */
289
    public function requiresSQLGrouping()
290
    {
291
        return false;
292
    }
293
294
    /**
295
     * Test whether this field supports data source parameter output. This
296
     * default implementation prohibits parameter output. Data-source
297
     * parameter output allows this field to be provided as a parameter
298
     * to other data sources or XSLT. Subclasses should override this if
299
     * parameter output is supported.
300
     *
301
     * @return boolean
302
     *  true if this supports data source parameter output, false otherwise.
303
     */
304
    public function allowDatasourceParamOutput()
305
    {
306
        return false;
307
    }
308
309
    /**
310
     * Accessor to the handle of this field object. The Symphony convention is
311
     * for field subclass names to be prefixed with field. Handle removes this prefix
312
     * so that the class handle can be used as the field type.
313
     *
314
     * @return string
315
     *  The field classname minus the field prefix.
316
     */
317
    public function handle()
318
    {
319
        return $this->_handle;
320
    }
321
322
    /**
323
     * Accessor to the name of this field object. The name may contain characters
324
     * that normally would be stripped in the handle while also allowing the field
325
     * name to be localized. If a name is not set, it will return the handle of the
326
     * the field
327
     *
328
     * @return string
329
     *  The field name
330
     */
331
    public function name()
332
    {
333
        return ($this->_name ? $this->_name : $this->_handle);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
334
    }
335
336
    /**
337
     * Clean the input value using html entity encode and the database specific
338
     * clean methods.
339
     *
340
     * @param mixed $value
341
     *  the value to clean.
342
     * @return string
343
     *  the cleaned value.
344
     */
345
    public function cleanValue($value)
346
    {
347
        return html_entity_decode(Symphony::Database()->cleanValue($value));
348
    }
349
350
    /**
351
     * Fields have settings that define how that field will act in a section, including
352
     * if it's required, any validators, if it can be shown on the entries table etc. This
353
     * function will set a setting to a value.  This function will set a setting to a value
354
     * overwriting any existing value for this setting
355
     *
356
     * @param string $setting
357
     *  the setting key.
358
     * @param mixed $value
359
     *  the value of the setting.
360
     */
361
    public function set($setting, $value)
362
    {
363
        $this->_settings[$setting] = $value;
364
    }
365
366
    /**
367
     * Add or overwrite the settings of this field by providing an associative array
368
     * of the settings. This will do nothing if the input array is empty. If a setting is
369
     * omitted from the input array, it will not be unset by this function
370
     *
371
     * @param array $array
372
     *  the associative array of settings for this field
373
     */
374
    public function setArray(array $array = array())
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$array" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$array"; expected 0 but found 1
Loading history...
375
    {
376
        if (empty($array)) {
377
            return;
378
        }
379
380
        foreach ($array as $setting => $value) {
381
            $this->set($setting, $value);
382
        }
383
    }
384
385
    /**
386
     * Fill the input data array with default values for known keys provided
387
     * these settings are not already set. The input array is then used to set
388
     * the values of the corresponding settings for this field. This function
389
     * is called when a section is saved.
390
     *
391
     * @param array $settings
392
     *  the data array to initialize if necessary.
393
     */
394
    public function setFromPOST(array $settings = array())
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$settings" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$settings"; expected 0 but found 1
Loading history...
395
    {
396
        $settings['location'] = (isset($settings['location']) ? $settings['location'] : 'main');
397
        $settings['required'] = (isset($settings['required']) && $settings['required'] === 'yes' ? 'yes' : 'no');
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
398
        $settings['show_column'] = (isset($settings['show_column']) && $settings['show_column'] === 'yes' ? 'yes' : 'no');
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
399
400
        $this->setArray($settings);
401
    }
402
403
    /**
404
     * Accessor to the a setting by name. If no setting is provided all the
405
     * settings of this `Field` instance are returned.
406
     *
407
     * @param string $setting (optional)
408
     *  the name of the setting to access the value for. This is optional and
409
     *  defaults to null in which case all settings are returned.
410
     * @return null|mixed|array
411
     *  the value of the setting if there is one, all settings if the input setting
412
     *  was omitted or null if the setting was supplied but there is no value
413
     *  for that setting.
414
     */
415
    public function get($setting = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$setting" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$setting"; expected 0 but found 1
Loading history...
416
    {
417
        if (is_null($setting)) {
418
            return $this->_settings;
419
        }
420
421
        if (!isset($this->_settings[$setting])) {
422
            return null;
423
        }
424
425
        return $this->_settings[$setting];
426
    }
427
428
    /**
429
     * Unset the value of a setting by the key
430
     *
431
     * @param string $setting
432
     *  the key of the setting to unset.
433
     */
434
    public function remove($setting)
435
    {
436
        unset($this->_settings[$setting]);
437
    }
438
439
    /**
440
     * Just prior to the field being deleted, this function allows
441
     * Fields to cleanup any additional things before it is removed
442
     * from the section. This may be useful to remove data from any
443
     * custom field tables or the configuration.
444
     *
445
     * @since Symphony 2.2.1
446
     * @return boolean
447
     */
448
    public function tearDown()
449
    {
450
        return true;
451
    }
452
453
    /**
454
     * Allows a field to set default settings.
455
     *
456
     * @param array $settings
457
     *  the array of settings to populate with their defaults.
458
     */
459
    public function findDefaults(array &$settings)
460
    {
461
    }
462
463
    /**
464
     * Display the default settings panel, calls the `buildSummaryBlock`
465
     * function after basic field settings are added to the wrapper.
466
     *
467
     * @see buildSummaryBlock()
468
     * @param XMLElement $wrapper
469
     *    the input XMLElement to which the display of this will be appended.
470
     * @param mixed $errors
471
     *  the input error collection. this defaults to null.
472
     * @throws InvalidArgumentException
473
     */
474
    public function displaySettingsPanel(XMLElement &$wrapper, $errors = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$errors" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$errors"; expected 0 but found 1
Loading history...
475
    {
476
        // Create header
477
        $location = ($this->get('location') ? $this->get('location') : 'main');
478
        $header = new XMLElement('header', null, array(
479
            'class' => 'frame-header ' . $location,
480
            'data-name' => $this->name(),
481
            'title' => $this->get('id'),
482
        ));
483
        $label = (($this->get('label')) ? $this->get('label') : __('New Field'));
484
        $header->appendChild(new XMLElement('h4', '<strong>' . $label . '</strong> <span class="type">' . $this->name() . '</span>'));
485
        $wrapper->appendChild($header);
486
487
        // Create content
488
        $wrapper->appendChild(Widget::Input('fields['.$this->get('sortorder').'][type]', $this->handle(), 'hidden'));
0 ignored issues
show
Bug introduced by
Are you sure $this->get('sortorder') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

488
        $wrapper->appendChild(Widget::Input('fields['./** @scrutinizer ignore-type */ $this->get('sortorder').'][type]', $this->handle(), 'hidden'));
Loading history...
489
490
        if ($this->get('id')) {
491
            $wrapper->appendChild(Widget::Input('fields['.$this->get('sortorder').'][id]', $this->get('id'), 'hidden'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('id') can also be of type array; however, parameter $value of Widget::Input() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

491
            $wrapper->appendChild(Widget::Input('fields['.$this->get('sortorder').'][id]', /** @scrutinizer ignore-type */ $this->get('id'), 'hidden'));
Loading history...
492
        }
493
494
        $wrapper->appendChild($this->buildSummaryBlock($errors));
495
    }
496
497
    /**
498
     * Construct the html block to display a summary of this field, which is the field
499
     * Label and it's location within the section. Any error messages generated are
500
     * appended to the optional input error array. This function calls
501
     * `buildLocationSelect` once it is completed
502
     *
503
     * @see buildLocationSelect()
504
     * @param array $errors (optional)
505
     *    an array to append html formatted error messages to. this defaults to null.
506
     * @throws InvalidArgumentException
507
     * @return XMLElement
508
     *    the root XML element of the html display of this.
509
     */
510
    public function buildSummaryBlock($errors = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$errors" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$errors"; expected 0 but found 1
Loading history...
511
    {
512
        $div = new XMLElement('div');
513
514
        // Publish label
515
        $label = Widget::Label(__('Label'));
516
        $label->appendChild(
517
            Widget::Input('fields['.$this->get('sortorder').'][label]', $this->get('label'))
0 ignored issues
show
Bug introduced by
Are you sure $this->get('sortorder') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

517
            Widget::Input('fields['./** @scrutinizer ignore-type */ $this->get('sortorder').'][label]', $this->get('label'))
Loading history...
Bug introduced by
It seems like $this->get('label') can also be of type array; however, parameter $value of Widget::Input() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

517
            Widget::Input('fields['.$this->get('sortorder').'][label]', /** @scrutinizer ignore-type */ $this->get('label'))
Loading history...
518
        );
519
        if (isset($errors['label'])) {
520
            $div->appendChild(Widget::Error($label, $errors['label']));
521
        } else {
522
            $div->appendChild($label);
523
        }
524
525
        // Handle + placement
526
        $group = new XMLElement('div');
527
        $group->setAttribute('class', 'two columns');
528
529
        $label = Widget::Label(__('Handle'));
530
        $label->setAttribute('class', 'column');
531
532
        $label->appendChild(Widget::Input('fields['.$this->get('sortorder').'][element_name]', $this->get('element_name')));
533
534
        if (isset($errors['element_name'])) {
535
            $group->appendChild(Widget::Error($label, $errors['element_name']));
536
        } else {
537
            $group->appendChild($label);
538
        }
539
540
        // Location
541
        $group->appendChild($this->buildLocationSelect($this->get('location'), 'fields['.$this->get('sortorder').'][location]'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('location') can also be of type array; however, parameter $selected of Field::buildLocationSelect() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

541
        $group->appendChild($this->buildLocationSelect(/** @scrutinizer ignore-type */ $this->get('location'), 'fields['.$this->get('sortorder').'][location]'));
Loading history...
542
543
        $div->appendChild($group);
544
545
        return $div;
546
    }
547
548
    /**
549
     * Build the location select widget. This widget allows users to select
550
     * whether this field will appear in the main content column or in the sidebar
551
     * when creating a new entry.
552
     *
553
     * @param string|null $selected (optional)
554
     *    the currently selected location, if there is one. this defaults to null.
555
     * @param string $name (optional)
556
     *    the name of this field. this is optional and defaults to `fields[location]`.
557
     * @param string $label_value (optional)
558
     *    any predefined label for this widget. this is an optional argument that defaults
559
     *    to null.
560
     * @throws InvalidArgumentException
561
     * @return XMLElement
562
     *    An XMLElement representing a `<select>` field containing the options.
563
     */
564
    public function buildLocationSelect($selected = null, $name = 'fields[location]', $label_value = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$selected" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$selected"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$name" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$name"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$label_value" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$label_value"; expected 0 but found 1
Loading history...
565
    {
566
        if (!$label_value) {
567
            $label_value = __('Placement');
568
        }
569
570
        $label = Widget::Label($label_value);
571
        $label->setAttribute('class', 'column');
572
573
        $options = array(
574
            array('main', $selected == 'main', __('Main content')),
575
            array('sidebar', $selected == 'sidebar', __('Sidebar'))
576
        );
577
        $label->appendChild(Widget::Select($name, $options));
578
579
        return $label;
580
    }
581
582
    /**
583
     * Construct the html widget for selecting a text formatter for this field.
584
     *
585
     * @param string $selected (optional)
586
     *    the currently selected text formatter name if there is one. this defaults
587
     *    to null.
588
     * @param string $name (optional)
589
     *    the name of this field in the form. this is optional and defaults to
590
     *    "fields[format]".
591
     * @param string $label_value
592
     *    the default label for the widget to construct. if null is passed in then
593
     *    this defaults to the localization of "Formatting".
594
     * @throws InvalidArgumentException
595
     * @return XMLElement
596
     *    An XMLElement representing a `<select>` field containing the options.
597
     */
598
    public function buildFormatterSelect($selected = null, $name = 'fields[format]', $label_value)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$selected" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$selected"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$name" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$name"; expected 0 but found 1
Loading history...
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
599
    {
600
        $formatters = TextformatterManager::listAll();
601
602
        if (!$label_value) {
603
            $label_value = __('Formatting');
604
        }
605
606
        $label = Widget::Label($label_value);
607
        $label->setAttribute('class', 'column');
608
609
        $options = array();
610
611
        $options[] = array('none', false, __('None'));
612
613
        if (!empty($formatters) && is_array($formatters)) {
614
            foreach ($formatters as $handle => $about) {
615
                $options[] = array($handle, ($selected == $handle), $about['name']);
616
            }
617
        }
618
619
        $label->appendChild(Widget::Select($name, $options));
620
621
        return $label;
622
    }
623
624
    /**
625
     * Append a validator selector to a given `XMLElement`. Note that this
626
     * function differs from the other two similarly named build functions in
627
     * that it takes an `XMLElement` to append the Validator to as a parameter,
628
     * and does not return anything.
629
     *
630
     * @param XMLElement $wrapper
631
     *    the parent element to append the XMLElement of the Validation select to,
632
     *  passed by reference.
633
     * @param string $selected (optional)
634
     *    the current validator selection if there is one. defaults to null if there
635
     *    isn't.
636
     * @param string $name (optional)
637
     *    the form element name of this field. this defaults to "fields[validator]".
638
     * @param string $type (optional)
639
     *    the type of input for the validation to apply to. this defaults to 'input'
640
     *    but also accepts 'upload'.
641
     * @param array $errors (optional)
642
     *    an associative array of errors
643
     * @throws InvalidArgumentException
644
     */
645
    public function buildValidationSelect(XMLElement &$wrapper, $selected = null, $name = 'fields[validator]', $type = 'input', array $errors = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$selected" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$selected"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$name" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$name"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$type" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$type"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$errors" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$errors"; expected 0 but found 1
Loading history...
646
    {
647
        include TOOLKIT . '/util.validators.php';
0 ignored issues
show
Bug introduced by
The constant TOOLKIT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
648
649
        $rules = ($type == 'upload' ? $upload : $validators);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $validators seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $upload seems to be never defined.
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
650
651
        $label = Widget::Label(__('Validation Rule'));
652
        $label->setAttribute('class', 'column');
653
        $label->appendChild(new XMLElement('i', __('Optional')));
654
        $label->appendChild(Widget::Input($name, $selected));
655
656
        $ul = new XMLElement('ul', null, array('class' => 'tags singular', 'data-interactive' => 'data-interactive'));
657
        foreach ($rules as $name => $rule) {
658
            $ul->appendChild(new XMLElement('li', $name, array('class' => $rule)));
659
        }
660
661
        if (isset($errors['validator'])) {
662
            $div = new XMLElement('div');
663
            $div->appendChild($label);
664
            $div->appendChild($ul);
665
666
            $wrapper->appendChild(Widget::Error($div, $errors['validator']));
667
        } else {
668
            $wrapper->appendChild($label);
669
            $wrapper->appendChild($ul);
670
        }
671
    }
672
673
    /**
674
     * Append the html widget for selecting an association interface and editor
675
     * for this field.
676
     *
677
     * @param XMLElement $wrapper
678
     *    the parent XML element to append the association interface selection to,
679
     *    if either interfaces or editors are provided to the system.
680
     * @since Symphony 2.5.0
681
     */
682
    public function appendAssociationInterfaceSelect(XMLElement &$wrapper)
683
    {
684
        $wrapper->setAttribute('data-condition', 'associative');
685
686
        $interfaces = Symphony::ExtensionManager()->getProvidersOf(iProvider::ASSOCIATION_UI);
687
        $editors = Symphony::ExtensionManager()->getProvidersOf(iProvider::ASSOCIATION_EDITOR);
688
689
        if (!empty($interfaces) || !empty($editors)) {
690
            $association_context = $this->getAssociationContext();
691
692
            $group = new XMLElement('div');
693
            if (!empty($interfaces) && !empty($editors)) {
694
                $group->setAttribute('class', 'two columns');
695
            }
696
697
            // Create interface select
698
            if (!empty($interfaces)) {
699
                $label = Widget::Label(__('Association Interface'), null, 'column');
700
                $label->appendChild(new XMLElement('i', __('Optional')));
701
702
                $options = array(
703
                    array(null, false, __('None'))
704
                );
705
                foreach ($interfaces as $id => $name) {
706
                    $options[] = array($id, ($association_context['interface'] === $id), $name);
707
                }
708
709
                $select = Widget::Select('fields[' . $this->get('sortorder') . '][association_ui]', $options);
0 ignored issues
show
Bug introduced by
Are you sure $this->get('sortorder') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

709
                $select = Widget::Select('fields[' . /** @scrutinizer ignore-type */ $this->get('sortorder') . '][association_ui]', $options);
Loading history...
710
                $label->appendChild($select);
711
                $group->appendChild($label);
712
            }
713
714
            // Create editor select
715
            if (!empty($editors)) {
716
                $label = Widget::Label(__('Association Editor'), null, 'column');
717
                $label->appendChild(new XMLElement('i', __('Optional')));
718
719
                $options = array(
720
                    array(null, false, __('None'))
721
                );
722
                foreach ($editors as $id => $name) {
723
                    $options[] = array($id, ($association_context['editor'] === $id), $name);
724
                }
725
726
                $select = Widget::Select('fields[' . $this->get('sortorder') . '][association_editor]', $options);
727
                $label->appendChild($select);
728
                $group->appendChild($label);
729
            }
730
731
            $wrapper->appendChild($group);
732
        }
733
    }
734
735
    /**
736
     * Get association data of the current field from the page context.
737
     *
738
     * @since Symphony 2.5.0
739
     * @return array
740
     */
741
    public function getAssociationContext()
742
    {
743
        $context = Symphony::Engine()->Page->getContext();
0 ignored issues
show
Bug introduced by
The method getContext() does not exist on HTMLPage. It seems like you code against a sub-type of HTMLPage such as AdministrationPage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

743
        /** @scrutinizer ignore-call */ 
744
        $context = Symphony::Engine()->Page->getContext();
Loading history...
Bug introduced by
The property Page does not seem to exist on Frontend.
Loading history...
744
        $associations = $context['associations']['parent'];
745
        $field_association = array();
746
        $count = 0;
747
748
        if (!empty($associations)) {
749
            $associationsCount = count($associations);
750
            for ($i = 0; $i < $associationsCount; $i++) {
751
                if ($associations[$i]['child_section_field_id'] == $this->get('id')) {
752
                    if ($count === 0) {
753
                        $field_association = $associations[$i];
754
                        $count++;
755
                    } else {
756
                        $field_association['parent_section_id'] .= '|' . $associations[$i]['parent_section_id'];
757
                        $field_association['parent_section_field_id'] .= '|' . $associations[$i]['parent_section_field_id'];
758
                    }
759
                }
760
            }
761
        }
762
763
        return $field_association;
764
    }
765
766
    /**
767
     * Set association data for the current field.
768
     *
769
     * @since Symphony 2.5.0
770
     * @param XMLElement $wrapper
771
     */
772
    public function setAssociationContext(XMLElement &$wrapper)
773
    {
774
        $association_context = $this->getAssociationContext();
775
776
        if (!empty($association_context)) {
777
            $wrapper->setAttributeArray(array(
778
                'data-parent-section-id' => $association_context['parent_section_id'],
779
                'data-parent-section-field-id' => $association_context['parent_section_field_id'],
780
                'data-child-section-id' => $association_context['child_section_id'],
781
                'data-child-section-field-id' => $association_context['child_section_field_id'],
782
                'data-interface' => $association_context['interface'],
783
                'data-editor' => $association_context['editor']
784
            ));
785
        }
786
    }
787
788
    /**
789
     * Append and set a labeled html checkbox to the input XML element if this
790
     * field is set as a required field.
791
     *
792
     * @param XMLElement $wrapper
793
     *    the parent XML element to append the constructed html checkbox to if
794
     *    necessary.
795
     * @throws InvalidArgumentException
796
     */
797
    public function appendRequiredCheckbox(XMLElement &$wrapper)
798
    {
799
        if (!$this->_required) {
800
            return;
801
        }
802
803
        $this->createCheckboxSetting($wrapper, 'required', __('Make this a required field'));
804
    }
805
806
    /**
807
     * Append the show column html widget to the input parent XML element. This
808
     * displays a column in the entries table or not.
809
     *
810
     * @param XMLElement $wrapper
811
     *    the parent XML element to append the checkbox to.
812
     * @throws InvalidArgumentException
813
     */
814
    public function appendShowColumnCheckbox(XMLElement &$wrapper)
815
    {
816
        if (!$this->_showcolumn) {
817
            return;
818
        }
819
820
        $this->createCheckboxSetting($wrapper, 'show_column', __('Display in entries table'));
821
    }
822
823
    /**
824
     * Append the show association html widget to the input parent XML element. This
825
     * widget allows fields that provide linking to hide or show the column in the linked
826
     * section, similar to how the Show Column functionality works, but for the linked
827
     * section.
828
     *
829
     * @param XMLElement $wrapper
830
     *    the parent XML element to append the checkbox to.
831
     * @param string $help (optional)
832
     *    a help message to show below the checkbox.
833
     * @throws InvalidArgumentException
834
     */
835
    public function appendShowAssociationCheckbox(XMLElement &$wrapper, $help = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$help" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$help"; expected 0 but found 1
Loading history...
836
    {
837
        if (!$this->_showassociation) {
838
            return;
839
        }
840
841
        $label = $this->createCheckboxSetting($wrapper, 'show_association', __('Display associations in entries table'), $help);
842
        $label->setAttribute('data-condition', 'associative');
843
    }
844
845
    /**
846
     * Given the setting name and the label, this helper method will add
847
     * the required markup for a checkbox to the given `$wrapper`.
848
     *
849
     * @since Symphony 2.5.2
850
     * @param XMLElement $wrapper
851
     *  Passed by reference, this will have the resulting markup appended to it
852
     * @param string $setting
853
     *  This will be used with $this->get() to get the existing value
854
     * @param string $label_description
855
     *  This will be localisable and displayed after the checkbox when
856
     *  generated.
857
     * @param string $help (optional)
858
     *    A help message to show below the checkbox.
859
     * @return XMLElement
860
     *  The Label and Checkbox that was just added to the `$wrapper`.
861
     */
862
    public function createCheckboxSetting(XMLElement &$wrapper, $setting, $label_description, $help = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$help" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$help"; expected 0 but found 1
Loading history...
863
    {
864
        $order = $this->get('sortorder');
865
        $name = "fields[$order][$setting]";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $order instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $setting instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
866
867
        $label = Widget::Checkbox($name, $this->get($setting), $label_description, $wrapper, $help);
0 ignored issues
show
Bug introduced by
It seems like $this->get($setting) can also be of type array; however, parameter $value of Widget::Checkbox() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

867
        $label = Widget::Checkbox($name, /** @scrutinizer ignore-type */ $this->get($setting), $label_description, $wrapper, $help);
Loading history...
868
        $label->addClass('column');
869
870
        return $label;
871
    }
872
873
    /**
874
     * Append the default status footer to the field settings panel.
875
     * Displays the required and show column checkboxes.
876
     *
877
     * @param XMLElement $wrapper
878
     *    the parent XML element to append the checkbox to.
879
     * @throws InvalidArgumentException
880
     */
881
    public function appendStatusFooter(XMLElement &$wrapper)
882
    {
883
        $fieldset = new XMLElement('fieldset');
884
        $div = new XMLElement('div', null, array('class' => 'two columns'));
885
886
        $this->appendRequiredCheckbox($div);
887
        $this->appendShowColumnCheckbox($div);
888
889
        $fieldset->appendChild($div);
890
        $wrapper->appendChild($fieldset);
891
    }
892
893
    /**
894
     * Check the field's settings to ensure they are valid on the section
895
     * editor
896
     *
897
     * @param array $errors
898
     *  the array to populate with the errors found.
899
     * @param boolean $checkForDuplicates (optional)
900
     *  if set to true, duplicate Field name's in the same section will be flagged
901
     *  as errors. Defaults to true.
902
     * @return integer
903
     *  returns the status of the checking. if errors has been populated with
904
     *  any errors `self::__ERROR__`, `self::__OK__` otherwise.
905
     */
906
    public function checkFields(array &$errors, $checkForDuplicates = true)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$checkForDuplicates" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$checkForDuplicates"; expected 0 but found 1
Loading history...
907
    {
908
        $parent_section = $this->get('parent_section');
909
        $label = $this->get('label');
910
        $element_name = $this->get('element_name');
911
912
        if (Lang::isUnicodeCompiled()) {
913
            $valid_name = preg_match('/^[\p{L}]([0-9\p{L}\.\-\_]+)?$/u', $element_name);
0 ignored issues
show
Bug introduced by
It seems like $element_name can also be of type array; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

913
            $valid_name = preg_match('/^[\p{L}]([0-9\p{L}\.\-\_]+)?$/u', /** @scrutinizer ignore-type */ $element_name);
Loading history...
914
        } else {
915
            $valid_name = preg_match('/^[A-z]([\w\d\-_\.]+)?$/i', $element_name);
916
        }
917
918
        if ($label === '') {
919
            $errors['label'] = __('This is a required field.');
920
        } elseif (strtolower($label) === 'id') {
0 ignored issues
show
Bug introduced by
It seems like $label can also be of type array; however, parameter $str of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

920
        } elseif (strtolower(/** @scrutinizer ignore-type */ $label) === 'id') {
Loading history...
921
            $errors['label'] = __('%s is a reserved name used by the system and is not allowed for a field handle. Try using %s instead.', array('<code>ID</code>', '<code>UID</code>'));
922
        }
923
924
        if ($element_name === '') {
925
            $errors['element_name'] = __('This is a required field.');
926
        } elseif ($element_name === 'id') {
927
            $errors['element_name'] = __('%s is a reserved name used by the system and is not allowed for a field handle. Try using %s instead.', array('<code>id</code>', '<code>uid</code>'));
928
        } elseif (!$valid_name) {
929
            $errors['element_name'] = __('Invalid element name. Must be valid %s.', array('<code>QName</code>'));
930
        } elseif ($checkForDuplicates) {
931
            if (FieldManager::fetchFieldIDFromElementName($element_name, $parent_section) !== $this->get('id')) {
0 ignored issues
show
Bug introduced by
It seems like $parent_section can also be of type array; however, parameter $section_id of FieldManager::fetchFieldIDFromElementName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

931
            if (FieldManager::fetchFieldIDFromElementName($element_name, /** @scrutinizer ignore-type */ $parent_section) !== $this->get('id')) {
Loading history...
932
                $errors['element_name'] = __('A field with that element name already exists. Please choose another.');
933
            }
934
        }
935
936
        // Check that if the validator is provided that it's a valid regular expression
937
        if (!is_null($this->get('validator')) && $this->get('validator') !== '') {
938
            if (@preg_match($this->get('validator'), 'teststring') === false) {
0 ignored issues
show
Bug introduced by
It seems like $this->get('validator') can also be of type array; however, parameter $pattern of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

938
            if (@preg_match(/** @scrutinizer ignore-type */ $this->get('validator'), 'teststring') === false) {
Loading history...
939
                $errors['validator'] = __('Validation rule is not a valid regular expression');
940
            }
941
        }
942
943
        return (!empty($errors) ? self::__ERROR__ : self::__OK__);
944
    }
945
946
    /**
947
     * Format this field value for display in the publish index tables.
948
     *
949
     * Since Symphony 2.5.0, this function will call `Field::prepareReadableValue`
950
     * in order to get the field's human readable value.
951
     *
952
     * @param array $data
953
     *  an associative array of data for this string. At minimum this requires a
954
     *  key of 'value'.
955
     * @param XMLElement $link (optional)
956
     *  an XML link structure to append the content of this to provided it is not
957
     *  null. it defaults to null.
958
     * @param integer $entry_id (optional)
959
     *  An option entry ID for more intelligent processing. defaults to null
960
     * @return string
961
     *  the formatted string summary of the values of this field instance.
962
     */
963
    public function prepareTableValue($data, XMLElement $link = null, $entry_id = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$link" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$link"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
964
    {
965
        $value = $this->prepareReadableValue($data, $entry_id, true, __('None'));
966
967
        if ($link) {
968
            $link->setValue($value);
969
970
            return $link->generate();
971
        }
972
973
        return $value;
974
    }
975
976
    /**
977
     * Format this field value for display as readable  text value. By default, it
978
     * will call `Field::prepareTextValue` to get the raw text value of this field.
979
     *
980
     * If $truncate is set to true, Symphony will truncate the value to the
981
     * configuration setting `cell_truncation_length`.
982
     *
983
     * @since Symphony 2.5.0
984
     * @param array $data
985
     *  an associative array of data for this string. At minimum this requires a
986
     *  key of 'value'.
987
     * @param integer $entry_id (optional)
988
     *  An option entry ID for more intelligent processing. Defaults to null.
989
     * @param string $defaultValue (optional)
990
     *  The value to use when no plain text representation of the field's data
991
     *  can be made. Defaults to null.
992
     * @return string
993
     *  the readable text summary of the values of this field instance.
994
     */
995
    public function prepareReadableValue($data, $entry_id = null, $truncate = false, $defaultValue = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$truncate" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$truncate"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$defaultValue" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$defaultValue"; expected 0 but found 1
Loading history...
996
    {
997
        $value = $this->prepareTextValue($data, $entry_id);
998
999
        if ($truncate) {
1000
            $max_length = Symphony::Configuration()->get('cell_truncation_length', 'symphony');
1001
            $max_length = ($max_length ? $max_length : 75);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
1002
1003
            $value = (General::strlen($value) <= $max_length ? $value : General::substr($value, 0, $max_length) . '…');
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
1004
        }
1005
1006
        if (General::strlen($value) == 0 && $defaultValue != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $defaultValue of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1007
            $value = $defaultValue;
1008
        }
1009
1010
        return $value;
1011
    }
1012
1013
    /**
1014
     * Format this field value for complete display as text (string). By default,
1015
     * it looks for the 'value' key in the $data array and strip tags from it.
1016
     *
1017
     * @since Symphony 2.5.0
1018
     * @param array $data
1019
     *  an associative array of data for this string. At minimum this requires a
1020
     *  key of 'value'.
1021
     * @param integer $entry_id (optional)
1022
     *  An option entry ID for more intelligent processing. defaults to null
1023
     * @return string
1024
     *  the complete text representation of the values of this field instance.
1025
     */
1026
    public function prepareTextValue($data, $entry_id = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1027
    {
1028
        return strip_tags($data['value']);
1029
    }
1030
1031
    /**
1032
     * This is general purpose factory method that makes it easier to create the
1033
     * markup needed in order to create an Associations Drawer XMLElement.
1034
     *
1035
     * @since Symphony 2.5.0
1036
     *
1037
     * @param string $value
1038
     *   The value to display in the link
1039
     * @param Entry $e
1040
     *   The associated entry
1041
     * @param array $parent_association
1042
     *   An array containing information about the association
1043
     * @param string $prepopulate
1044
     *   A string containing prepopulate parameter to append to the association url
1045
     *
1046
     * @return XMLElement
1047
     *   The XMLElement must be a li node, since it will be added an ul node.
1048
     */
1049
    public static function createAssociationsDrawerXMLElement($value, Entry $e, array $parent_association, $prepopulate = '')
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$prepopulate" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$prepopulate"; expected 0 but found 1
Loading history...
1050
    {
1051
        $li = new XMLElement('li');
1052
        $a = new XMLElement('a', $value);
1053
        $a->setAttribute('href', SYMPHONY_URL . '/publish/' . $parent_association['handle'] . '/edit/' . $e->get('id') . '/' . $prepopulate);
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
Are you sure $e->get('id') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1053
        $a->setAttribute('href', SYMPHONY_URL . '/publish/' . $parent_association['handle'] . '/edit/' . /** @scrutinizer ignore-type */ $e->get('id') . '/' . $prepopulate);
Loading history...
1054
        $li->appendChild($a);
1055
        return $li;
1056
    }
1057
1058
    /**
1059
     * Format this field value for display in the Associations Drawer publish index.
1060
     * By default, Symphony will use the return value of the `prepareReadableValue` function.
1061
     *
1062
     * @since Symphony 2.4
1063
     * @since Symphony 2.5.0 The prepopulate parameter was added.
1064
     *
1065
     * @param Entry $e
1066
     *   The associated entry
1067
     * @param array $parent_association
1068
     *   An array containing information about the association
1069
     * @param string $prepopulate
1070
     *   A string containing prepopulate parameter to append to the association url
1071
     *
1072
     * @return XMLElement
1073
     *   The XMLElement must be a li node, since it will be added an ul node.
1074
     */
1075
    public function prepareAssociationsDrawerXMLElement(Entry $e, array $parent_association, $prepopulate = '')
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$prepopulate" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$prepopulate"; expected 0 but found 1
Loading history...
1076
    {
1077
        $value = $this->prepareReadableValue($e->getData($this->get('id')), $e->get('id'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('id') can also be of type array; however, parameter $field_id of Entry::getData() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1077
        $value = $this->prepareReadableValue($e->getData(/** @scrutinizer ignore-type */ $this->get('id')), $e->get('id'));
Loading history...
Bug introduced by
It seems like $e->get('id') can also be of type array; however, parameter $entry_id of Field::prepareReadableValue() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1077
        $value = $this->prepareReadableValue($e->getData($this->get('id')), /** @scrutinizer ignore-type */ $e->get('id'));
Loading history...
Bug introduced by
It seems like $e->getData($this->get('id')) can also be of type object; however, parameter $data of Field::prepareReadableValue() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1077
        $value = $this->prepareReadableValue(/** @scrutinizer ignore-type */ $e->getData($this->get('id')), $e->get('id'));
Loading history...
1078
1079
        // fallback for compatibility since the default
1080
        // `preparePlainTextValue` is not compatible with all fields
1081
        // this should be removed in Symphony 3.0
1082
        if (empty($value)) {
1083
            $value = strip_tags($this->prepareTableValue($e->getData($this->get('id')), null, $e->get('id')));
0 ignored issues
show
Bug introduced by
It seems like $e->get('id') can also be of type array; however, parameter $entry_id of Field::prepareTableValue() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1083
            $value = strip_tags($this->prepareTableValue($e->getData($this->get('id')), null, /** @scrutinizer ignore-type */ $e->get('id')));
Loading history...
Bug introduced by
It seems like $e->getData($this->get('id')) can also be of type object; however, parameter $data of Field::prepareTableValue() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1083
            $value = strip_tags($this->prepareTableValue(/** @scrutinizer ignore-type */ $e->getData($this->get('id')), null, $e->get('id')));
Loading history...
1084
        }
1085
1086
        // use our factory method to create the html
1087
        $li = self::createAssociationsDrawerXMLElement($value, $e, $parent_association, $prepopulate);
1088
1089
        $li->setAttribute('class', 'field-' . $this->get('type'));
0 ignored issues
show
Bug introduced by
Are you sure $this->get('type') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1089
        $li->setAttribute('class', 'field-' . /** @scrutinizer ignore-type */ $this->get('type'));
Loading history...
1090
1091
        return $li;
1092
    }
1093
1094
    /**
1095
     * Display the publish panel for this field. The display panel is the
1096
     * interface shown to Authors that allow them to input data into this
1097
     * field for an `Entry`.
1098
     *
1099
     * @param XMLElement $wrapper
1100
     *  the XML element to append the html defined user interface to this
1101
     *  field.
1102
     * @param array $data (optional)
1103
     *  any existing data that has been supplied for this field instance.
1104
     *  this is encoded as an array of columns, each column maps to an
1105
     *  array of row indexes to the contents of that column. this defaults
1106
     *  to null.
1107
     * @param mixed $flagWithError (optional)
1108
     *  flag with error defaults to null.
1109
     * @param string $fieldnamePrefix (optional)
1110
     *  the string to be prepended to the display of the name of this field.
1111
     *  this defaults to null.
1112
     * @param string $fieldnamePostfix (optional)
1113
     *  the string to be appended to the display of the name of this field.
1114
     *  this defaults to null.
1115
     * @param integer $entry_id (optional)
1116
     *  the entry id of this field. this defaults to null.
1117
     */
1118
    public function displayPublishPanel(XMLElement &$wrapper, $data = null, $flagWithError = null, $fieldnamePrefix = null, $fieldnamePostfix = null, $entry_id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $flagWithError is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1118
    public function displayPublishPanel(XMLElement &$wrapper, $data = null, /** @scrutinizer ignore-unused */ $flagWithError = null, $fieldnamePrefix = null, $fieldnamePostfix = null, $entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$data" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$data"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$flagWithError" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$flagWithError"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$fieldnamePrefix" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$fieldnamePrefix"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$fieldnamePostfix" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$fieldnamePostfix"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1119
    {
1120
    }
1121
1122
    /**
1123
     * Check the field data that has been posted from a form. This will set the
1124
     * input message to the error message or to null if there is none. Any existing
1125
     * message value will be overwritten.
1126
     *
1127
     * @param array $data
1128
     *  the input data to check.
1129
     * @param string $message
1130
     *  the place to set any generated error message. any previous value for
1131
     *  this variable will be overwritten.
1132
     * @param integer $entry_id (optional)
1133
     *  the optional id of this field entry instance. this defaults to null.
1134
     * @return integer
1135
     *  `self::__MISSING_FIELDS__` if there are any missing required fields,
1136
     *  `self::__OK__` otherwise.
1137
     */
1138
    public function checkPostFieldData($data, &$message, $entry_id = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1139
    {
1140
        $message = null;
1141
1142
        $has_no_value = is_array($data) ? empty($data) : strlen(trim($data)) == 0;
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
1143
1144
        if ($this->get('required') === 'yes' && $has_no_value) {
1145
            $message = __('‘%s’ is a required field.', array($this->get('label')));
1146
1147
            return self::__MISSING_FIELDS__;
1148
        }
1149
1150
        return self::__OK__;
1151
    }
1152
1153
    /**
1154
     * Process the raw field data.
1155
     *
1156
     * @param mixed $data
1157
     *  post data from the entry form
1158
     * @param integer $status
1159
     *  the status code resultant from processing the data.
1160
     * @param string $message
1161
     *  the place to set any generated error message. any previous value for
1162
     *  this variable will be overwritten.
1163
     * @param boolean $simulate (optional)
1164
     *  true if this will tell the CF's to simulate data creation, false
1165
     *  otherwise. this defaults to false. this is important if clients
1166
     *  will be deleting or adding data outside of the main entry object
1167
     *  commit function.
1168
     * @param mixed $entry_id (optional)
1169
     *  the current entry. defaults to null.
1170
     * @return array
1171
     *  the processed field data.
1172
     */
1173
    public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $simulate is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1173
    public function processRawFieldData($data, &$status, &$message = null, /** @scrutinizer ignore-unused */ $simulate = false, $entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$message" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$message"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$simulate" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$simulate"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1174
    {
1175
        $status = self::__OK__;
1176
1177
        return array(
1178
            'value' => $data,
1179
        );
1180
    }
1181
1182
    /**
1183
     * Returns the keywords that this field supports for filtering. Note
1184
     * that no filter will do a simple 'straight' match on the value.
1185
     *
1186
     * @since Symphony 2.6.0
1187
     * @return array
1188
     */
1189
    public function fetchFilterableOperators()
1190
    {
1191
        return array(
1192
            array(
1193
                'title' => 'is',
1194
                'filter' => ' ',
1195
                'help' => __('Find values that are an exact match for the given string.')
1196
            ),
1197
            array(
1198
                'filter' => 'sql: NOT NULL',
1199
                'title' => 'is not empty',
1200
                'help' => __('Find entries with a non-empty value.')
1201
            ),
1202
            array(
1203
                'filter' => 'sql: NULL',
1204
                'title' => 'is empty',
1205
                'help' => __('Find entries with an empty value.')
1206
            ),
1207
            array(
1208
                'title' => 'contains',
1209
                'filter' => 'regexp: ',
1210
                'help' => __('Find values that match the given <a href="%s">MySQL regular expressions</a>.', array(
1211
                    'https://dev.mysql.com/doc/mysql/en/regexp.html'
1212
                ))
1213
            ),
1214
            array(
1215
                'title' => 'does not contain',
1216
                'filter' => 'not-regexp: ',
1217
                'help' => __('Find values that do not match the given <a href="%s">MySQL regular expressions</a>.', array(
1218
                    'https://dev.mysql.com/doc/mysql/en/regexp.html'
1219
                ))
1220
            ),
1221
        );
1222
    }
1223
1224
    /**
1225
     * Returns the types of filter suggestion this field supports. 
1226
     * The array may contain the following values:
1227
     *
1228
     * - `entry` for searching entries in the current section
1229
     * - `association` for searching entries in associated sections
1230
     * - `static` for searching static values
1231
     * - `date` for searching in a calendar
1232
     * - `parameters` for searching in parameters
1233
     *
1234
     * If the date type is set, only the calendar will be shown in the suggestion dropdown.
1235
     *
1236
     * @since Symphony 2.6.0
1237
     * @return array
1238
     */
1239
    public function fetchSuggestionTypes()
1240
    {
1241
        return array('entry');
1242
    }
1243
1244
    /**
1245
     * Display the default data source filter panel.
1246
     *
1247
     * @param XMLElement $wrapper
1248
     *    the input XMLElement to which the display of this will be appended.
1249
     * @param mixed $data (optional)
1250
     *    the input data. this defaults to null.
1251
     * @param null $errors
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $errors is correct as it would always require null to be passed?
Loading history...
1252
     *  the input error collection. this defaults to null.
1253
     * @param string $fieldnamePrefix
1254
     *  the prefix to apply to the display of this.
1255
     * @param string $fieldnamePostfix
1256
     *  the suffix to apply to the display of this.
1257
     * @throws InvalidArgumentException
1258
     */
1259
    public function displayDatasourceFilterPanel(XMLElement &$wrapper, $data = null, $errors = null, $fieldnamePrefix = null, $fieldnamePostfix = null)
0 ignored issues
show
Unused Code introduced by
The parameter $errors is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1259
    public function displayDatasourceFilterPanel(XMLElement &$wrapper, $data = null, /** @scrutinizer ignore-unused */ $errors = null, $fieldnamePrefix = null, $fieldnamePostfix = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$data" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$data"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$errors" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$errors"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$fieldnamePrefix" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$fieldnamePrefix"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$fieldnamePostfix" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$fieldnamePostfix"; expected 0 but found 1
Loading history...
1260
    {
1261
        $wrapper->appendChild(new XMLElement('header', '<h4>' . $this->get('label') . '</h4> <span>' . $this->name() . '</span>', array(
0 ignored issues
show
Bug introduced by
Are you sure $this->get('label') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1261
        $wrapper->appendChild(new XMLElement('header', '<h4>' . /** @scrutinizer ignore-type */ $this->get('label') . '</h4> <span>' . $this->name() . '</span>', array(
Loading history...
1262
            'data-name' => $this->get('label') . ' (' . $this->name() . ')'
1263
        )));
1264
1265
        $label = Widget::Label(__('Value'));
1266
        $input = Widget::Input('fields[filter]'.($fieldnamePrefix ? '['.$fieldnamePrefix.']' : '').'['.$this->get('id').']'.($fieldnamePostfix ? '['.$fieldnamePostfix.']' : ''), ($data ? General::sanitize($data) : null));
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
Bug introduced by
Are you sure $this->get('id') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1266
        $input = Widget::Input('fields[filter]'.($fieldnamePrefix ? '['.$fieldnamePrefix.']' : '').'['./** @scrutinizer ignore-type */ $this->get('id').']'.($fieldnamePostfix ? '['.$fieldnamePostfix.']' : ''), ($data ? General::sanitize($data) : null));
Loading history...
1267
        $input->setAttribute('autocomplete', 'off');
1268
        $input->setAttribute('data-search-types', 'parameters');
1269
        $input->setAttribute('data-trigger', '{$');
1270
        $label->appendChild($input);
1271
        $wrapper->appendChild($label);
1272
1273
        $this->displayFilteringOptions($wrapper);
1274
    }
1275
1276
    /**
1277
     * Inserts tags at the bottom of the filter panel
1278
     *
1279
     * @since Symphony 2.6.0
1280
     * @param XMLElement $wrapper
1281
     */
1282
    public function displayFilteringOptions(XMLElement &$wrapper)
1283
    {
1284
        // Add filter tags
1285
        $filterTags = new XMLElement('ul');
1286
        $filterTags->setAttribute('class', 'tags singular');
1287
        $filterTags->setAttribute('data-interactive', 'data-interactive');
1288
1289
        $filters = $this->fetchFilterableOperators();
1290
        foreach ($filters as $value) {
1291
            $item = new XMLElement('li', $value['title']);
1292
            $item->setAttribute('data-value', $value['filter']);
1293
1294
            if (isset($value['help'])) {
1295
                $item->setAttribute('data-help', General::sanitize($value['help']));
1296
            }
1297
1298
            $filterTags->appendChild($item);
1299
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1300
        $wrapper->appendChild($filterTags);
1301
1302
        $help = new XMLElement('p');
1303
        $help->setAttribute('class', 'help');
1304
        $first = array_shift($filters);
1305
        $help->setValue($first['help']);
1306
        $wrapper->appendChild($help);
1307
    }
1308
1309
    /**
1310
     * Default accessor for the includable elements of this field. This array
1311
     * will populate the `Datasource` included elements. Fields that have
1312
     * different modes will override this and add new items to the array.
1313
     * The Symphony convention is element_name : mode. Modes allow Fields to
1314
     * output different XML in datasources.
1315
     *
1316
     * @return array
1317
     *  the array of includable elements from this field.
1318
     */
1319
    public function fetchIncludableElements()
1320
    {
1321
        return array($this->get('element_name'));
1322
    }
1323
1324
    /**
1325
     * Test whether the input string is a regular expression, by searching
1326
     * for the prefix of `regexp:` or `not-regexp:` in the given `$string`.
1327
     *
1328
     * @param string $string
1329
     *  The string to test.
1330
     * @return boolean
1331
     *  true if the string is prefixed with `regexp:` or `not-regexp:`, false otherwise.
1332
     */
1333
    protected static function isFilterRegex($string)
1334
    {
1335
        if (preg_match('/^regexp:/i', $string) || preg_match('/^not-?regexp:/i', $string)) {
1336
            return true;
1337
        }
1338
    }
1339
1340
    /**
1341
     * Builds a basic REGEXP statement given a `$filter`. This function supports
1342
     * `regexp:` or `not-regexp:`. Users should keep in mind this function
1343
     * uses MySQL patterns, not the usual PHP patterns, the syntax between these
1344
     * flavours differs at times.
1345
     *
1346
     * @since Symphony 2.3
1347
     * @link https://dev.mysql.com/doc/refman/en/regexp.html
1348
     * @param string $filter
1349
     *  The full filter, eg. `regexp: ^[a-d]`
1350
     * @param array $columns
1351
     *  The array of columns that need the given `$filter` applied to. The conditions
1352
     *  will be added using `OR` when using `regexp:` but they will be added using `AND`
1353
     *  when using `not-regexp:`
1354
     * @param string $joins
1355
     *  A string containing any table joins for the current SQL fragment. By default
1356
     *  Datasources will always join to the `tbl_entries` table, which has an alias of
1357
     *  `e`. This parameter is passed by reference.
1358
     * @param string $where
1359
     *  A string containing the WHERE conditions for the current SQL fragment. This
1360
     *  is passed by reference and is expected to be used to add additional conditions
1361
     *  specific to this field
1362
     */
1363
    public function buildRegexSQL($filter, array $columns, &$joins, &$where)
1364
    {
1365
        $this->_key++;
1366
        $field_id = $this->get('id');
1367
        $filter = $this->cleanValue($filter);
1368
        $op = '';
1369
1370
        if (preg_match('/^regexp:\s*/i', $filter)) {
1371
            $pattern = preg_replace('/^regexp:\s*/i', null, $filter);
1372
            $regex = 'REGEXP';
1373
            $op = 'OR';
1374
        } elseif (preg_match('/^not-?regexp:\s*/i', $filter)) {
1375
            $pattern = preg_replace('/^not-?regexp:\s*/i', null, $filter);
1376
            $regex = 'NOT REGEXP';
1377
            $op = 'AND';
1378
        } else {
1379
            throw new Exception("Filter `$filter` is not a Regexp filter");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $filter instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1380
        }
1381
1382
        if (strlen($pattern) == 0) {
1383
            return;
1384
        }
1385
1386
        $joins .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1387
            LEFT JOIN
1388
                `tbl_entries_data_{$field_id}` AS t{$field_id}_{$this->_key}
1389
                ON (e.id = t{$field_id}_{$this->_key}.entry_id)
1390
        ";
1391
1392
        $where .= "AND ( ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal AND ( does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1393
1394
        foreach ($columns as $key => $col) {
1395
            $modifier = ($key === 0) ? '' : $op;
1396
1397
            $where .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $modifier instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $col instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $regex instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $pattern instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1398
                {$modifier} t{$field_id}_{$this->_key}.{$col} {$regex} '{$pattern}'
1399
            ";
1400
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1401
        $where .= ")";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal ) does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1402
    }
1403
1404
    /**
1405
     * Test whether the input string is a NULL/NOT NULL SQL clause, by searching
1406
     * for the prefix of `sql:` in the given `$string`, followed by `(NOT )? NULL`
1407
     *
1408
     * @since Symphony 2.7.0
1409
     * @param string $string
1410
     *  The string to test.
1411
     * @return boolean
1412
     *  true if the string is prefixed with `sql:`, false otherwise.
1413
     */
1414
    protected static function isFilterSQL($string)
1415
    {
1416
        if (preg_match('/^sql:\s*(NOT )?NULL$/i', $string)) {
1417
            return true;
1418
        }
1419
    }
1420
1421
    /**
1422
     * Builds a basic NULL/NOT NULL SQL statement given a `$filter`.
1423
     *  This function supports `sql: NULL` or `sql: NOT NULL`.
1424
     *
1425
     * @since Symphony 2.7.0
1426
     * @link https://dev.mysql.com/doc/refman/en/regexp.html
1427
     * @param string $filter
1428
     *  The full filter, eg. `sql: NULL`
1429
     * @param array $columns
1430
     *  The array of columns that need the given `$filter` applied to. The conditions
1431
     *  will be added using `OR`.
1432
     * @param string $joins
1433
     *  A string containing any table joins for the current SQL fragment. By default
1434
     *  Datasources will always join to the `tbl_entries` table, which has an alias of
1435
     *  `e`. This parameter is passed by reference.
1436
     * @param string $where
1437
     *  A string containing the WHERE conditions for the current SQL fragment. This
1438
     *  is passed by reference and is expected to be used to add additional conditions
1439
     *  specific to this field
1440
     */
1441
    public function buildFilterSQL($filter, array $columns, &$joins, &$where)
1442
    {
1443
        $this->_key++;
1444
        $field_id = $this->get('id');
1445
        $filter = $this->cleanValue($filter);
1446
        $pattern = '';
1447
1448
        if (preg_match('/^sql:\s*NOT NULL$/i', $filter)) {
1449
            $pattern = 'NOT NULL';
1450
        } elseif (preg_match('/^sql:\s*NULL$/i', $filter)) {
1451
            $pattern = 'NULL';
1452
        } else {
1453
            // No match, return
1454
            return;
1455
        }
1456
1457
        $joins .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1458
            LEFT JOIN
1459
                `tbl_entries_data_{$field_id}` AS t{$field_id}_{$this->_key}
1460
                ON (e.id = t{$field_id}_{$this->_key}.entry_id)
1461
        ";
1462
1463
        $where .= "AND ( ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal AND ( does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1464
1465
        foreach ($columns as $key => $col) {
1466
            $modifier = ($key === 0) ? '' : 'OR';
1467
1468
            $where .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $modifier instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $col instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $pattern instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1469
                {$modifier} t{$field_id}_{$this->_key}.{$col} IS {$pattern}
1470
            ";
1471
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1472
        $where .= ")";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal ) does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1473
    }
1474
1475
    /**
1476
     * Construct the SQL statement fragments to use to retrieve the data of this
1477
     * field when utilized as a data source.
1478
     *
1479
     * @see toolkit.Datasource#__determineFilterType
1480
     * @param array $data
1481
     *  An array of the data that contains the values for the filter as specified
1482
     *  in the datasource editor. The value that is entered in the datasource editor
1483
     *  is made into an array by using + or , to separate the filter.
1484
     * @param string $joins
1485
     *  A string containing any table joins for the current SQL fragment. By default
1486
     *  Datasources will always join to the `tbl_entries` table, which has an alias of
1487
     *  `e`. This parameter is passed by reference.
1488
     * @param string $where
1489
     *  A string containing the WHERE conditions for the current SQL fragment. This
1490
     *  is passed by reference and is expected to be used to add additional conditions
1491
     *  specific to this field
1492
     * @param boolean $andOperation (optional)
1493
     *  This parameter defines whether the `$data` provided should be treated as
1494
     *  AND or OR conditions. This parameter will be set to true if $data used a
1495
     *  + to separate the values, otherwise it will be false. It is false by default.
1496
     * @return boolean
1497
     *  true if the construction of the SQL was successful, false otherwise.
1498
     */
1499
    public function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation = false)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$andOperation" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$andOperation"; expected 0 but found 1
Loading history...
1500
    {
1501
        $field_id = $this->get('id');
1502
1503
        // REGEX filtering is a special case, and will only work on the first item
1504
        // in the array. You cannot specify multiple filters when REGEX is involved.
1505
        if (self::isFilterRegex($data[0])) {
1506
            $this->buildRegexSQL($data[0], array('value'), $joins, $where);
1507
1508
            // SQL filtering: allows for NULL/NOT NULL statements
1509
        } elseif (self::isFilterSQL($data[0])) {
1510
            $this->buildFilterSQL($data[0], array('value'), $joins, $where);
1511
1512
            // AND operation, iterates over `$data` and uses a new JOIN for
1513
            // every item.
1514
        } elseif ($andOperation) {
1515
            foreach ($data as $value) {
1516
                $this->_key++;
1517
                $value = $this->cleanValue($value);
1518
                $joins .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1519
                    LEFT JOIN
1520
                        `tbl_entries_data_{$field_id}` AS t{$field_id}_{$this->_key}
1521
                        ON (e.id = t{$field_id}_{$this->_key}.entry_id)
1522
                ";
1523
                $where .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $value instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1524
                    AND t{$field_id}_{$this->_key}.value = '{$value}'
1525
                ";
1526
            }
1527
1528
            // Default logic, this will use a single JOIN statement and collapse
1529
            // `$data` into a string to be used in conjunction with IN
1530
        } else {
1531
            foreach ($data as &$value) {
1532
                $value = $this->cleanValue($value);
1533
            }
1534
1535
            $this->_key++;
1536
            $data = implode("', '", $data);
1537
            $joins .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1538
                LEFT JOIN
1539
                    `tbl_entries_data_{$field_id}` AS t{$field_id}_{$this->_key}
1540
                    ON (e.id = t{$field_id}_{$this->_key}.entry_id)
1541
            ";
1542
            $where .= "
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $field_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $this instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $data instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1543
                AND t{$field_id}_{$this->_key}.value IN ('{$data}')
1544
            ";
1545
        }
1546
1547
        return true;
1548
    }
1549
1550
    /**
1551
     * Determine if the requested $order is random or not.
1552
     *
1553
     * @since Symphony 2.7.0
1554
     * @param string $order
1555
     *  the sorting direction.
1556
     * @return boolean
1557
     *  true if the $order is either 'rand' or 'random'
1558
     */
1559
    protected function isRandomOrder($order)
1560
    {
1561
        return in_array(strtolower($order), array('random', 'rand'));
1562
    }
1563
1564
    /**
1565
     * Build the SQL command to append to the default query to enable
1566
     * sorting of this field. By default this will sort the results by
1567
     * the entry id in ascending order.
1568
     *
1569
     * Extension developers should always implement both `buildSortingSQL()`
1570
     * and `buildSortingSelectSQL()`.
1571
     *
1572
     * @uses Field::isRandomOrder()
1573
     * @see Field::buildSortingSelectSQL()
1574
     * @param string $joins
1575
     *  the join element of the query to append the custom join sql to.
1576
     * @param string $where
1577
     *  the where condition of the query to append to the existing where clause.
1578
     * @param string $sort
1579
     *  the existing sort component of the sql query to append the custom
1580
     *  sort sql code to.
1581
     * @param string $order (optional)
1582
     *  an optional sorting direction. this defaults to ascending. if this
1583
     *  is declared either 'random' or 'rand' then a random sort is applied.
1584
     */
1585
    public function buildSortingSQL(&$joins, &$where, &$sort, $order = 'ASC')
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$order" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$order"; expected 0 but found 1
Loading history...
1586
    {
1587
        if ($this->isRandomOrder($order)) {
1588
            $sort = 'ORDER BY RAND()';
1589
        } else {
1590
            $joins .= "LEFT OUTER JOIN `tbl_entries_data_".$this->get('id')."` AS `ed` ON (`e`.`id` = `ed`.`entry_id`) ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal LEFT OUTER JOIN `tbl_entries_data_ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal ` AS `ed` ON (`e`.`id` = `ed`.`entry_id`) does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Bug introduced by
Are you sure $this->get('id') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1590
            $joins .= "LEFT OUTER JOIN `tbl_entries_data_"./** @scrutinizer ignore-type */ $this->get('id')."` AS `ed` ON (`e`.`id` = `ed`.`entry_id`) ";
Loading history...
1591
            $sort = sprintf('ORDER BY `ed`.`value` %1$s, `e`.`id` %1$s', $order);
1592
        }
1593
    }
1594
1595
    /**
1596
     * Build the needed SQL clause command to make `buildSortingSQL()` work on
1597
     * MySQL 5.7 in strict mode, which requires all columns in the ORDER BY
1598
     * clause to be included in the SELECT's projection.
1599
     *
1600
     * If no new projection is needed (like if the order is made via a sub-query),
1601
     * simply return null.
1602
     *
1603
     * For backward compatibility, this method checks if the sort expression
1604
     * contains `ed`.`value`. This check will be removed in Symphony 3.0.0.
1605
     *
1606
     * Extension developers should make their Fields implement
1607
     * `buildSortingSelectSQL()` when overriding `buildSortingSQL()`.
1608
     *
1609
     * @since Symphony 2.7.0
1610
     * @uses Field::isRandomOrder()
1611
     * @see Field::buildSortingSQL()
1612
     * @param string $sort
1613
     *  the existing sort component of the sql query, after it has been passed
1614
     *  to `buildSortingSQL()`
1615
     * @param string $order (optional)
1616
     *  an optional sorting direction. this defaults to ascending. Should be the
1617
     *  same value that was passed to `buildSortingSQL()`
1618
     * @return string
1619
     *  an optional select clause to append to the generated SQL query.
1620
     *  This is needed when sorting on a column that is not part of the projection.
1621
     */
1622
    public function buildSortingSelectSQL($sort, $order = 'ASC')
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$order" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$order"; expected 0 but found 1
Loading history...
1623
    {
1624
        if ($this->isRandomOrder($order)) {
1625
            return null;
1626
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1627
        // @deprecated This check should be removed in Symphony 3.0.0
1628
        if (strpos($sort, '`ed`.`value`') === false) {
1629
            return null;
1630
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1631
        return '`ed`.`value`';
1632
    }
1633
1634
    /**
1635
     * Default implementation of record grouping. This default implementation
1636
     * will throw an `Exception`. Thus, clients must overload this method
1637
     * for grouping to be successful.
1638
     *
1639
     * @throws Exception
1640
     * @param array $records
1641
     *  the records to group.
1642
     */
1643
    public function groupRecords($records)
0 ignored issues
show
Unused Code introduced by
The parameter $records is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1643
    public function groupRecords(/** @scrutinizer ignore-unused */ $records)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1644
    {
1645
        throw new Exception(
1646
            __('Data source output grouping is not supported by the %s field', array('<code>' . $this->get('label') . '</code>'))
0 ignored issues
show
Bug introduced by
Are you sure $this->get('label') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1646
            __('Data source output grouping is not supported by the %s field', array('<code>' . /** @scrutinizer ignore-type */ $this->get('label') . '</code>'))
Loading history...
1647
        );
1648
    }
1649
1650
    /**
1651
     * Function to format this field if it chosen in a data source to be
1652
     * output as a parameter in the XML.
1653
     *
1654
     * Since Symphony 2.5.0, it will defaults to `prepareReadableValue` return value.
1655
     *
1656
     * @param array $data
1657
     *  The data for this field from it's `tbl_entry_data_{id}` table
1658
     * @param integer $entry_id
1659
     *  The optional id of this field entry instance
1660
     * @return string|array
1661
     *  The formatted value to be used as the parameter. Note that this can be
1662
     *  an array or a string. When returning multiple values use array, otherwise
1663
     *  use string.
1664
     */
1665
    public function getParameterPoolValue(array $data, $entry_id = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1666
    {
1667
        return $this->prepareReadableValue($data, $entry_id);
1668
    }
1669
1670
    /**
1671
     * Append the formatted XML output of this field as utilized as a data source.
1672
     *
1673
     * Since Symphony 2.5.0, it will defaults to `prepareReadableValue` return value.
1674
     *
1675
     * @param XMLElement $wrapper
1676
     *  the XML element to append the XML representation of this to.
1677
     * @param array $data
1678
     *  the current set of values for this field. the values are structured as
1679
     *  for displayPublishPanel.
1680
     * @param boolean $encode (optional)
1681
     *  flag as to whether this should be html encoded prior to output. this
1682
     *  defaults to false.
1683
     * @param string $mode
1684
     *   A field can provide ways to output this field's data. For instance a mode
1685
     *  could be 'items' or 'full' and then the function would display the data
1686
     *  in a different way depending on what was selected in the datasource
1687
     *  included elements.
1688
     * @param integer $entry_id (optional)
1689
     *  the identifier of this field entry instance. defaults to null.
1690
     */
1691
    public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = null, $entry_id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $mode is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1691
    public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, /** @scrutinizer ignore-unused */ $mode = null, $entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$encode" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$encode"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$mode" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$mode"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$entry_id"; expected 0 but found 1
Loading history...
1692
    {
1693
        $wrapper->appendChild(new XMLElement($this->get('element_name'), ($encode ?
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
Bug introduced by
It seems like $this->get('element_name') can also be of type array; however, parameter $name of XMLElement::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1693
        $wrapper->appendChild(new XMLElement(/** @scrutinizer ignore-type */ $this->get('element_name'), ($encode ?
Loading history...
1694
                              General::sanitize($this->prepareReadableValue($data, $entry_id)) :
1695
                              $this->prepareReadableValue($data, $entry_id))));
1696
    }
1697
1698
    /**
1699
     * The default method for constructing the example form markup containing this
1700
     * field when utilized as part of an event. This displays in the event documentation
1701
     * and serves as a basic guide for how markup should be constructed on the
1702
     * `Frontend` to save this field
1703
     *
1704
     * @throws InvalidArgumentException
1705
     * @return XMLElement
1706
     *  a label widget containing the formatted field element name of this.
1707
     */
1708
    public function getExampleFormMarkup()
1709
    {
1710
        $label = Widget::Label($this->get('label'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('label') can also be of type array; however, parameter $name of Widget::Label() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1710
        $label = Widget::Label(/** @scrutinizer ignore-type */ $this->get('label'));
Loading history...
1711
        $label->appendChild(Widget::Input('fields['.$this->get('element_name').']'));
0 ignored issues
show
Bug introduced by
Are you sure $this->get('element_name') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1711
        $label->appendChild(Widget::Input('fields['./** @scrutinizer ignore-type */ $this->get('element_name').']'));
Loading history...
1712
1713
        return $label;
1714
    }
1715
1716
    /**
1717
     * Commit the settings of this field from the section editor to
1718
     * create an instance of this field in a section.
1719
     *
1720
     * @return boolean
1721
     *  true if the commit was successful, false otherwise.
1722
     */
1723
    public function commit()
1724
    {
1725
        $fields = array();
1726
1727
        $fields['label'] = General::sanitize($this->get('label'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('label') can also be of type array; however, parameter $source of General::sanitize() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1727
        $fields['label'] = General::sanitize(/** @scrutinizer ignore-type */ $this->get('label'));
Loading history...
1728
        $fields['element_name'] = ($this->get('element_name') ? $this->get('element_name') : Lang::createHandle($this->get('label')));
0 ignored issues
show
Bug introduced by
It seems like $this->get('label') can also be of type array; however, parameter $string of Lang::createHandle() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1728
        $fields['element_name'] = ($this->get('element_name') ? $this->get('element_name') : Lang::createHandle(/** @scrutinizer ignore-type */ $this->get('label')));
Loading history...
1729
        $fields['parent_section'] = $this->get('parent_section');
1730
        $fields['location'] = $this->get('location');
1731
        $fields['required'] = $this->get('required');
1732
        $fields['type'] = $this->_handle;
1733
        $fields['show_column'] = $this->get('show_column');
1734
        $fields['sortorder'] = (string)$this->get('sortorder');
1735
1736
        if ($id = $this->get('id')) {
1737
            return FieldManager::edit($id, $fields);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type array; however, parameter $id of FieldManager::edit() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1737
            return FieldManager::edit(/** @scrutinizer ignore-type */ $id, $fields);
Loading history...
1738
        } elseif ($id = FieldManager::add($fields)) {
1739
            $this->set('id', $id);
1740
            if ($this->requiresTable()) {
1741
                return $this->createTable();
1742
            }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1743
            return true;
1744
        }
1745
1746
        return false;
1747
    }
1748
1749
    /**
1750
     * The default field table construction method. This constructs the bare
1751
     * minimum set of columns for a valid field table. Subclasses are expected
1752
     * to overload this method to create a table structure that contains
1753
     * additional columns to store the specific data created by the field.
1754
     *
1755
     * @throws DatabaseException
1756
     * @see Field::requiresTable()
1757
     * @return boolean
1758
     */
1759
    public function createTable()
1760
    {
1761
        return Symphony::Database()->query(
1762
            "CREATE TABLE IF NOT EXISTS `tbl_entries_data_" . $this->get('id') . "` (
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal CREATE TABLE IF NOT EXISTS `tbl_entries_data_ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal ` (\n `id` ...OLLATE=utf8_unicode_ci; does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Bug introduced by
Are you sure $this->get('id') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1762
            "CREATE TABLE IF NOT EXISTS `tbl_entries_data_" . /** @scrutinizer ignore-type */ $this->get('id') . "` (
Loading history...
1763
              `id` int(11) unsigned NOT null auto_increment,
1764
              `entry_id` int(11) unsigned NOT null,
1765
              `value` varchar(255) default null,
1766
              PRIMARY KEY  (`id`),
1767
              KEY `entry_id` (`entry_id`),
1768
              KEY `value` (`value`)
1769
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"
1770
        );
1771
    }
1772
1773
    /**
1774
     * Tells Symphony that this field needs a table in order to store
1775
     * data for each of its entries. Used when adding/deleting this field in a section
1776
     * or entries are edited/added, data as a performance optimization.
1777
     * It defaults to true, which force table creation.
1778
     *
1779
     * Developers are encouraged to update their null create table implementation
1780
     * with this method.
1781
     *
1782
     * @since Symphony 2.7.0
1783
     * @see Field::createTable()
1784
     * @return boolean
1785
     *  true if Symphony should call `createTable()`
1786
     */
1787
    public function requiresTable()
1788
    {
1789
        return true;
1790
    }
1791
1792
    /**
1793
     * Checks that we are working with a valid field handle and
1794
     * that the setting table exists.
1795
     *
1796
     * @since Symphony 2.7.0
1797
     * @return boolean
1798
     *   true if the table exists, false otherwise
1799
     */
1800
    public function tableExists()
1801
    {
1802
        if (!$this->_handle) {
1803
            return false;
1804
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1805
        return Symphony::Database()->tableExists('tbl_fields_' . $this->_handle);
1806
    }
1807
1808
    /**
1809
     * Checks that we are working with a valid field handle and field id, and
1810
     * checks that the field record exists in the settings table.
1811
     *
1812
     * @since Symphony 2.7.1 It does check if the settings table only contains
1813
     *   default columns and assume those fields do not require a record in the settings table.
1814
     *   When this situation is detected the field is considered as valid even if no records were
1815
     *   found in the settings table.
1816
     *
1817
     * @since Symphony 2.7.0
1818
     * @see Field::tableExists()
1819
     * @return boolean
1820
     *   true if the field id exists in the table, false otherwise
1821
     */
1822
    public function exists()
1823
    {
1824
        if (!$this->get('id') || !$this->_handle) {
1825
            return false;
1826
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1827
        $row = Symphony::Database()->fetch(sprintf(
1828
            'SELECT `id` FROM `tbl_fields_%s` WHERE `field_id` = %d',
1829
            $this->_handle,
1830
            General::intval($this->get('id'))
1831
        ));
1832
        if (empty($row)) {
1833
            // Some fields do not create any records in their settings table because they do not
1834
            // implement a proper `Field::commit()` method.
1835
            // The base implementation of the commit function only deals with the "core"
1836
            // `tbl_fields` table.
1837
            // The problem with this approach is that it can lead to data corruption when
1838
            // saving a field that got deleted by another user.
1839
            // The only way a field can live without a commit method is if it does not store any
1840
            // settings at all.
1841
            // But current version of Symphony assume that the `tbl_fields_$handle` table exists
1842
            // with at least a `id` and `field_id` column, so field are required to at least create
1843
            // the table to make their field work without SQL errors from the core.
1844
            $columns = Symphony::Database()->fetchCol('Field', sprintf(
1845
                'DESC `tbl_fields_%s`',
1846
                $this->_handle
1847
            ));
1848
            // The table only has the two required columns, tolerate the missing record
1849
            $isDefault = count($columns) === 2 &&
1850
                in_array('id', $columns) &&
1851
                in_array('field_id', $columns);
1852
            if ($isDefault) {
1853
                Symphony::Log()->pushDeprecateWarningToLog($this->_handle, get_class($this), array(
1854
                    'message-format' => __('The field `%1$s` does not create settings records in the `tbl_fields_%1$s`.'),
1855
                    'alternative-format' => __('Please implement the commit function in class `%s`.'),
1856
                    'removal-format' => __('The compatibility check will will be removed in Symphony %s.'),
1857
                    'removal-version' => '4.0.0',
1858
                ));
1859
            }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1860
            return $isDefault;
1861
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
1862
        return true;
1863
    }
1864
1865
    /**
1866
     * Remove the entry data of this field from the database.
1867
     *
1868
     * @param integer|array $entry_id
1869
     *    the ID of the entry, or an array of entry ID's to delete.
1870
     * @param array $data (optional)
1871
     *    The entry data provided for fields to do additional cleanup
1872
     *  This is an optional argument and defaults to null.
1873
     * @throws DatabaseException
1874
     * @return boolean
1875
     *    Returns true after the cleanup has been completed
1876
     */
1877
    public function entryDataCleanup($entry_id, $data = null)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$data" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$data"; expected 0 but found 1
Loading history...
1878
    {
1879
        $where = is_array($entry_id)
1880
            ? " `entry_id` IN (" . implode(',', $entry_id) . ") "
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
Coding Style Comprehensibility introduced by
The string literal `entry_id` IN ( does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal ) does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1881
            : " `entry_id` = '$entry_id' ";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $entry_id instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
1882
1883
        Symphony::Database()->delete('tbl_entries_data_' . $this->get('id'), $where);
0 ignored issues
show
Bug introduced by
Are you sure $this->get('id') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1883
        Symphony::Database()->delete('tbl_entries_data_' . /** @scrutinizer ignore-type */ $this->get('id'), $where);
Loading history...
1884
1885
        return true;
1886
    }
1887
1888
    /**
1889
     * Accessor to the associated entry search value for this field
1890
     * instance. This default implementation simply returns `$data`
1891
     *
1892
     * @param array $data
1893
     *  the data from which to construct the associated search entry value, this is usually
1894
     *  Entry with the `$parent_entry_id` value's data.
1895
     * @param integer $field_id (optional)
1896
     *  the ID of the field that is the parent in the relationship
1897
     * @param integer $parent_entry_id (optional)
1898
     *  the ID of the entry from the parent section in the relationship
1899
     * @return array|string
1900
     *  Defaults to returning `$data`, but overriding implementation should return
1901
     *  a string
1902
     */
1903
    public function fetchAssociatedEntrySearchValue($data, $field_id = null, $parent_entry_id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $parent_entry_id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1903
    public function fetchAssociatedEntrySearchValue($data, $field_id = null, /** @scrutinizer ignore-unused */ $parent_entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $field_id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1903
    public function fetchAssociatedEntrySearchValue($data, /** @scrutinizer ignore-unused */ $field_id = null, $parent_entry_id = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Incorrect spacing between argument "$field_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$field_id"; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between argument "$parent_entry_id" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$parent_entry_id"; expected 0 but found 1
Loading history...
1904
    {
1905
        return $data;
1906
    }
1907
1908
    /**
1909
     * Fetch the count of the associated entries given a `$value`.
1910
     *
1911
     * @see toolkit.Field#fetchAssociatedEntrySearchValue()
1912
     * @param mixed $value
1913
     *  the value to find the associated entry count for, this usually comes from
1914
     *  the `fetchAssociatedEntrySearchValue` function.
1915
     * @return void|integer
1916
     *  this default implementation returns void. overriding implementations should
1917
     *  return an integer.
1918
     */
1919
    public function fetchAssociatedEntryCount($value)
1920
    {
1921
    }
1922
1923
    /**
1924
     * Fetch the Entry ID's associated with this field instance given a `$value`,
1925
     * where the `$value` can be anything. This function is unused by Symphony core
1926
     * but should be implemented by Fields that maintain relationships.
1927
     *
1928
     * @param mixed $value
1929
     *  the value to find the associated entry ID's for.
1930
     * @return void|array
1931
     *  this default implementation returns void. overriding implementations should
1932
     *  return an array of the associated entry ids.
1933
     * @deprecated Since Symphony 2.5.0 this method is not called anymore in the core. Please use
1934
     *  `Field::findRelatedEntries` and `Field::findParentRelatedEntries` instead. This method
1935
     *  will be removed in Symphony 3.0
1936
     */
1937
    public function fetchAssociatedEntryIDs($value)
1938
    {
1939
        if (Symphony::Log()) {
1940
            Symphony::Log()->pushDeprecateWarningToLog('Field::fetchAssociatedEntryIDs()', 'Field::findRelatedEntries()` or Field::findParentRelatedEntries()`');
1941
        }
1942
    }
1943
1944
    /**
1945
     * Find related entries from a linking field's data table. Default implementation uses
1946
     * column names `entry_id` and `relation_id` as with the Select Box Link
1947
     *
1948
     * @since Symphony 2.5.0
1949
     *
1950
     * @param  integer $entry_id
1951
     * @param  integer $parent_field_id
1952
     * @return array
1953
     */
1954
    public function findRelatedEntries($entry_id, $parent_field_id)
0 ignored issues
show
Unused Code introduced by
The parameter $parent_field_id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1954
    public function findRelatedEntries($entry_id, /** @scrutinizer ignore-unused */ $parent_field_id)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1955
    {
1956
        try {
1957
            $ids = Symphony::Database()->fetchCol('entry_id', sprintf("
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal \n SELECT... NOT NULL\n does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1958
                SELECT `entry_id`
1959
                FROM `tbl_entries_data_%d`
1960
                WHERE `relation_id` = %d
1961
                AND `entry_id` IS NOT NULL
1962
            ", $this->get('id'), $entry_id));
0 ignored issues
show
Bug introduced by
It seems like $this->get('id') can also be of type array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1962
            ", /** @scrutinizer ignore-type */ $this->get('id'), $entry_id));
Loading history...
1963
        } catch (Exception $e) {
1964
            return array();
1965
        }
1966
1967
        return $ids;
1968
    }
1969
1970
    /**
1971
     * Find related entries for the current field. Default implementation uses
1972
     * column names `entry_id` and `relation_id` as with the Select Box Link
1973
     *
1974
     * @since Symphony 2.5.0
1975
     *
1976
     * @param  integer $parent_field_id
1977
     * @param  integer $entry_id
1978
     * @return array
1979
     */
1980
    public function findParentRelatedEntries($parent_field_id, $entry_id)
0 ignored issues
show
Unused Code introduced by
The parameter $parent_field_id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1980
    public function findParentRelatedEntries(/** @scrutinizer ignore-unused */ $parent_field_id, $entry_id)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1981
    {
1982
        try {
1983
            $ids = Symphony::Database()->fetchCol('relation_id', sprintf("
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal \n SELECT... NOT NULL\n does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1984
                SELECT `relation_id`
1985
                FROM `tbl_entries_data_%d`
1986
                WHERE `entry_id` = %d
1987
                AND `relation_id` IS NOT NULL
1988
            ", $this->get('id') , $entry_id));
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
Bug introduced by
It seems like $this->get('id') can also be of type array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1988
            ", /** @scrutinizer ignore-type */ $this->get('id') , $entry_id));
Loading history...
1989
        } catch (Exception $e) {
1990
            return array();
1991
        }
1992
1993
        return $ids;
1994
    }
1995
}
1996