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.
Completed
Pull Request — 2.6.x (#2509)
by Nicolas
04:59
created

Entry::checkPostData()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 49
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
eloc 21
c 1
b 0
f 1
nc 4
nop 3
dl 0
loc 49
rs 6.7272
1
<?php
2
3
/**
4
 * @package toolkit
5
 */
6
/**
7
 * An entry is a combination of data that is stored in several Fields
8
 * typically contained in one Section. Entries are created by the
9
 * Authors of Symphony and hold all the content for the website.
10
 * Entries are typically created from the Symphony backend, but
11
 * can also be created using Events from the Frontend.
12
 */
13
14
class Entry
15
{
16
    /**
17
     * The constant for when an Entry is ok, that is, no errors have
18
     * been raised by any of it's Fields.
19
     * @var integer
20
     */
21
    const __ENTRY_OK__ = 0;
22
23
    /**
24
     * The constant for an Entry if there is an error is raised by any of
25
     * it's Fields.
26
     * @var integer
27
     */
28
    const __ENTRY_FIELD_ERROR__ = 100;
29
30
    /**
31
     * An associative array of basic metadata/settings for this Entry
32
     * @var array
33
     */
34
    protected $_fields = array();
35
36
    /**
37
     * An associative array of the data for each of the Fields that make up
38
     * this Entry. The key is the Field ID, and the value is typically an array
39
     * @var array
40
     */
41
    protected $_data = array();
42
43
    /**
44
     * An ISO 8601 representation of when this Entry was created
45
     * eg. `2004-02-12T15:19:21+00:00`
46
     * @deprecated Since Symphony 2.3.1, use $entry->get('creation_date') instead. This
47
     *  variable will be removed in Symphony 3.0
48
     * @var string
49
     */
50
    public $creationDate = null;
51
52
    /**
53
     * Entries have some basic metadata settings such as the Entry ID, the Author ID
54
     * who created it and the Section that the Entry sits in. This function will set a
55
     * setting to a value overwriting any existing value for this setting
56
     *
57
     * @param string $setting
58
     *  the setting key.
59
     * @param mixed $value
60
     *  the value of the setting.
61
     */
62
    public function set($setting, $value)
63
    {
64
        $this->_fields[$setting] = $value;
65
    }
66
67
    /**
68
     * Accessor to the a setting by name. If no setting is provided all the
69
     * settings of this Entry instance are returned.
70
     *
71
     * @param string $setting (optional)
72
     *  the name of the setting to access the value for. This is optional and
73
     *  defaults to null in which case all settings are returned.
74
     * @return null|mixed|array
75
     *  the value of the setting if there is one, all settings if the input setting
76
     * was omitted or null if the setting was supplied but there is no value
77
     * for that setting.
78
     */
79 View Code Duplication
    public function get($setting = null)
80
    {
81
        if (is_null($setting)) {
82
            return $this->_fields;
83
        }
84
85
        if (!isset($this->_fields[$setting])) {
86
            return null;
87
        }
88
89
        return $this->_fields[$setting];
90
    }
91
92
    /**
93
     * Creates the initial entry row in tbl_entries and returns the resulting
94
     * Entry ID using `getInsertID()`.
95
     *
96
     * @see toolkit.MySQL#getInsertID()
97
     * @throws DatabaseException
98
     * @return integer
99
     */
100
    public function assignEntryId()
101
    {
102
        $fields = $this->get();
103
        $fields['creation_date'] = $fields['modification_date'] = DateTimeObj::get('Y-m-d H:i:s');
104
        $fields['creation_date_gmt'] = $fields['modification_date_gmt'] = DateTimeObj::getGMT('Y-m-d H:i:s');
105
        $fields['author_id'] = is_null($this->get('author_id')) ? '1' : $this->get('author_id'); // Author_id cannot be null
106
107
        Symphony::Database()->insert($fields, 'tbl_entries');
108
109
        if (!$entry_id = Symphony::Database()->getInsertID()) {
110
            return null;
111
        }
112
113
        $this->set('id', $entry_id);
114
115
        return $entry_id;
116
    }
117
118
    /**
119
     * Set the data for a Field in this Entry, given the Field ID and it's data
120
     *
121
     * @param integer $field_id
122
     *  The ID of the Field this data is for
123
     * @param mixed $data
124
     *  Often an array
125
     */
126
    public function setData($field_id, $data)
127
    {
128
        $this->_data[$field_id] = $data;
129
    }
130
131
    /**
132
     * When an entry is saved from a form (either Frontend/Backend) this
133
     * function will find all the fields in this set and loop over them, setting
134
     * the data to each of the fields for processing. If any errors occur during
135
     * this, `_ENTRY_FIELD_ERROR_` is returned, and an array is available with
136
     * the errors.
137
     *
138
     * @param array $data
139
     *  An associative array of the data for this entry where they key is the
140
     *  Field's handle for this Section and the value is the data from the form
141
     * @param array $errors
142
     *  An associative array of errors, by reference. The key is the `field_id`, the value
143
     *  is the message text. Defaults to an empty array
144
     * @param boolean $simulate
145
     *  If $simulate is given as true, a dry run of this function will occur, where
146
     *  regardless of errors, an Entry will not be saved in the database. Defaults to
147
     *  false
148
     * @param boolean $ignore_missing_fields
149
     *  This parameter allows Entries to be updated, rather than replaced. This is
150
     *  useful if the input form only contains a couple of the fields for this Entry.
151
     *  Defaults to false, which will set Fields to their default values if they are not
152
     *  provided in the $data
153
     * @throws DatabaseException
154
     * @throws Exception
155
     * @return integer
156
     *  Either `Entry::__ENTRY_OK__` or `Entry::__ENTRY_FIELD_ERROR__`
157
     */
158
    public function setDataFromPost($data, &$errors = null, $simulate = false, $ignore_missing_fields = false)
159
    {
160
        $status = Entry::__ENTRY_OK__;
161
162
        // Entry has no ID, create it:
163
        if (!$this->get('id') && $simulate === false) {
164
            $entry_id = $this->assignEntryId();
165
166
            if (is_null($entry_id)) {
167
                return Entry::__ENTRY_FIELD_ERROR__;
168
            }
169
        }
170
171
        $section = SectionManager::fetch($this->get('section_id'));
172
        $schema = $section->fetchFieldsSchema();
173
174
        foreach ($schema as $info) {
175
            $message = null;
176
            $field = FieldManager::fetch($info['id']);
177
178
            if ($ignore_missing_fields && !isset($data[$field->get('element_name')])) {
0 ignored issues
show
Bug introduced by
The method get cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
179
                continue;
180
            }
181
182
            $result = $field->processRawFieldData((isset($data[$info['element_name']]) ? $data[$info['element_name']] : null), $s, $message, $simulate, $this->get('id'));
0 ignored issues
show
Bug introduced by
The variable $s does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The method processRawFieldData cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
183
184
            if ($s !== Field::__OK__) {
185
                $status = Entry::__ENTRY_FIELD_ERROR__;
186
                $errors[$info['id']] = $message;
187
            }
188
189
            $this->setData($info['id'], $result);
190
        }
191
192
        // Failed to create entry, cleanup
193
        if ($status !== Entry::__ENTRY_OK__ && !is_null($entry_id)) {
194
            Symphony::Database()->delete('tbl_entries', sprintf(" `id` = %d ", $entry_id));
0 ignored issues
show
Bug introduced by
The variable $entry_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
195
        }
196
197
        return $status;
198
    }
199
200
    /**
201
     * Accessor function to return data from this Entry for a particular
202
     * field. Optional parameter to return this data as an object instead
203
     * of an array. If a Field is not provided, an associative array of all data
204
     * assigned to this Entry will be returned.
205
     *
206
     * @param integer $field_id
207
     *  The ID of the Field whose data you want
208
     * @param boolean $asObject
209
     *  If true, the data will be returned as an object instead of an
210
     *  array. Defaults to false. Note that if a `$field_id` is not provided
211
     *  the result will always be an array.
212
     * @return array|object
213
     *  Depending on the value of `$asObject`, return the field's data
214
     *  as either an array or an object. If no data exists, null will be
215
     *  returned.
216
     */
217
    public function getData($field_id = null, $asObject = false)
218
    {
219
        $fieldData = isset($this->_data[$field_id])
220
            ? $this->_data[$field_id]
221
            : array();
222
223
        if (!$field_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $field_id of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
224
            return $this->_data;
225
        }
226
227
        return ($asObject ? (object)$fieldData : $fieldData);
228
    }
229
230
    /**
231
     * Given a array of data from a form, this function will iterate over all the fields
232
     * in this Entry's Section and call their `checkPostFieldData()` function.
233
     *
234
     * @param array $data
235
     *  An associative array of the data for this entry where they key is the
236
     *  Field's handle for this Section and the value is the data from the form
237
     * @param null|array $errors
238
     *  An array of errors, by reference. Defaults to empty*  An array of errors, by reference.
239
     *  Defaults to empty
240
     * @param boolean $ignore_missing_fields
241
     *  This parameter allows Entries to be updated, rather than replaced. This is
242
     *  useful if the input form only contains a couple of the fields for this Entry.
243
     *  Defaults to false, which will check all Fields even if they are not
244
     *  provided in the $data
245
     * @throws Exception
246
     * @return integer
247
     *  Either `Entry::__ENTRY_OK__` or `Entry::__ENTRY_FIELD_ERROR__`
248
     */
249
    public function checkPostData($data, &$errors = null, $ignore_missing_fields = false)
250
    {
251
        $status = Entry::__ENTRY_OK__;
252
        $section = SectionManager::fetch($this->get('section_id'));
253
        $schema = $section->fetchFieldsSchema();
254
255
        foreach ($schema as $info) {
256
            $message = null;
257
            $field = FieldManager::fetch($info['id']);
258
259
            /**
260
             * Prior to checking a field's post data.
261
             *
262
             * @delegate EntryPreCheckPostFieldData
263
             * @since Symphony 2.7.0
264
             * @param string $context
265
             * '/backend/' resp. '/frontend/'
266
             * @param object $section
267
             *  The section of the field
268
             * @param object $field
269
             *  The field, passed by reference
270
             * @param array $post_data
271
             *  All post data, passed by reference
272
             * @param array $errors
273
             *  The errors (of fields already checked), passed by reference
274
             */
275
            Symphony::ExtensionManager()->notifyMembers(
276
                'EntryPreCheckPostFieldData',
277
                class_exists('Administration', false) ? '/backend/' : '/frontend/',
278
                array(
279
                    'section' => $section,
280
                    'field' => &$field,
281
                    'post_data' => &$data,
282
                    'errors' => &$errors
283
                )
284
            );
285
286
            if ($ignore_missing_fields && !isset($data[$field->get('element_name')])) {
0 ignored issues
show
Bug introduced by
The method get cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
287
                continue;
288
            }
289
290
            if (Field::__OK__ !== $field->checkPostFieldData((isset($data[$info['element_name']]) ? $data[$info['element_name']] : null), $message, $this->get('id'))) {
0 ignored issues
show
Bug introduced by
The method checkPostFieldData cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
291
                $status = Entry::__ENTRY_FIELD_ERROR__;
292
                $errors[$info['id']] = $message;
293
            }
294
        }
295
296
        return $status;
297
    }
298
299
    /**
300
     * Iterates over all the Fields in this Entry calling their
301
     * `processRawFieldData()` function to set default values for this Entry.
302
     *
303
     * @see toolkit.Field#processRawFieldData()
304
     */
305
    public function findDefaultData()
306
    {
307
        $section = SectionManager::fetch($this->get('section_id'));
308
        $schema = $section->fetchFields();
309
310
        foreach ($schema as $field) {
311
            $field_id = $field->get('field_id');
312
            if (empty($field_id) || isset($this->_data[$field_id])) {
313
                continue;
314
            }
315
316
            $result = $field->processRawFieldData(null, $status, $message, false, $this->get('id'));
0 ignored issues
show
Bug introduced by
The variable $status does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $message does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
317
            $this->setData($field_id, $result);
318
        }
319
320
        $this->set('modification_date', DateTimeObj::get('Y-m-d H:i:s'));
321
        $this->set('modification_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s'));
322
323
        if (!$this->get('creation_date')) {
324
            $this->set('creation_date', $this->get('modification_date'));
325
        }
326
327
        if (!$this->get('creation_date_gmt')) {
328
            $this->set('creation_date_gmt', $this->get('modification_date_gmt'));
329
        }
330
    }
331
332
    /**
333
     * Commits this Entry's data to the database, by first finding the default
334
     * data for this `Entry` and then utilising the `EntryManager`'s
335
     * add or edit function. The `EntryManager::edit` function is used if
336
     * the current `Entry` object has an ID, otherwise `EntryManager::add`
337
     * is used.
338
     *
339
     * @see toolkit.Entry#findDefaultData()
340
     * @throws Exception
341
     * @return boolean
342
     *  true if the commit was successful, false otherwise.
343
     */
344
    public function commit()
345
    {
346
        $this->findDefaultData();
347
348
        return ($this->get('id') ? EntryManager::edit($this) : EntryManager::add($this));
349
    }
350
351
    /**
352
     * Entries may link to other Entries through fields. This function will return the
353
     * number of entries that are associated with the current entry as an associative
354
     * array. If there are no associated entries, null will be returned.
355
     *
356
     * @param array $associated_sections
357
     *  An associative array of sections to return the Entry counts from. Defaults to
358
     *  null, which will fetch all the associations of this Entry.
359
     * @throws Exception
360
     * @return array
361
     *  An associative array with the key being the associated Section's ID and the
362
     *  value being the number of entries associated with this Entry.
363
     */
364
    public function fetchAllAssociatedEntryCounts($associated_sections = null)
365
    {
366
        if (is_null($this->get('section_id'))) {
367
            return null;
368
        }
369
370
        if (is_null($associated_sections)) {
371
            $section = SectionManager::fetch($this->get('section_id'));
372
            $associated_sections = $section->fetchChildAssociations();
373
        }
374
375
        if (!is_array($associated_sections) || empty($associated_sections)) {
376
            return null;
377
        }
378
379
        $counts = array();
380
381
        foreach ($associated_sections as $as) {
382
            $field = FieldManager::fetch($as['child_section_field_id']);
383
            $parent_section_field_id = $as['parent_section_field_id'];
384
385
            if (!is_null($parent_section_field_id)) {
386
                $search_value = $field->fetchAssociatedEntrySearchValue(
0 ignored issues
show
Bug introduced by
The method fetchAssociatedEntrySearchValue cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
387
                    $this->getData($as['parent_section_field_id']),
388
                    $as['parent_section_field_id'],
389
                    $this->get('id')
390
                );
391
            } else {
392
                $search_value = $this->get('id');
393
            }
394
395
            $counts[$as['child_section_id']][$as['child_section_field_id']] = $field->fetchAssociatedEntryCount($search_value);
0 ignored issues
show
Bug introduced by
The method fetchAssociatedEntryCount cannot be called on $field (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
396
        }
397
398
        return $counts;
399
    }
400
}
401