| Total Complexity | 48 |
| Total Lines | 394 |
| Duplicated Lines | 0 % |
| Changes | 6 | ||
| Bugs | 0 | Features | 0 |
Complex classes like Entry 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 Entry, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 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 | 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 : (int)$this->get('author_id'); // Author_id cannot be null |
||
| 106 | $fields['modification_author_id'] = is_null($this->get('modification_author_id')) ? $fields['author_id'] : (int)$this->get('modification_author_id'); |
||
| 107 | |||
| 108 | Symphony::Database()->insert($fields, 'tbl_entries'); |
||
| 109 | |||
| 110 | if (!$entry_id = Symphony::Database()->getInsertID()) { |
||
| 111 | return null; |
||
| 112 | } |
||
| 113 | |||
| 114 | $this->set('id', $entry_id); |
||
| 115 | |||
| 116 | return $entry_id; |
||
| 117 | } |
||
| 118 | |||
| 119 | /** |
||
| 120 | * Set the data for a Field in this Entry, given the Field ID and it's data |
||
| 121 | * |
||
| 122 | * @param integer $field_id |
||
| 123 | * The ID of the Field this data is for |
||
| 124 | * @param mixed $data |
||
| 125 | * Often an array |
||
| 126 | */ |
||
| 127 | public function setData($field_id, $data) |
||
| 130 | } |
||
| 131 | |||
| 132 | /** |
||
| 133 | * When an entry is saved from a form (either Frontend/Backend) this |
||
| 134 | * function will find all the fields in this set and loop over them, setting |
||
| 135 | * the data to each of the fields for processing. If any errors occur during |
||
| 136 | * this, `_ENTRY_FIELD_ERROR_` is returned, and an array is available with |
||
| 137 | * the errors. |
||
| 138 | * |
||
| 139 | * @param array $data |
||
| 140 | * An associative array of the data for this entry where they key is the |
||
| 141 | * Field's handle for this Section and the value is the data from the form |
||
| 142 | * @param array $errors |
||
| 143 | * An associative array of errors, by reference. The key is the `field_id`, the value |
||
| 144 | * is the message text. Defaults to an empty array |
||
| 145 | * @param boolean $simulate |
||
| 146 | * If $simulate is given as true, a dry run of this function will occur, where |
||
| 147 | * regardless of errors, an Entry will not be saved in the database. Defaults to |
||
| 148 | * false |
||
| 149 | * @param boolean $ignore_missing_fields |
||
| 150 | * This parameter allows Entries to be updated, rather than replaced. This is |
||
| 151 | * useful if the input form only contains a couple of the fields for this Entry. |
||
| 152 | * Defaults to false, which will set Fields to their default values if they are not |
||
| 153 | * provided in the $data |
||
| 154 | * @throws DatabaseException |
||
| 155 | * @throws Exception |
||
| 156 | * @return integer |
||
| 157 | * Either `Entry::__ENTRY_OK__` or `Entry::__ENTRY_FIELD_ERROR__` |
||
| 158 | */ |
||
| 159 | public function setDataFromPost($data, &$errors = null, $simulate = false, $ignore_missing_fields = false) |
||
| 160 | { |
||
| 161 | $status = Entry::__ENTRY_OK__; |
||
| 162 | |||
| 163 | // Entry has no ID, create it: |
||
| 164 | if (!$this->get('id') && $simulate === false) { |
||
| 165 | $entry_id = $this->assignEntryId(); |
||
| 166 | |||
| 167 | if (is_null($entry_id)) { |
||
| 168 | return Entry::__ENTRY_FIELD_ERROR__; |
||
| 169 | } |
||
| 170 | } |
||
| 171 | |||
| 172 | $section = SectionManager::fetch($this->get('section_id')); |
||
| 173 | $schema = $section->fetchFieldsSchema(); |
||
| 174 | |||
| 175 | foreach ($schema as $info) { |
||
| 176 | $message = null; |
||
| 177 | $field = FieldManager::fetch($info['id']); |
||
| 178 | |||
| 179 | if ($ignore_missing_fields && !isset($data[$field->get('element_name')])) { |
||
| 180 | continue; |
||
| 181 | } |
||
| 182 | |||
| 183 | $result = $field->processRawFieldData((isset($data[$info['element_name']]) ? $data[$info['element_name']] : null), $s, $message, $simulate, $this->get('id')); |
||
| 184 | |||
| 185 | if ($s !== Field::__OK__) { |
||
| 186 | $status = Entry::__ENTRY_FIELD_ERROR__; |
||
| 187 | $errors[$info['id']] = $message; |
||
| 188 | } |
||
| 189 | |||
| 190 | $this->setData($info['id'], $result); |
||
| 191 | } |
||
| 192 | |||
| 193 | // Failed to create entry, cleanup |
||
| 194 | if ($status !== Entry::__ENTRY_OK__ && !is_null($entry_id)) { |
||
| 195 | Symphony::Database()->delete('tbl_entries', sprintf(" `id` = %d ", $entry_id)); |
||
| 196 | } |
||
| 197 | |||
| 198 | return $status; |
||
| 199 | } |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Accessor function to return data from this Entry for a particular |
||
| 203 | * field. Optional parameter to return this data as an object instead |
||
| 204 | * of an array. If a Field is not provided, an associative array of all data |
||
| 205 | * assigned to this Entry will be returned. |
||
| 206 | * |
||
| 207 | * @param integer $field_id |
||
| 208 | * The ID of the Field whose data you want |
||
| 209 | * @param boolean $asObject |
||
| 210 | * If true, the data will be returned as an object instead of an |
||
| 211 | * array. Defaults to false. Note that if a `$field_id` is not provided |
||
| 212 | * the result will always be an array. |
||
| 213 | * @return array|object |
||
| 214 | * Depending on the value of `$asObject`, return the field's data |
||
| 215 | * as either an array or an object. If no data exists, null will be |
||
| 216 | * returned. |
||
| 217 | */ |
||
| 218 | public function getData($field_id = null, $asObject = false) |
||
| 219 | { |
||
| 220 | $fieldData = isset($this->_data[$field_id]) |
||
| 221 | ? $this->_data[$field_id] |
||
| 222 | : array(); |
||
| 223 | |||
| 224 | if (!$field_id) { |
||
| 225 | return $this->_data; |
||
| 226 | } |
||
| 227 | |||
| 228 | return ($asObject ? (object)$fieldData : $fieldData); |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * Given a array of data from a form, this function will iterate over all the fields |
||
| 233 | * in this Entry's Section and call their `checkPostFieldData()` function. |
||
| 234 | * |
||
| 235 | * @param array $data |
||
| 236 | * An associative array of the data for this entry where they key is the |
||
| 237 | * Field's handle for this Section and the value is the data from the form |
||
| 238 | * @param null|array $errors |
||
| 239 | * An array of errors, by reference. Defaults to empty* An array of errors, by reference. |
||
| 240 | * Defaults to empty |
||
| 241 | * @param boolean $ignore_missing_fields |
||
| 242 | * This parameter allows Entries to be updated, rather than replaced. This is |
||
| 243 | * useful if the input form only contains a couple of the fields for this Entry. |
||
| 244 | * Defaults to false, which will check all Fields even if they are not |
||
| 245 | * provided in the $data |
||
| 246 | * @throws Exception |
||
| 247 | * @return integer |
||
| 248 | * Either `Entry::__ENTRY_OK__` or `Entry::__ENTRY_FIELD_ERROR__` |
||
| 249 | */ |
||
| 250 | public function checkPostData($data, &$errors = null, $ignore_missing_fields = false) |
||
| 251 | { |
||
| 252 | $status = Entry::__ENTRY_OK__; |
||
| 253 | $section = SectionManager::fetch($this->get('section_id')); |
||
| 254 | $schema = $section->fetchFieldsSchema(); |
||
| 255 | |||
| 256 | foreach ($schema as $info) { |
||
| 257 | $message = null; |
||
| 258 | $field = FieldManager::fetch($info['id']); |
||
| 259 | |||
| 260 | /** |
||
| 261 | * Prior to checking a field's post data. |
||
| 262 | * |
||
| 263 | * @delegate EntryPreCheckPostFieldData |
||
| 264 | * @since Symphony 2.7.0 |
||
| 265 | * @param string $context |
||
| 266 | * '/backend/' resp. '/frontend/' |
||
| 267 | * @param object $section |
||
| 268 | * The section of the field |
||
| 269 | * @param object $field |
||
| 270 | * The field, passed by reference |
||
| 271 | * @param array $post_data |
||
| 272 | * All post data, passed by reference |
||
| 273 | * @param array $errors |
||
| 274 | * The errors (of fields already checked), passed by reference |
||
| 275 | */ |
||
| 276 | Symphony::ExtensionManager()->notifyMembers( |
||
| 277 | 'EntryPreCheckPostFieldData', |
||
| 278 | class_exists('Administration', false) ? '/backend/' : '/frontend/', |
||
| 279 | array( |
||
| 280 | 'section' => $section, |
||
| 281 | 'field' => &$field, |
||
| 282 | 'post_data' => &$data, |
||
| 283 | 'errors' => &$errors |
||
| 284 | ) |
||
| 285 | ); |
||
| 286 | |||
| 287 | if ($ignore_missing_fields && !isset($data[$field->get('element_name')])) { |
||
| 288 | continue; |
||
| 289 | } |
||
| 290 | |||
| 291 | if (Field::__OK__ !== $field->checkPostFieldData((isset($data[$info['element_name']]) ? $data[$info['element_name']] : null), $message, $this->get('id'))) { |
||
| 292 | $status = Entry::__ENTRY_FIELD_ERROR__; |
||
| 293 | $errors[$info['id']] = $message; |
||
| 294 | } |
||
| 295 | } |
||
| 296 | |||
| 297 | return $status; |
||
| 298 | } |
||
| 299 | |||
| 300 | /** |
||
| 301 | * Iterates over all the Fields in this Entry calling their |
||
| 302 | * `processRawFieldData()` function to set default values for this Entry. |
||
| 303 | * |
||
| 304 | * @see toolkit.Field#processRawFieldData() |
||
| 305 | */ |
||
| 306 | public function findDefaultData() |
||
| 307 | { |
||
| 308 | $section = SectionManager::fetch($this->get('section_id')); |
||
| 309 | $schema = $section->fetchFields(); |
||
| 310 | |||
| 311 | foreach ($schema as $field) { |
||
| 312 | $field_id = $field->get('field_id'); |
||
| 313 | if (empty($field_id) || isset($this->_data[$field_id])) { |
||
| 314 | continue; |
||
| 315 | } |
||
| 316 | |||
| 317 | $result = $field->processRawFieldData(null, $status, $message, false, $this->get('id')); |
||
| 318 | $this->setData($field_id, $result); |
||
| 319 | } |
||
| 320 | |||
| 321 | $this->set('modification_date', DateTimeObj::get('Y-m-d H:i:s')); |
||
| 322 | $this->set('modification_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); |
||
| 323 | |||
| 324 | if (!$this->get('creation_date')) { |
||
| 325 | $this->set('creation_date', $this->get('modification_date')); |
||
| 326 | } |
||
| 327 | |||
| 328 | if (!$this->get('creation_date_gmt')) { |
||
| 329 | $this->set('creation_date_gmt', $this->get('modification_date_gmt')); |
||
| 330 | } |
||
| 331 | |||
| 332 | if (!$this->get('author_id')) { |
||
| 333 | $this->set('author_id', 1); |
||
| 334 | } |
||
| 335 | |||
| 336 | if (!$this->get('modification_author_id')) { |
||
| 337 | $this->set('modification_author_id', $this->get('author_id')); |
||
| 338 | } |
||
| 339 | } |
||
| 340 | |||
| 341 | /** |
||
| 342 | * Commits this Entry's data to the database, by first finding the default |
||
| 343 | * data for this `Entry` and then utilising the `EntryManager`'s |
||
| 344 | * add or edit function. The `EntryManager::edit` function is used if |
||
| 345 | * the current `Entry` object has an ID, otherwise `EntryManager::add` |
||
| 346 | * is used. |
||
| 347 | * |
||
| 348 | * @see toolkit.Entry#findDefaultData() |
||
| 349 | * @throws Exception |
||
| 350 | * @return boolean |
||
| 351 | * true if the commit was successful, false otherwise. |
||
| 352 | */ |
||
| 353 | public function commit() |
||
| 358 | } |
||
| 359 | |||
| 360 | /** |
||
| 361 | * Entries may link to other Entries through fields. This function will return the |
||
| 362 | * number of entries that are associated with the current entry as an associative |
||
| 363 | * array. If there are no associated entries, null will be returned. |
||
| 364 | * |
||
| 365 | * @param array $associated_sections |
||
| 366 | * An associative array of sections to return the Entry counts from. Defaults to |
||
| 367 | * null, which will fetch all the associations of this Entry. |
||
| 368 | * @throws Exception |
||
| 369 | * @return array |
||
| 370 | * An associative array with the key being the associated Section's ID and the |
||
| 371 | * value being the number of entries associated with this Entry. |
||
| 372 | */ |
||
| 373 | public function fetchAllAssociatedEntryCounts($associated_sections = null) |
||
| 408 | } |
||
| 409 | } |
||
| 410 |