/** * Gets the filters for the given model config * * @param ModelConfig $config * * @return array */ public static function getFilters($config) { //get the model's filter fields $filters = array(); //if there are no filters, exit out early if ($config->filters) { //iterate over the filters and create field objects for them foreach ($config->filters as $field => $info) { if ($fieldObject = Field::get($field, $info, $config)) { $filters[$fieldObject->field] = $fieldObject->toArray(); } } } return $filters; }
/** * Given a model, field, type (filter or edit), and constraints (either int or array), returns an array of options * * @param Eloquent $model * @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 static function updateRelationshipOptions($config, $field, $type, $constraints, $selectedItems, $term = null) { //first get the related model and fetch the field's options $model = $config->model; $relatedModel = $model->{$field}()->model; $info = Field::getOptions($field, $config, $type); //if we can't find the field, return an empty array if (!$info) { return array(); } //set up the field object $info = Field::get($field, $info, $config, false); //make sure we're grouping by the model's id $query = $relatedModel::with($relatedModel->includes)->group_by($relatedModel->table() . '.' . $relatedModel::$key); //set up the selects $selects = array(DB::raw($relatedModel->table() . '.*')); //if selectedItems are provided, set them up as a proper array if ($selectedItems) { //if this isn't an array, set it up as one $selectedItems = is_array($selectedItems) ? $selectedItems : array($selectedItems); } else { $selectedItems = array(); } //if this is an autocomplete field, check if there is a search term. If not, just return the selected items if ($info->autocomplete && !$term) { if (sizeof($selectedItems)) { $query->where_in($relatedModel->table() . '.' . $relatedModel::$key, $selectedItems); return static::formatOptions($relatedModel, $info, $query->get($selects)); } else { return array(); } } //if there are constraints if (sizeof($info->constraints)) { //iterate over the constraints foreach ($info->constraints as $key => $relationshipName) { //now that we're looping through the constraints, check to see if this one was supplied if (isset($constraints[$key]) && $constraints[$key] && sizeof($constraints[$key])) { //constrain the query $info->applyConstraints($query, $model, $key, $relationshipName, $constraints); } } } //if there is a search term, limit the result set by that term if ($term) { //set up the wheres foreach ($info->searchFields as $search) { $query->or_where(DB::raw($search), 'LIKE', '%' . $term . '%'); } //include the currently-selected items if there are any if (count($selectedItems)) { $query->or_where_in($relatedModel->table() . '.' . $relatedModel::$key, $selectedItems); } //set up the limits $query->take($info->numOptions + count($selectedItems)); } //finally we can return the options return static::formatOptions($relatedModel, $info, $query->get($selects)); }
/** * Constrains a query object with this item's relation to a third model * * @param Query $query * @param Eloquent $model * @param string $key //the relationship name on this model * @param string $relationshipName //the relationship name on the constraint model * @param array $constraints * * @return void */ public function applyConstraints(&$query, $model, $key, $relationshipName, $constraints) { //first we get the other model and the relationship field on it $relatedModel = $model->{$this->field}()->model; $otherModel = $model->{$key}()->model; $otherField = Field::get($relationshipName, array('type' => 'relationship'), $otherModel, false); $otherField->constrainQuery($query, $relatedModel, $constraints); }
/** * Given a model, field, type (filter or edit), and search term, this returns an array of arrays with 'id' and 'name' * * @param Eloquent $model * @param string $field * @param string $type //either 'filter' or 'edit' * @param array|false $selectedItems //an array of ids of currently-selected items (necessary to maintain selections) * @param string $term //the search term * * @return array */ public static function getRelationshipSuggestions($model, $field, $type, $selectedItems, $term) { //first get the related model $related_model = $model->{$field}()->model; $info = false; //now we can sort out what the actual field info is if ($type === 'filter') { $fields = static::getFilters($model); } else { $editFields = Field::getEditFields($model); $fields = $editFields['arrayFields']; } //iterate over the fields to get the one for this $field value foreach ($fields as $key => $val) { if ($key === $field) { $info = $val; } } //if we can't find the field, return an empty array if (!$info) { return array(); } //set up the field object $info = Field::get($field, $info, $model, false); //now we can start to set up the query $query = new \Laravel\Database\Eloquent\Query($related_model); //set up the wheres foreach ($info->searchFields as $search) { $query->or_where(DB::raw($search), 'LIKE', '%' . $term . '%'); } //include the currently-selected items if ($selectedItems) { //if this isn't an array, set it up as one $selectedItems = is_array($selectedItems) ? $selectedItems : array($selectedItems); $query->or_where_in($related_model::$key, $selectedItems); } else { $selectedItems = array(); } //set up the limits $query->take($info->numOptions + count($selectedItems)); //return the array map based on the result set return array_map(function ($m) use($info, $field, $related_model) { return array($related_model::$key => $m->{$related_model::$key}, $info->nameField => $m->{$info->nameField}); }, $query->get()); }
/** * Takes a the key/value of the columns array and the associated model and returns an instance of the column or false * * @param string|int $field //the key of the options array * @param array|string $column //the value of the options array * @param ModelConfig $config //this model's config * * @return false|Field object */ public static function get($field, $column, $config) { //if this is a numeric field, $column holds the field if (is_numeric($field)) { $field = $column; $column = array(); } //set up the $column array with the supplied or default values $column = array('title' => array_get($column, 'title', $field), 'sort_field' => array_get($column, 'sort_field', $field), 'relationship' => array_get($column, 'relationship'), 'select' => array_get($column, 'select'), 'sortable' => true, 'output' => array_get($column, 'output')); //if the relation option is set, we'll set up the column array using the select if ($column['relationship']) { if (!method_exists($config->model, $column['relationship']) || !$column['select']) { return false; } //now we'll need to grab a relation field to see what its foreign table is if (!($relationshipField = Field::get($column['relationship'], array('type' => 'relationship'), $config, false))) { return false; } //if this is a belongs_to, we need to set up the proper aliased select replacement if (!$relationshipField->external) { $selectTable = $field . '_' . $relationshipField->table; } else { $selectTable = $relationshipField->table; } $column['select'] = str_replace('(:table)', $selectTable, $column['select']); $column['relationshipField'] = $relationshipField; } else { if (method_exists($config->model, 'get_' . $field) && $field === $column['sort_field']) { $column['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 (!$column['relationship'] && $column['select']) { $column['select'] = str_replace('(:table)', $config->model->table(), $column['select']); $column['sortable'] = true; } //now we do some final organization to categorize these columns (useful later in the sorting) if ($column['relationship']) { $column['isRelated'] = true; } else { if (method_exists($config->model, 'get_' . $field) || $column['select']) { $column['isComputed'] = true; } else { $column['isIncluded'] = true; } } //now we can instantiate the object return new static($field, $column); }