/** * The fetch method returns a instance of a Field from tbl_fields. The most common * use of this function is to retrieve a Field by ID, but it can be used to retrieve * Fields from a Section also. There are several parameters that can be used to fetch * fields by their Type, Location, by a Field Constant or with a custom WHERE query. * * @throws DatabaseException * @throws Exception * @param integer|array $id * The ID of the field to retrieve. Defaults to null which will return multiple field * objects. Since Symphony 2.3, `$id` will accept an array of Field ID's * @param integer $section_id * The ID of the section to look for the fields in. Defaults to null which will allow * all fields in the Symphony installation to be searched on. * @param string $order * Available values of ASC (Ascending) or DESC (Descending), which refer to the * sort order for the query. Defaults to ASC (Ascending) * @param string $sortfield * The field to sort the query by. Can be any from the tbl_fields schema. Defaults to * 'sortorder' * @param string $type * Filter fields by their type, ie. input, select. Defaults to null * @param string $location * Filter fields by their location in the entry form. There are two possible values, * 'main' or 'sidebar'. Defaults to null * @param string $where * Allows a custom where query to be included. Must be valid SQL. The tbl_fields alias * is t1 * @param integer|string $restrict * Only return fields if they match one of the Field Constants. Available values are * `__TOGGLEABLE_ONLY__`, `__UNTOGGLEABLE_ONLY__`, `__FILTERABLE_ONLY__`, * `__UNFILTERABLE_ONLY__` or `__FIELD_ALL__`. Defaults to `__FIELD_ALL__` * @return array * An array of Field objects. If no Field are found, null is returned. */ public static function fetch($id = null, $section_id = null, $order = 'ASC', $sortfield = 'sortorder', $type = null, $location = null, $where = null, $restrict = Field::__FIELD_ALL__) { $fields = array(); $returnSingle = false; $ids = array(); $field_contexts = array(); if (!is_null($id)) { if (is_numeric($id)) { $returnSingle = true; } if (!is_array($id)) { $field_ids = array((int) $id); } else { $field_ids = $id; } // Loop over the `$field_ids` and check to see we have // instances of the request fields foreach ($field_ids as $key => $field_id) { if (isset(self::$_initialiased_fields[$field_id]) && self::$_initialiased_fields[$field_id] instanceof Field) { $fields[$field_id] = self::$_initialiased_fields[$field_id]; unset($field_ids[$key]); } } } // If there is any `$field_ids` left to be resolved lets do that, otherwise // if `$id` wasn't provided in the first place, we'll also continue if (!empty($field_ids) || is_null($id)) { $sql = sprintf("SELECT t1.*\n FROM tbl_fields AS `t1`\n WHERE 1\n %s %s %s %s\n %s", isset($type) ? " AND t1.`type` = '{$type}' " : null, isset($location) ? " AND t1.`location` = '{$location}' " : null, isset($section_id) ? " AND t1.`parent_section` = '{$section_id}' " : null, $where, isset($field_ids) ? " AND t1.`id` IN(" . implode(',', $field_ids) . ") " : " ORDER BY t1.`{$sortfield}` {$order}"); if (!($result = Symphony::Database()->fetch($sql))) { return $returnSingle ? null : array(); } // Loop over the resultset building an array of type, field_id foreach ($result as $f) { $ids[$f['type']][] = $f['id']; } // Loop over the `ids` array, which is grouped by field type // and get the field context. foreach ($ids as $type => $field_id) { $field_contexts[$type] = Symphony::Database()->fetch(sprintf("SELECT * FROM `tbl_fields_%s` WHERE `field_id` IN (%s)", $type, implode(',', $field_id)), 'field_id'); } foreach ($result as $f) { // We already have this field in our static store if (isset(self::$_initialiased_fields[$f['id']]) && self::$_initialiased_fields[$f['id']] instanceof Field) { $field = self::$_initialiased_fields[$f['id']]; // We don't have an instance of this field, so let's set one up } else { $field = self::create($f['type']); $field->setArray($f); // If the field has said that's going to have associations, then go find the // association setting value. In future this check will be most robust with // an interface, but for now, this is what we've got. RE: #2082 if ($field->canShowAssociationColumn()) { $field->set('show_association', SectionManager::getSectionAssociationSetting($f['id'])); } // Get the context for this field from our previous queries. $context = $field_contexts[$f['type']][$f['id']]; if (is_array($context) && !empty($context)) { try { unset($context['id']); $field->setArray($context); } catch (Exception $e) { throw new Exception(__('Settings for field %s could not be found in table tbl_fields_%s.', array($f['id'], $f['type']))); } } self::$_initialiased_fields[$f['id']] = $field; } // Check to see if there was any restricts imposed on the fields if ($restrict == Field::__FIELD_ALL__ || $restrict == Field::__TOGGLEABLE_ONLY__ && $field->canToggle() || $restrict == Field::__UNTOGGLEABLE_ONLY__ && !$field->canToggle() || $restrict == Field::__FILTERABLE_ONLY__ && $field->canFilter() || $restrict == Field::__UNFILTERABLE_ONLY__ && !$field->canFilter()) { $fields[$f['id']] = $field; } } } return count($fields) <= 1 && $returnSingle ? current($fields) : $fields; }