public function __invoke($records) { $data = ['totals' => [], 'group_by' => $this->search->group_by, 'group_by_attribute_key' => $this->search->group_by_attribute_key, 'timeline_attribute' => $this->search->timeline_attribute]; if (count($records)) { // Grab just label and total from db results if ($this->search->timeline) { $data['totals'] = $this->formatTimelineTotals($records); $data['time_interval'] = $this->search->getFilter('timeline_interval', 86400); } else { $data['totals'] = $this->formatTotals($records); } } return $data; }
public function setSearchParams(SearchData $search) { $this->search_query = $this->selectQuery(); $sorting = $search->getSorting(); if (!empty($sorting['orderby'])) { $this->search_query->order_by($this->getTable() . '.' . $sorting['orderby'], Arr::get($sorting, 'order')); } if (!empty($sorting['offset'])) { $this->search_query->offset($sorting['offset']); } if (!empty($sorting['limit'])) { $this->search_query->limit($sorting['limit']); } // apply the unique conditions of the search $this->setSearchConditions($search); }
/** * Get filter parameters as search data. * * @return SearchData */ protected function getSearch() { $fields = $this->repo->getSearchFields(); $paging = $this->getPagingFields(); $filters = $this->getFilters(array_merge($fields, array_keys($paging))); $this->search->setFilters(array_merge($paging, $filters)); $this->search->setSortingKeys(array_keys($paging)); return $this->search; }
public function setSearchParams(SearchData $search) { // Overriding so we can alter sorting logic // @todo make it easier to override just sorting $this->search_query = $this->selectQuery(); $sorting = $search->getSorting(); // Always return featured sets first // @todo make this optional $this->search_query->order_by('sets.featured', 'DESC'); if (!empty($sorting['orderby'])) { $this->search_query->order_by($this->getTable() . '.' . $sorting['orderby'], Arr::get($sorting, 'order')); } if (!empty($sorting['offset'])) { $this->search_query->offset($sorting['offset']); } if (!empty($sorting['limit'])) { $this->search_query->limit($sorting['limit']); } // apply the unique conditions of the search $this->setSearchConditions($search); }
protected function setSearchConditions(SearchData $search) { if ($search->include_types) { if (is_array($search->include_types)) { $this->include_value_types = $search->include_types; } else { $this->include_value_types = explode(',', $search->include_types); } } if ($search->include_attributes) { if (is_array($search->include_attributes)) { $this->include_attributes = $search->include_attributes; } else { $this->include_attributes = explode(',', $search->include_attributes); } } $query = $this->search_query; $table = $this->getTable(); $status = $search->getFilter('status', 'published'); if ($status !== 'all') { $query->where("{$table}.status", '=', $status); } foreach (['type', 'locale', 'slug'] as $key) { if ($search->{$key}) { $query->where("{$table}.{$key}", '=', $search->{$key}); } } // If user = me, replace with current user id if ($search->user === 'me') { $search->user = $this->getUserId(); } foreach (['user', 'parent', 'form'] as $key) { if (isset($search->{$key})) { // Make sure we have an array if (!is_array($search->{$key})) { $search->{$key} = explode(',', $search->{$key}); } // Special case: 'none' looks for null if (in_array('none', $search->{$key})) { $query->and_where_open()->where("{$table}.{$key}_id", 'IS', NULL)->or_where("{$table}.{$key}_id", 'IN', $search->{$key})->and_where_close(); } else { $query->where("{$table}.{$key}_id", 'IN', $search->{$key}); } } } if ($search->q) { // search terms are all wrapped as a series of OR conditions $query->and_where_open(); // searching in title / content $query->where("{$table}.title", 'LIKE', "%{$search->q}%")->or_where("{$table}.content", 'LIKE', "%{$search->q}%"); if (is_numeric($search->q)) { // if `q` is numeric, could be searching for a specific id $query->or_where('id', '=', $search->q); } $query->and_where_close(); } if ($search->id) { //searching for specific post id, used for single post in set searches $query->where('id', '=', $search->id); } // date chcks if ($search->created_after) { $created_after = strtotime($search->created_after); $query->where("{$table}.created", '>=', $created_after); } if ($search->created_before) { $created_before = strtotime($search->created_before); $query->where("{$table}.created", '<=', $created_before); } if ($search->updated_after) { $updated_after = strtotime($search->updated_after); $query->where("{$table}.updated", '>=', $updated_after); } if ($search->updated_before) { $updated_before = strtotime($search->updated_before); $query->where("{$table}.updated", '<=', $updated_before); } // Bounding box search // Create geometry from bbox (or create bbox from center & radius) $bounding_box = null; if ($search->bbox) { $bounding_box = $this->createBoundingBoxFromCSV($search->bbox); } else { if ($search->center_point && $search->within_km) { $bounding_box = $this->createBoundingBoxFromCenter($search->center_point, $search->within_km); } } if ($bounding_box) { $query->join([$this->getBoundingBoxSubquery($bounding_box), 'Filter_BBox'], 'INNER')->on('posts.id', '=', 'Filter_BBox.post_id'); } if ($search->current_stage) { $stages = $search->current_stage; if (!is_array($stages)) { $stages = explode(',', $stages); } /** * Here be dragons * The purpose of this query is to return the set of posts which * have current stage X. In this case, current stage X is actually the * the stage the post has NOT yet completed - which is the stage with. * the lowest priority. * For example: * If I have 3 stages for a given Post Type, I am on stage 1 if * I have completed no stages and I am on stage 3 if I have completed * stages 1 and 2. * If I have completed stages 1 and 3, I am on stage 2 as stages are considered * to be sequential */ /** * This query is responsible for returning all the * stages for a given post id, where the stage has been completed. * This is used to check which stages the Post has not yet completed */ $stages_posts = DB::select('form_stage_id')->from('form_stages_posts')->where('post_id', '=', DB::expr('posts.id'))->and_where('completed', '=', '1'); /** * This query returns the IDs for the stages that we are filtering by */ $forms_sub = DB::select('form_stages.form_id')->from('form_stages')->where('form_stages.id', 'IN', $stages); /** * This is the master query, it collects all the posts * missing stages that we are filtering by. */ $sub = DB::select(array('posts.id', 'p_id'), array('form_stages.id', 'fs_id'), 'priority', 'posts.form_id', 'forms.id')->from('posts')->join('forms')->on('posts.form_id', '=', 'forms.id')->on('forms.id', 'IN', $forms_sub)->join('form_stages')->on('form_stages.form_id', 'IN', $forms_sub)->on('form_stages.id', 'NOT IN', $stages_posts)->group_by('p_id')->having('form_stages.id', 'IN', $stages)->order_by('priority'); //This step wraps the query and returns only the posts ids without the extra data such as form, stage or priority $posts_sub = DB::select('p_id')->from(array($sub, 'sub')); $query->where('posts.id', 'IN', $posts_sub); } // Filter by tag if ($search->tags) { if (isset($search->tags['any'])) { $tags = $search->tags['any']; if (!is_array($tags)) { $tags = explode(',', $tags); } $query->join('posts_tags')->on('posts.id', '=', 'posts_tags.post_id')->where('tag_id', 'IN', $tags); } elseif (isset($search->tags['all'])) { $tags = $search->tags['all']; if (!is_array($tags)) { $tags = explode(',', $tags); } foreach ($tags as $tag) { $sub = DB::select('post_id')->from('posts_tags')->where('tag_id', '=', $tag); $query->where('posts.id', 'IN', $sub); } } else { $tags = $search->tags; if (!is_array($tags)) { $tags = explode(',', $tags); } $query->join('posts_tags')->on('posts.id', '=', 'posts_tags.post_id')->where('tag_id', 'IN', $tags); } } // Filter by set if ($search->set) { $set = $search->set; if (!is_array($set)) { $set = explode(',', $set); } $query->join('posts_sets', 'INNER')->on('posts.id', '=', 'posts_sets.post_id')->where('posts_sets.set_id', 'IN', $set); } // Attributes if ($search->values) { foreach ($search->values as $key => $value) { $attribute = $this->form_attribute_repo->getByKey($key); $sub = $this->post_value_factory->getRepo($attribute->type)->getValueQuery($attribute->id, $value); $query->join([$sub, 'Filter_' . ucfirst($key)], 'INNER')->on('posts.id', '=', 'Filter_' . ucfirst($key) . '.post_id'); } } $user = $this->getUser(); // If there's no logged in user, or the user isn't admin // restrict our search to make sure we still return SOME results // they are allowed to see if (!$user->id) { $query->where("{$table}.status", '=', 'published'); } elseif ($user->role !== 'admin') { $query->and_where_open()->where("{$table}.status", '=', 'published')->or_where("{$table}.user_id", '=', $user->id)->and_where_close(); } }
/** * Get the paging parameters for the current collection request from input data. * @param Ushahidi\SearchData $input * @return Array [limit, offset, order, orderby, curr, next, prev] */ protected function _get_paging_for_input(SearchData $input) { $params = $input->getSortingParams(); $prev_params = $next_params = $params; $next_params['offset'] = $params['offset'] + $params['limit']; $prev_params['offset'] = $params['offset'] - $params['limit']; $prev_params['offset'] = $prev_params['offset'] > 0 ? $prev_params['offset'] : 0; $curr = URL::site($this->request->uri() . URL::query($params), $this->request); $next = URL::site($this->request->uri() . URL::query($next_params), $this->request); $prev = URL::site($this->request->uri() . URL::query($prev_params), $this->request); return array('limit' => $input->limit, 'offset' => $input->offset, 'order' => $input->order, 'orderby' => $input->orderby, 'curr' => $curr, 'next' => $next, 'prev' => $prev); }
protected function setSearchConditions(SearchData $search) { if ($search->include_types) { if (is_array($search->include_types)) { $this->include_value_types = $search->include_types; } else { $this->include_value_types = explode(',', $search->include_types); } } if ($search->include_attributes) { if (is_array($search->include_attributes)) { $this->include_attributes = $search->include_attributes; } else { $this->include_attributes = explode(',', $search->include_attributes); } } $query = $this->search_query; $table = $this->getTable(); $status = $search->getFilter('status', 'published'); if ($status !== 'all') { $query->where("{$table}.status", '=', $status); } foreach (['type', 'locale', 'slug'] as $key) { if ($search->{$key}) { $query->where("{$table}.{$key}", '=', $search->{$key}); } } // If user = me, replace with current user id if ($search->user === 'me') { $search->user = $this->getUserId(); } foreach (['user', 'parent', 'form'] as $key) { if (isset($search->{$key})) { // Special case: empty search string looks for null if (empty($search->{$key})) { $query->where("{$table}.{$key}_id", "IS", NULL); } else { // Make sure we have an array if (!is_array($search->{$key})) { $search->{$key} = explode(',', $search->{$key}); } $query->where("{$table}.{$key}_id", 'IN', $search->{$key}); } } } if ($search->q) { // search terms are all wrapped as a series of OR conditions $query->and_where_open(); // searching in title / content $query->where("{$table}.title", 'LIKE', "%{$search->q}%")->or_where("{$table}.content", 'LIKE', "%{$search->q}%"); if (is_numeric($search->q)) { // if `q` is numeric, could be searching for a specific id $query->or_where('id', '=', $search->q); } $query->and_where_close(); } if ($search->id) { //searching for specific post id, used for single post in set searches $query->where('id', '=', $search->id); } // date chcks if ($search->created_after) { $created_after = strtotime($search->created_after); $query->where("{$table}.created", '>=', $created_after); } if ($search->created_before) { $created_before = strtotime($search->created_before); $query->where("{$table}.created", '<=', $created_before); } if ($search->updated_after) { $updated_after = strtotime($search->updated_after); $query->where("{$table}.updated", '>=', $updated_after); } if ($search->updated_before) { $updated_before = strtotime($search->updated_before); $query->where("{$table}.updated", '<=', $updated_before); } // Bounding box search // Create geometry from bbox (or create bbox from center & radius) $bounding_box = null; if ($search->bbox) { $bounding_box = $this->createBoundingBoxFromCSV($search->bbox); } else { if ($search->center_point && $search->within_km) { $bounding_box = $this->createBoundingBoxFromCenter($search->center_point, $search->within_km); } } if ($bounding_box) { $query->join([$this->getBoundingBoxSubquery($bounding_box), 'Filter_BBox'], 'INNER')->on('posts.id', '=', 'Filter_BBox.post_id'); } // Filter by tag if ($search->tags) { if (isset($search->tags['any'])) { $tags = $search->tags['any']; if (!is_array($tags)) { $tags = explode(',', $tags); } $query->join('posts_tags')->on('posts.id', '=', 'posts_tags.post_id')->where('tag_id', 'IN', $tags); } elseif (isset($search->tags['all'])) { $tags = $search->tags['all']; if (!is_array($tags)) { $tags = explode(',', $tags); } foreach ($tags as $tag) { $sub = DB::select('post_id')->from('posts_tags')->where('tag_id', '=', $tag); $query->where('posts.id', 'IN', $sub); } } else { $tags = $search->tags; if (!is_array($tags)) { $tags = explode(',', $tags); } $query->join('posts_tags')->on('posts.id', '=', 'posts_tags.post_id')->where('tag_id', 'IN', $tags); } } // Filter by set if ($search->set) { $query->join('posts_sets', 'INNER')->on('posts.id', '=', 'posts_sets.post_id')->where('posts_sets.set_id', '=', $search->set); } // Attributes if ($search->values) { foreach ($search->values as $key => $value) { $attribute = $this->form_attribute_repo->getByKey($key); $sub = $this->post_value_factory->getRepo($attribute->type)->getValueQuery($attribute->id, $value); $query->join([$sub, 'Filter_' . ucfirst($key)], 'INNER')->on('posts.id', '=', 'Filter_' . ucfirst($key) . '.post_id'); } } }