/**
  * Builds the necessary fields on the object
  *
  * @return void
  */
 public function build()
 {
     $model = $this->config->getDataModel();
     $options = $this->suppliedOptions;
     $this->tablePrefix = $this->db->getTablePrefix();
     //set some options-based defaults
     $options['title'] = $this->validator->arrayGet($options, 'title', $options['column_name']);
     $options['sort_field'] = $this->validator->arrayGet($options, 'sort_field', $options['column_name']);
     //if the supplied item is an accessor, make this unsortable for the moment
     if (method_exists($model, camel_case('get_' . $options['column_name'] . '_attribute')) && $options['column_name'] === $options['sort_field']) {
         $options['sortable'] = false;
     }
     //however, if this is not a relation and the select option was supplied, str_replace the select option and make it sortable again
     if ($select = $this->validator->arrayGet($options, 'select')) {
         $options['select'] = str_replace('(:table)', $this->tablePrefix . $model->getTable(), $select);
     }
     //now we do some final organization to categorize these columns (useful later in the sorting)
     if (method_exists($model, camel_case('get_' . $options['column_name'] . '_attribute')) || $select) {
         $options['is_computed'] = true;
     } else {
         $options['is_included'] = true;
     }
     //run the visible property closure if supplied
     $visible = $this->validator->arrayGet($options, 'visible');
     if (is_callable($visible)) {
         $options['visible'] = $visible($this->config->getDataModel()) ? true : false;
     }
     $this->suppliedOptions = $options;
 }
 /**
  * Given a model, field, type (filter or edit), and constraints (either int or array), returns an array of options
  *
  * @param string	$field
  * @param string	$type			//either 'filter' or 'edit'
  * @param array		$constraints	//an array of ids of the other model's items
  * @param array		$selectedItems	//an array of ids that are currently selected
  * @param string	$term			//the search term
  *
  * @return array
  */
 public function updateRelationshipOptions($field, $type, $constraints, $selectedItems, $term = null)
 {
     //first get the related model and fetch the field's options
     $model = $this->config->getDataModel();
     $relatedModel = $model->{$field}()->getRelated();
     $relatedTable = $relatedModel->getTable();
     $relatedKeyName = $relatedModel->getKeyName();
     $relatedKeyTable = $relatedTable . '.' . $relatedKeyName;
     $fieldObject = $this->getFieldObjectByName($field, $type);
     //if we can't find the field, return an empty array
     if (!$fieldObject) {
         return array();
     }
     //make sure we're grouping by the model's id
     $query = $relatedModel->newQuery();
     //set up the selects
     $query->select(array($this->db->raw($this->db->getTablePrefix() . $relatedTable . '.*')));
     //format the selected items into an array
     $selectedItems = $this->formatSelectedItems($selectedItems);
     //if this is an autocomplete field, check if there is a search term. If not, just return the selected items
     if ($fieldObject->getOption('autocomplete') && !$term) {
         if (sizeof($selectedItems)) {
             $this->filterQueryBySelectedItems($query, $selectedItems, $fieldObject, $relatedKeyTable);
             return $this->formatSelectOptions($fieldObject, $query->get());
         } else {
             return array();
         }
     }
     //applies constraints if there are any
     $this->applyConstraints($constraints, $query, $fieldObject);
     //if there is a search term, limit the result set by that term
     $this->filterBySearchTerm($term, $query, $fieldObject, $selectedItems, $relatedKeyTable);
     //perform any user-supplied options filter
     $filter = $fieldObject->getOption('options_filter');
     $filter($query);
     //finally we can return the options
     return $this->formatSelectOptions($fieldObject, $query->get());
 }