/** * Tests fetching of incidents when the limit parameter is specified * @test */ public function testGetIncidentsByLimit() { // Randomly generate the record limit $limit = rand(1, Incident_Model::get_incidents()->count()); // HTTP GET data $_GET = array('task' => 'incidents', 'limit' => $limit); ob_start(); $this->api_controller->index(); $contents = json_decode(ob_get_clean()); $this->assertEquals("0", $contents->error->code); $this->assertEquals($limit, count($contents->payload->incidents)); }
/** * Helper method to load the report listing view */ private function _get_report_listing_view($locale = '') { // Check if the local is empty if (empty($locale)) { $locale = Kohana::config('locale.language.0'); } // Load the report listing view $report_listing = new View('reports_listing'); // Fetch all incidents $all_incidents = reports::fetch_incidents(); // Pagination $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => (int) Kohana::config('settings.items_per_page'), 'total_items' => $all_incidents->count())); // Reports $incidents = Incident_Model::get_incidents(reports::$params, $pagination); // Swap out category titles with their proper localizations using an array (cleaner way to do this?) $localized_categories = array(); foreach ($incidents as $incident) { $incident = ORM::factory('incident', $incident->incident_id); foreach ($incident->category as $category) { $ct = (string) $category->category_title; if (!isset($localized_categories[$ct])) { $translated_title = Category_Lang_Model::category_title($category->id, $locale); $localized_categories[$ct] = $category->category_title; if ($translated_title) { $localized_categories[$ct] = $translated_title; } } } } // Set the view content $report_listing->incidents = $incidents; $report_listing->localized_categories = $localized_categories; //Set default as not showing pagination. Will change below if necessary. $report_listing->pagination = ""; // Pagination and Total Num of Report Stats $plural = $pagination->total_items == 1 ? "" : "s"; // Set the next and previous page numbers $report_listing->next_page = $pagination->next_page; $report_listing->previous_page = $pagination->previous_page; if ($pagination->total_items > 0) { $current_page = $pagination->sql_offset / $pagination->items_per_page + 1; $total_pages = ceil($pagination->total_items / $pagination->items_per_page); if ($total_pages >= 1) { $report_listing->pagination = $pagination; // Show the total of report // @todo This is only specific to the frontend reports theme $report_listing->stats_breadcrumb = $pagination->current_first_item . '-' . $pagination->current_last_item . ' of ' . $pagination->total_items . ' ' . Kohana::lang('ui_main.reports'); } else { // If we don't want to show pagination $report_listing->stats_breadcrumb = $pagination->total_items . ' ' . Kohana::lang('ui_admin.reports'); } } else { $report_listing->stats_breadcrumb = '(' . $pagination->total_items . ' report' . $plural . ')'; } // Return return $report_listing; }
/** * Helper function to fetch and optionally paginate the list of * incidents/reports via the Incident Model using one or all of the * following URL parameters * - category * - location bounds * - incident mode * - media * - location radius * * @param $paginate Optionally paginate the incidents - Default is FALSE * @return Database_Result */ public static function fetch_incidents($paginate = FALSE, $items_per_page = 0) { // Reset the paramters self::$params = array(); // Initialize the category id $category_id = 0; $table_prefix = Kohana::config('database.default.table_prefix'); // Fetch the URL data into a local variable $url_data = array_merge($_GET); // Check if some parameter values are separated by "," except the location bounds $exclude_params = array('c' => '', 'v' => '', 'm' => '', 'mode' => '', 'sw' => '', 'ne' => ''); foreach ($url_data as $key => $value) { if (array_key_exists($key, $exclude_params) and !is_array($value)) { if (is_array(explode(",", $value))) { $url_data[$key] = explode(",", $value); } } } //> BEGIN PARAMETER FETCH // // Check for the category parameter // if (isset($url_data['c']) and !is_array($url_data['c']) and intval($url_data['c']) > 0) { // Get the category ID $category_id = intval($_GET['c']); // Add category parameter to the parameter list array_push(self::$params, '(c.id = ' . $category_id . ' OR c.parent_id = ' . $category_id . ')', 'c.category_visible = 1'); } elseif (isset($url_data['c']) and is_array($url_data['c'])) { // Sanitize each of the category ids $category_ids = array(); foreach ($url_data['c'] as $c_id) { if (intval($c_id) > 0) { $category_ids[] = intval($c_id); } } // Check if there are any category ids if (count($category_ids) > 0) { $category_ids = implode(",", $category_ids); array_push(self::$params, '(c.id IN (' . $category_ids . ') OR c.parent_id IN (' . $category_ids . '))', 'c.category_visible = 1'); } } // // Incident modes // if (isset($url_data['mode']) and is_array($url_data['mode'])) { $incident_modes = array(); // Sanitize the modes foreach ($url_data['mode'] as $mode) { if (intval($mode) > 0) { $incident_modes[] = intval($mode); } } // Check if any modes exist and add them to the parameter list if (count($incident_modes) > 0) { array_push(self::$params, 'i.incident_mode IN (' . implode(",", $incident_modes) . ')'); } } // // Location bounds parameters // if (isset($url_data['sw']) and isset($url_data['ne'])) { $southwest = $url_data['sw']; $northeast = $url_data['ne']; if (count($southwest) == 2 and count($northeast) == 2) { $lon_min = (double) $southwest[0]; $lon_max = (double) $northeast[0]; $lat_min = (double) $southwest[1]; $lat_max = (double) $northeast[1]; // Add the location conditions to the parameter list array_push(self::$params, 'l.latitude >= ' . $lat_min, 'l.latitude <= ' . $lat_max, 'l.longitude >= ' . $lon_min, 'l.longitude <= ' . $lon_max); } } // // Location bounds - based on start location and radius // if (isset($url_data['radius']) and isset($url_data['start_loc'])) { //if $url_data['start_loc'] is just comma delimited strings, then make it into an array if (!is_array($url_data['start_loc'])) { $url_data['start_loc'] = explode(",", $url_data['start_loc']); } if (intval($url_data['radius']) > 0 and is_array($url_data['start_loc'])) { $bounds = $url_data['start_loc']; if (count($bounds) == 2 and is_numeric($bounds[0]) and is_numeric($bounds[1])) { self::$params['radius'] = array('distance' => intval($url_data['radius']), 'latitude' => $bounds[0], 'longitude' => $bounds[1]); } } } // // Check for incident date range parameters // if (isset($url_data['from']) and isset($url_data['to'])) { $date_from = date('Y-m-d', strtotime($url_data['from'])); $date_to = date('Y-m-d', strtotime($url_data['to'])); array_push(self::$params, 'i.incident_date >= "' . $date_from . '"', 'i.incident_date <= "' . $date_to . '"'); } /** * --------------------------- * NOTES: E.Kala July 13, 2011 * --------------------------- * Additional checks for date parameters specified in timestamp format * This only affects those submitted from the main page */ // Start Date if (isset($_GET['s']) and intval($_GET['s']) > 0) { $start_date = intval($_GET['s']); array_push(self::$params, 'i.incident_date >= "' . date("Y-m-d H:i:s", $start_date) . '"'); } // End Date if (isset($_GET['e']) and intval($_GET['e'])) { $end_date = intval($_GET['e']); array_push(self::$params, 'i.incident_date <= "' . date("Y-m-d H:i:s", $end_date) . '"'); } // // Check for media type parameter // if (isset($url_data['m']) and is_array($url_data['m'])) { // An array of media filters has been specified // Validate the media types $media_types = array(); foreach ($url_data['m'] as $media_type) { if (intval($media_type) > 0) { $media_types[] = intval($media_type); } } if (count($media_types) > 0) { array_push(self::$params, 'i.id IN (SELECT DISTINCT incident_id FROM ' . $table_prefix . 'media WHERE media_type IN (' . implode(",", $media_types) . '))'); } } elseif (isset($url_data['m']) and !is_array($url_data['m'])) { // A single media filter has been specified $media_type = $url_data['m']; // Sanitization if (intval($media_type) > 0) { array_push(self::$params, 'i.id IN (SELECT DISTINCT incident_id FROM ' . $table_prefix . 'media WHERE media_type = ' . $media_type . ')'); } } // // Check if the verification status has been specified // if (isset($url_data['v']) and is_array($url_data['v'])) { $verified_status = array(); foreach ($url_data['v'] as $verified) { if (intval($verified) >= 0) { $verified_status[] = intval($verified); } } if (count($verified_status) > 0) { array_push(self::$params, 'i.incident_verified IN (' . implode(",", $verified_status) . ')'); } } elseif (isset($url_data['v']) and !is_array($url_data['v']) and intval($url_data) >= 0) { array_push(self::$param, 'i.incident_verified = ' . intval($url_data['v'])); } // // Check if they're filtering over custom form fields // if (isset($url_data['cff']) and is_array($url_data['cff'])) { $where_text = ""; $i = 0; foreach ($url_data['cff'] as $field) { $field_id = $field[0]; if (intval($field_id) < 1) { break; } $field_value = $field[1]; if (is_array($field_value)) { $field_value = implode(",", $field_value); } $i++; if ($i > 1) { $where_text .= " OR "; } $where_text .= "(form_field_id = " . intval($field_id) . " AND form_response = '" . Database::instance()->escape_str(trim($field_value)) . "')"; } // Make sure there was some valid input in there if ($i > 0) { array_push(self::$params, 'i.id IN (SELECT DISTINCT incident_id FROM ' . $table_prefix . 'form_response WHERE ' . $where_text . ')'); } } // End of handling cff // In case a plugin or something wants to get in on the parameter fetching fun Event::run('ushahidi_filter.fetch_incidents_set_params', self::$params); //> END PARAMETER FETCH // Fetch all the incidents $all_incidents = Incident_Model::get_incidents(self::$params); if ($paginate) { // Set up pagination $page_limit = intval($items_per_page) > 0 ? $items_per_page : intval(Kohana::config('settings.items_per_page')); $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => $page_limit, 'total_items' => $all_incidents->count())); // Return paginated results return Incident_Model::get_incidents(self::$params, $pagination); } else { // Return return $all_incidents; } }
/** * Helper function to fetch and optionally paginate the list of * incidents/reports via the Incident Model using one or all of the * following URL parameters * - category * - location bounds * - incident mode * - media * - location radius * * @param bool $paginate Optionally paginate the incidents - Default is FALSE * @param int $items_per_page No. of items to show per page * @return Database_Result */ public static function fetch_incidents($paginate = FALSE, $items_per_page = 0) { // Reset the paramters self::$params = array(); // Initialize the category id $category_id = 0; $table_prefix = Kohana::config('database.default.table_prefix'); // Fetch the URL data into a local variable $url_data = $_GET; // Split selected parameters on "," // For simplicity, always turn them into arrays even theres just one value $exclude_params = array('c', 'v', 'm', 'mode', 'sw', 'ne', 'start_loc'); foreach ($url_data as $key => $value) { if (in_array($key, $exclude_params) and !is_array($value)) { $url_data[$key] = explode(",", $value); } } //> BEGIN PARAMETER FETCH // // Check for the category parameter // if (isset($url_data['c']) and is_array($url_data['c'])) { // Sanitize each of the category ids $category_ids = array(); foreach ($url_data['c'] as $c_id) { if (intval($c_id) > 0) { $category_ids[] = intval($c_id); } } // Check if there are any category ids if (count($category_ids) > 0) { $category_ids = implode(",", $category_ids); array_push(self::$params, '(c.id IN (' . $category_ids . ') OR c.parent_id IN (' . $category_ids . '))', 'c.category_visible = 1'); } } // // Incident modes // if (isset($url_data['mode']) and is_array($url_data['mode'])) { $incident_modes = array(); // Sanitize the modes foreach ($url_data['mode'] as $mode) { if (intval($mode) > 0) { $incident_modes[] = intval($mode); } } // Check if any modes exist and add them to the parameter list if (count($incident_modes) > 0) { array_push(self::$params, 'i.incident_mode IN (' . implode(",", $incident_modes) . ')'); } } // // Location bounds parameters // if (isset($url_data['sw']) and isset($url_data['ne'])) { $southwest = $url_data['sw']; $northeast = $url_data['ne']; if (count($southwest) == 2 and count($northeast) == 2) { $lon_min = (double) $southwest[0]; $lon_max = (double) $northeast[0]; $lat_min = (double) $southwest[1]; $lat_max = (double) $northeast[1]; // Add the location conditions to the parameter list array_push(self::$params, 'l.latitude >= ' . $lat_min, 'l.latitude <= ' . $lat_max, 'l.longitude >= ' . $lon_min, 'l.longitude <= ' . $lon_max); } } // // Location bounds - based on start location and radius // if (isset($url_data['radius']) and isset($url_data['start_loc'])) { //if $url_data['start_loc'] is just comma delimited strings, then make it into an array if (intval($url_data['radius']) > 0 and is_array($url_data['start_loc'])) { $bounds = $url_data['start_loc']; if (count($bounds) == 2 and is_numeric($bounds[0]) and is_numeric($bounds[1])) { self::$params['radius'] = array('distance' => intval($url_data['radius']), 'latitude' => $bounds[0], 'longitude' => $bounds[1]); } } } // // Check for incident date range parameters // if (!empty($url_data['from'])) { // Add hours/mins/seconds so we still get reports if from and to are the same day $date_from = date('Y-m-d 00:00:00', strtotime($url_data['from'])); array_push(self::$params, 'i.incident_date >= "' . $date_from . '"'); } if (!empty($url_data['to'])) { // Add hours/mins/seconds so we still get reports if from and to are the same day $date_to = date('Y-m-d 23:59:59', strtotime($url_data['to'])); array_push(self::$params, 'i.incident_date <= "' . $date_to . '"'); } // Additional checks for date parameters specified in timestamp format // This only affects those submitted from the main page // Start Date if (isset($_GET['s']) and intval($_GET['s']) > 0) { $start_date = intval($_GET['s']); array_push(self::$params, 'i.incident_date >= "' . date("Y-m-d H:i:s", $start_date) . '"'); } // End Date if (isset($_GET['e']) and intval($_GET['e'])) { $end_date = intval($_GET['e']); array_push(self::$params, 'i.incident_date <= "' . date("Y-m-d H:i:s", $end_date) . '"'); } // // Check for media type parameter // if (isset($url_data['m']) and is_array($url_data['m'])) { // An array of media filters has been specified // Validate the media types $media_types = array(); foreach ($url_data['m'] as $media_type) { if (intval($media_type) > 0) { $media_types[] = intval($media_type); } } if (count($media_types) > 0) { array_push(self::$params, 'i.id IN (SELECT DISTINCT incident_id FROM ' . $table_prefix . 'media WHERE media_type IN (' . implode(",", $media_types) . '))'); } } // // Check if the verification status has been specified // if (isset($url_data['v']) and is_array($url_data['v'])) { $verified_status = array(); foreach ($url_data['v'] as $verified) { if (intval($verified) >= 0) { $verified_status[] = intval($verified); } } if (count($verified_status) > 0) { array_push(self::$params, 'i.incident_verified IN (' . implode(",", $verified_status) . ')'); } } // // Check if they're filtering over custom form fields // if (isset($url_data['cff']) and is_array($url_data['cff'])) { $where_text = ""; $i = 0; foreach ($url_data['cff'] as $field) { $field_id = $field[0]; if (intval($field_id) < 1) { continue; } $field_value = $field[1]; if (is_array($field_value)) { $field_value = implode(",", $field_value); } $i++; if ($i > 1) { $where_text .= " OR "; } $where_text .= "(form_field_id = " . intval($field_id) . " AND form_response = '" . Database::instance()->escape_str(trim($field_value)) . "')"; } // Make sure there was some valid input in there if ($i > 0) { // Get the valid IDs - faster in a separate query as opposed // to a subquery within the main query $db = new Database(); $rows = $db->query('SELECT DISTINCT incident_id FROM ' . $table_prefix . 'form_response WHERE ' . $where_text); $incident_ids = ''; foreach ($rows as $row) { if ($incident_ids != '') { $incident_ids .= ','; } $incident_ids .= $row->incident_id; } //make sure there are IDs found if ($incident_ids != '') { array_push(self::$params, 'i.id IN (' . $incident_ids . ')'); } else { array_push(self::$params, 'i.id IN (0)'); } } } // End of handling cff // In case a plugin or something wants to get in on the parameter fetching fun Event::run('ushahidi_filter.fetch_incidents_set_params', self::$params); //> END PARAMETER FETCH // Check for order and sort params $order_field = NULL; $sort = NULL; $order_options = array('title' => 'i.incident_title', 'date' => 'i.incident_date', 'id' => 'i.id'); if (isset($url_data['order']) and isset($order_options[$url_data['order']])) { $order_field = $order_options[$url_data['order']]; } if (isset($url_data['sort'])) { $sort = strtoupper($url_data['sort']) == 'ASC' ? 'ASC' : 'DESC'; } if ($paginate) { // Fetch incident count $incident_count = Incident_Model::get_incidents(self::$params, false, $order_field, $sort, TRUE); // Set up pagination $page_limit = intval($items_per_page) > 0 ? $items_per_page : intval(Kohana::config('settings.items_per_page')); $total_items = $incident_count->current() ? $incident_count->current()->report_count : 0; $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => $page_limit, 'total_items' => $total_items)); Event::run('ushahidi_filter.pagination', $pagination); self::$pagination = $pagination; // Return paginated results return Incident_Model::get_incidents(self::$params, self::$pagination, $order_field, $sort); } else { // Return return Incident_Model::get_incidents(self::$params, false, $order_field, $sort); } }
/** * Generic function to get reports by given set of parameters * * @param string $where SQL where clause * @param int $limit No. of records to return - set to 20 by default * @return string XML or JSON string */ public function _get_incidents($where = array()) { // STEP 1. // Get the incidents $items = Incident_Model::get_incidents($where, $this->list_limit, $this->order_field, $this->sort); //No record found. if ($items->count() == 0) { return $this->response(4, $this->error_messages); } // Records found - proceed // Set the no. of records returned $this->record_count = $items->count(); // Will hold the XML/JSON string to return $ret_json_or_xml = ''; $json_reports = array(); $json_report_media = array(); $json_report_categories = array(); $json_incident_media = array(); $upload_path = str_replace("media/uploads/", "", Kohana::config('upload.relative_directory') . "/"); //XML elements $xml = new XmlWriter(); $xml->openMemory(); $xml->startDocument('1.0', 'UTF-8'); $xml->startElement('response'); $xml->startElement('payload'); $xml->writeElement('domain', $this->domain); $xml->startElement('incidents'); // Records found, proceed // Store the incident ids $incidents_ids = array(); foreach ($items as $item) { $incident_ids[] = $item->incident_id; } // // STEP 2. // Fetch the incident categories // $this->query = "SELECT c.category_title AS categorytitle, ic.incident_id, " . "c.id AS cid, c.category_image_thumb AS categorythumb, " . "d.decayimage_thumb AS decayimagethumb " . "FROM " . $this->table_prefix . "category AS c " . "INNER JOIN " . $this->table_prefix . "incident_category AS ic ON ic.category_id = c.id " . "LEFT JOIN " . $this->table_prefix . "decayimage as d ON c.id = d.category_id " . "WHERE ic.incident_id IN (" . implode(',', $incident_ids) . ")"; // Execute the query $incident_categories = $this->db->query($this->query); // To hold the incident category items $category_items = array(); // Temporary counter $i = 1; // Fetch items into array foreach ($incident_categories as $incident_category) { $category_items[$incident_category->incident_id][$i]['cid'] = $incident_category->cid; $category_items[$incident_category->incident_id][$i]['categorytitle'] = $incident_category->categorytitle; $category_items[$incident_category->incident_id][$i]['categorythumb'] = $incident_category->categorythumb; $category_items[$incident_category->incident_id][$i]['decayimagethumb'] = $incident_category->decayimagethumb; $i++; } // Free temporary variables from memory unset($incident_categories); // // STEP 3. // Fetch the media associated with all the incidents // $this->query = "SELECT i.id AS incident_id, m.id AS mediaid, m.media_title AS mediatitle, " . "m.media_type AS mediatype, m.media_link AS medialink, m.media_thumb AS mediathumb " . "FROM " . $this->table_prefix . "media AS m " . "INNER JOIN " . $this->table_prefix . "incident AS i ON i.id = m.incident_id " . "WHERE i.id IN (" . implode(",", $incident_ids) . ")"; $media_items_result = $this->db->query($this->query); // To store the fetched media items $media_items = array(); // Reset the temporary counter $i = 1; // Fetch items into array foreach ($media_items_result as $media_item) { $media_items[$media_item->incident_id][$i]['mediaid'] = $media_item->mediaid; $media_items[$media_item->incident_id][$i]['mediatitle'] = $media_item->mediatitle; $media_items[$media_item->incident_id][$i]['mediatype'] = $media_item->mediatype; $media_items[$media_item->incident_id][$i]['medialink'] = $media_item->medialink; $media_items[$media_item->incident_id][$i]['mediathumb'] = $media_item->mediathumb; $i++; } // Free temporary variables unset($media_items_result, $i); // // STEP 4. // Fetch the comments associated with the incidents // if ($this->comments) { $this->query = "SELECT id, incident_id, comment_author, comment_email, " . "comment_description, comment_rating, comment_date " . "FROM " . $this->table_prefix . "comment AS c " . "WHERE c.incident_id IN (" . implode(',', $incident_ids) . ")"; // Execute the query $incident_comments = $this->db->query($this->query); // To hold the incident category items $comment_items = array(); // Temporary counter $i = 1; // Fetch items into array foreach ($incident_comments as $incident_comment) { $comment_items[$incident_comment->incident_id][$i]['id'] = $incident_comment->id; $comment_items[$incident_comment->incident_id][$i]['incident_id'] = $incident_comment->incident_id; $comment_items[$incident_comment->incident_id][$i]['comment_author'] = $incident_comment->comment_author; $comment_items[$incident_comment->incident_id][$i]['comment_email'] = $incident_comment->comment_email; $comment_items[$incident_comment->incident_id][$i]['comment_description'] = $incident_comment->comment_description; $comment_items[$incident_comment->incident_id][$i]['comment_rating'] = $incident_comment->comment_rating; $comment_items[$incident_comment->incident_id][$i]['comment_date'] = $incident_comment->comment_date; $i++; } // Free temporary variables from memory unset($incident_comments); } // // STEP 5. // Return XML // foreach ($items as $item) { // Build xml file $xml->startElement('incident'); $xml->writeElement('id', $item->incident_id); $xml->writeElement('title', $item->incident_title); $xml->writeElement('description', $item->incident_description); $xml->writeElement('date', $item->incident_date); $xml->writeElement('mode', $item->incident_mode); $xml->writeElement('active', $item->incident_active); $xml->writeElement('verified', $item->incident_verified); $xml->startElement('location'); $xml->writeElement('id', $item->location_id); $xml->writeElement('name', $item->location_name); $xml->writeElement('latitude', $item->latitude); $xml->writeElement('longitude', $item->longitude); $xml->endElement(); $xml->startElement('categories'); $json_report_categories[$item->incident_id] = array(); // Check if the incident id exists if (isset($category_items[$item->incident_id])) { foreach ($category_items[$item->incident_id] as $category_item) { if ($this->response_type == 'json') { $category = array("id" => $category_item['cid'], "title" => $category_item['categorytitle']); $category["icon"] = url::base() . Kohana::config('upload.relative_directory') . '/' . $category_item['categorythumb']; if ($category_item['decayimagethumb']) { if ($category_item['decayimagethumb'] == $this->default_decayimage_thumb) { $category['decayimage'] = url::site() . '/plugins/decayimage/images/' . $category_item['decayimagethumb']; } else { $category['decayimage'] = url::base() . Kohana::config('upload.relative_directory') . '/' . $category_item['decayimagethumb']; } } $json_report_categories[$item->incident_id][] = array("category" => $category); } else { $xml->startElement('category'); $xml->writeElement('id', $category_item['cid']); $xml->writeElement('title', $category_item['categorytitle']); $xml->endElement(); } } } // End categories $xml->endElement(); $xml->startElement('comments'); $json_report_comments[$item->incident_id] = array(); // Check if the incident id exists if (isset($comment_items[$item->incident_id])) { foreach ($comment_items[$item->incident_id] as $comment_item) { if ($this->response_type == 'json') { $json_report_comments[$item->incident_id][] = array("comment" => $comment_item); } else { $xml->startElement('comment'); $xml->writeElement('id', $comment_item['id']); $xml->writeElement('comment_author', $comment_item['comment_author']); $xml->writeElement('comment_email', $comment_item['comment_email']); $xml->writeElement('comment_description', $comment_item['comment_description']); $xml->writeElement('comment_rating', $comment_item['comment_rating']); $xml->writeElement('comment_date', $comment_item['comment_date']); $xml->endElement(); } } } // End comments $xml->endElement(); $json_report_media[$item->incident_id] = array(); if (count($media_items) > 0) { if (isset($media_items[$item->incident_id]) and count($media_items[$item->incident_id]) > 0) { $xml->startElement('mediaItems'); foreach ($media_items[$item->incident_id] as $media_item) { $url_prefix = url::base() . Kohana::config('upload.relative_directory') . '/'; // If our media is not an image, we don't need to show an upload path if ($media_item['mediatype'] != 1) { $upload_path = ''; } elseif ($media_item['mediatype'] == 1 and valid::url($media_item['medialink']) == TRUE) { // If our media is an img and is a valid URL, don't show the upload path or prefix $upload_path = ''; $url_prefix = ''; } if ($this->response_type == 'json') { $json_report_media[$item->incident_id][] = array("id" => $media_item['mediaid'], "type" => $media_item['mediatype'], "link" => $upload_path . $media_item['medialink'], "thumb" => $upload_path . $media_item['mediathumb']); // If we are look at certain types of media, add some fields if ($media_item['mediatype'] == 1) { // Grab that last key up there $add_to_key = key($json_report_media[$item->incident_id]) + 1; // Give a full absolute URL to the image $json_report_media[$item->incident_id][$add_to_key]["thumb_url"] = $url_prefix . $upload_path . $media_item['mediathumb']; $json_report_media[$item->incident_id][$add_to_key]["link_url"] = $url_prefix . $upload_path . $media_item['medialink']; } } else { $xml->startElement('media'); if ($media_item['mediaid'] != "") { $xml->writeElement('id', $media_item['mediaid']); } if ($media_item['mediatitle'] != "") { $xml->writeElement('title', $media_item['mediatitle']); } if ($media_item['mediatype'] != "") { $xml->writeElement('type', $media_item['mediatype']); } if ($media_item['medialink'] != "") { $xml->writeElement('link', $upload_path . $media_item['medialink']); } if ($media_item['mediathumb'] != "") { $xml->writeElement('thumb', $upload_path . $media_item['mediathumb']); } if ($media_item['mediathumb'] != "" and $media_item['mediatype'] == 1) { $add_to_key = key($json_report_media[$item->incident_id]) + 1; $xml->writeElement('thumb_url', $url_prefix . $upload_path . $media_item['mediathumb']); $xml->writeElement('link_url', $url_prefix . $upload_path . $media_item['medialink']); } $xml->endElement(); } } $xml->endElement(); // Media } } $xml->endElement(); // End incident // Check for response type if ($this->response_type == 'json') { $json_reports[] = array("incident" => array("incidentid" => $item->incident_id, "incidenttitle" => $item->incident_title, "incidentdescription" => $item->incident_description, "incidentdate" => $item->incident_date, "incidentmode" => $item->incident_mode, "incidentactive" => $item->incident_active, "incidentverified" => $item->incident_verified, "locationid" => $item->location_id, "locationname" => $item->location_name, "locationlatitude" => $item->latitude, "locationlongitude" => $item->longitude, "incidenthasended" => $this->incidentHasEnded($item->incident_id)), "categories" => $json_report_categories[$item->incident_id], "media" => $json_report_media[$item->incident_id], "comments" => $json_report_comments[$item->incident_id]); } } // Get the default decayimage icon $decayimage_default_icon = ORM::factory('decayimage', 1); if ($decayimage_default_icon->decayimage_thumb == $this->default_decayimage_thumb) { $decayimage_default_icon = url::site() . '/plugins/decayimage/images/' . $decayimage_default_icon->decayimage_thumb; } else { $decayimage_default_icon = $prefix . '/' . $decayimage_default_icon->decayimage_thumb; } // Create the JSON array $data = array("payload" => array("domain" => $this->domain, "incidents" => $json_reports, "decayimage_default_icon" => $decayimage_default_icon), "error" => $this->api_service->get_error_msg(0)); if ($this->response_type == 'json') { return $this->array_as_json($data); } else { $xml->endElement(); //end incidents $xml->endElement(); // end payload $xml->startElement('error'); $xml->writeElement('code', 0); $xml->writeElement('message', 'No Error'); $xml->endElement(); //end error $xml->endElement(); // end response return $xml->outputMemory(true); } }
/** * Lists the reports. * * @param int $page */ public function index($page = 1) { // If user doesn't have access, redirect to dashboard if (!admin::permissions($this->user, "reports_view")) { url::redirect(url::site() . 'admin/dashboard'); } $this->template->content = new View('admin/reports'); $this->template->content->title = Kohana::lang('ui_admin.reports'); //hook into the event for the reports::fetch_incidents() method Event::add('ushahidi_filter.fetch_incidents_set_params', array($this, '_add_incident_filters')); $status = "0"; if (!empty($_GET['status'])) { $status = $_GET['status']; if (strtolower($status) == 'a') { array_push($this->params, 'i.incident_active = 0'); } elseif (strtolower($status) == 'v') { array_push($this->params, 'i.incident_verified = 0'); } else { $status = "0"; } } // Get Search Keywords (If Any) if (isset($_GET['k'])) { // Brute force input sanitization // Phase 1 - Strip the search string of all non-word characters $keyword_raw = isset($_GET['k']) ? preg_replace('#/\\w+/#', '', $_GET['k']) : ""; // Strip any HTML tags that may have been missed in Phase 1 $keyword_raw = strip_tags($keyword_raw); // Phase 3 - Invoke Kohana's XSS cleaning mechanism just incase an outlier wasn't caught // in the first 2 steps $keyword_raw = $this->input->xss_clean($keyword_raw); $filter = " (" . $this->_get_searchstring($keyword_raw) . ")"; array_push($this->params, $filter); } else { $keyword_raw = ""; } // Check, has the form been submitted? $form_error = FALSE; $form_saved = FALSE; $form_action = ""; if ($_POST) { $post = Validation::factory($_POST); // Add some filters $post->pre_filter('trim', TRUE); // Add some rules, the input field, followed by a list of checks, carried out in order $post->add_rules('action', 'required', 'alpha', 'length[1,1]'); $post->add_rules('incident_id.*', 'required', 'numeric'); if ($post->validate()) { // Approve Action if ($post->action == 'a') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); if ($update->loaded == TRUE) { $update->incident_active = $update->incident_active == 0 ? '1' : '0'; // Tag this as a report that needs to be sent out as an alert if ($update->incident_alert_status != '2') { // 2 = report that has had an alert sent $update->incident_alert_status = '1'; } $update->save(); $verify = new Verify_Model(); $verify->incident_id = $item; $verify->verified_status = '1'; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); // Action::report_approve - Approve a Report Event::run('ushahidi_action.report_approve', $update); } } $form_action = strtoupper(Kohana::lang('ui_admin.approved')); } elseif ($post->action == 'u') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); if ($update->loaded == TRUE) { $update->incident_active = '0'; // If Alert hasn't been sent yet, disable it if ($update->incident_alert_status == '1') { $update->incident_alert_status = '0'; } $update->save(); $verify = new Verify_Model(); $verify->incident_id = $item; $verify->verified_status = '0'; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); // Action::report_unapprove - Unapprove a Report Event::run('ushahidi_action.report_unapprove', $update); } } $form_action = strtoupper(Kohana::lang('ui_admin.unapproved')); } elseif ($post->action == 'v') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); $verify = new Verify_Model(); if ($update->loaded == TRUE) { if ($update->incident_verified == '1') { $update->incident_verified = '0'; $verify->verified_status = '0'; } else { $update->incident_verified = '1'; $verify->verified_status = '2'; } $update->save(); $verify->incident_id = $item; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); } } // Set the form action $form_action = strtoupper(Kohana::lang('ui_admin.verified_unverified')); } elseif ($post->action == 'd') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); if ($update->loaded == TRUE) { $incident_id = $update->id; $location_id = $update->location_id; $update->delete(); // Delete Location ORM::factory('location')->where('id', $location_id)->delete_all(); // Delete Categories ORM::factory('incident_category')->where('incident_id', $incident_id)->delete_all(); // Delete Translations ORM::factory('incident_lang')->where('incident_id', $incident_id)->delete_all(); // Delete Photos From Directory foreach (ORM::factory('media')->where('incident_id', $incident_id)->where('media_type', 1) as $photo) { deletePhoto($photo->id); } // Delete Media ORM::factory('media')->where('incident_id', $incident_id)->delete_all(); // Delete Sender ORM::factory('incident_person')->where('incident_id', $incident_id)->delete_all(); // Delete relationship to SMS message $updatemessage = ORM::factory('message')->where('incident_id', $incident_id)->find(); if ($updatemessage->loaded == TRUE) { $updatemessage->incident_id = 0; $updatemessage->save(); } // Delete Comments ORM::factory('comment')->where('incident_id', $incident_id)->delete_all(); // Delete form responses ORM::factory('form_response')->where('incident_id', $incident_id)->delete_all(); // Action::report_delete - Deleted a Report Event::run('ushahidi_action.report_delete', $incident_id); } } $form_action = strtoupper(Kohana::lang('ui_admin.deleted')); } $form_saved = TRUE; } else { $form_error = TRUE; } } // Fetch all incidents $all_incidents = reports::fetch_incidents(); // Pagination $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => (int) Kohana::config('settings.items_per_page'), 'total_items' => $all_incidents->count())); Event::run('ushahidi_filter.pagination', $pagination); // Reports $incidents = Incident_Model::get_incidents(reports::$params, $pagination); Event::run('ushahidi_filter.filter_incidents', $incidents); $this->template->content->countries = Country_Model::get_countries_list(); $this->template->content->incidents = $incidents; $this->template->content->pagination = $pagination; $this->template->content->form_error = $form_error; $this->template->content->form_saved = $form_saved; $this->template->content->form_action = $form_action; // Total Reports $this->template->content->total_items = $pagination->total_items; // Status Tab $this->template->content->status = $status; // Javascript Header $this->template->js = new View('admin/reports_js'); }
/** * Helper function to fetch and optionally paginate the list of * incidents/reports via the Incident Model using one or all of the * following URL parameters * - category * - location bounds * - incident mode * - media * - location radius * JP: added one additional URL parameter: * - search * * @param bool $paginate Optionally paginate the incidents - Default is FALSE * @param int $items_per_page No. of items to show per page * @return Database_Result */ public static function fetch_incidents($paginate = FALSE, $items_per_page = 0) { // Reset the paramters self::$params = array(); // Initialize the category id $category_id = 0; $table_prefix = Kohana::config('database.default.table_prefix'); // Fetch the URL data into a local variable $url_data = $_GET; // Split selected parameters on "," // For simplicity, always turn them into arrays even theres just one value $exclude_params = array('c', 'v', 'm', 'mode', 'sw', 'ne', 'start_loc'); foreach ($url_data as $key => $value) { if (in_array($key, $exclude_params) and !is_array($value)) { $url_data[$key] = explode(",", $value); } } //> BEGIN PARAMETER FETCH // // Check for the category parameter // if (isset($url_data['c']) and is_array($url_data['c'])) { // Sanitize each of the category ids $category_ids = array(); foreach ($url_data['c'] as $c_id) { if (intval($c_id) > 0) { $category_ids[] = intval($c_id); } } // Check if there are any category ids if (count($category_ids) > 0) { $category_ids = implode(",", $category_ids); array_push(self::$params, '(c.id IN (' . $category_ids . ') OR c.parent_id IN (' . $category_ids . '))', 'c.category_visible = 1'); } } // // Incident modes // if (isset($url_data['mode']) and is_array($url_data['mode'])) { $incident_modes = array(); // Sanitize the modes foreach ($url_data['mode'] as $mode) { if (intval($mode) > 0) { $incident_modes[] = intval($mode); } } // Check if any modes exist and add them to the parameter list if (count($incident_modes) > 0) { array_push(self::$params, 'i.incident_mode IN (' . implode(",", $incident_modes) . ')'); } } // // Location bounds parameters // if (isset($url_data['sw']) and isset($url_data['ne'])) { $southwest = $url_data['sw']; $northeast = $url_data['ne']; if (count($southwest) == 2 and count($northeast) == 2) { $lon_min = (double) $southwest[0]; $lon_max = (double) $northeast[0]; $lat_min = (double) $southwest[1]; $lat_max = (double) $northeast[1]; // Add the location conditions to the parameter list array_push(self::$params, 'l.latitude >= ' . $lat_min, 'l.latitude <= ' . $lat_max, 'l.longitude >= ' . $lon_min, 'l.longitude <= ' . $lon_max); } } // // Location bounds - based on start location and radius // if (isset($url_data['radius']) and isset($url_data['start_loc'])) { //if $url_data['start_loc'] is just comma delimited strings, then make it into an array if (intval($url_data['radius']) > 0 and is_array($url_data['start_loc'])) { $bounds = $url_data['start_loc']; if (count($bounds) == 2 and is_numeric($bounds[0]) and is_numeric($bounds[1])) { self::$params['radius'] = array('distance' => intval($url_data['radius']), 'latitude' => $bounds[0], 'longitude' => $bounds[1]); } } } // // Check for incident date range parameters // if (!empty($url_data['from'])) { // Add hours/mins/seconds so we still get reports if from and to are the same day $date_from = date('Y-m-d 00:00:00', strtotime($url_data['from'])); array_push(self::$params, 'i.incident_date >= "' . $date_from . '"'); } if (!empty($url_data['to'])) { // Add hours/mins/seconds so we still get reports if from and to are the same day $date_to = date('Y-m-d 23:59:59', strtotime($url_data['to'])); array_push(self::$params, 'i.incident_date <= "' . $date_to . '"'); } // Additional checks for date parameters specified in timestamp format // This only affects those submitted from the main page // Start Date if (isset($_GET['s']) and intval($_GET['s']) > 0) { $start_date = intval($_GET['s']); array_push(self::$params, 'i.incident_date >= "' . date("Y-m-d H:i:s", $start_date) . '"'); } // End Date if (isset($_GET['e']) and intval($_GET['e'])) { $end_date = intval($_GET['e']); array_push(self::$params, 'i.incident_date <= "' . date("Y-m-d H:i:s", $end_date) . '"'); } // // Check for media type parameter // if (isset($url_data['m']) and is_array($url_data['m'])) { // An array of media filters has been specified // Validate the media types $media_types = array(); foreach ($url_data['m'] as $media_type) { if (intval($media_type) > 0) { $media_types[] = intval($media_type); } } if (count($media_types) > 0) { array_push(self::$params, 'i.id IN (SELECT DISTINCT incident_id FROM ' . $table_prefix . 'media WHERE media_type IN (' . implode(",", $media_types) . '))'); } } // // Check if the verification status has been specified // if (isset($url_data['v']) and is_array($url_data['v'])) { $verified_status = array(); foreach ($url_data['v'] as $verified) { if (intval($verified) >= 0) { $verified_status[] = intval($verified); } } if (count($verified_status) > 0) { array_push(self::$params, 'i.incident_verified IN (' . implode(",", $verified_status) . ')'); } } //Search for Keyword in all Custom Form Fields if (isset($url_data['custom_field_0'])) { $keywords = $url_data['custom_field_0']; $db = new Database(); $rows = $db->query('SELECT DISTINCT incident_id FROM ' . $table_prefix . 'form_response WHERE form_response LIKE "%' . $keywords . '%"'); $incident_ids = ''; foreach ($rows as $row) { if ($incident_ids != '') { $incident_ids .= ','; } $incident_ids .= $row->incident_id; } //make sure there are IDs found if ($incident_ids != '') { array_push(self::$params, 'i.id IN (' . $incident_ids . ')'); } else { array_push(self::$params, 'i.id IN (0)'); } } // End of handling cff // // Check if they're filtering over custom form fields // if (isset($url_data['cff']) and is_array($url_data['cff'])) { $where_text = ""; $i = 0; foreach ($url_data['cff'] as $field) { $field_id = $field[0]; if (intval($field_id) < 1) { continue; } $field_value = $field[1]; if (is_array($field_value)) { $field_value = implode(",", $field_value); } $i++; if ($i > 1) { $where_text .= " OR "; } $where_text .= "(form_field_id = " . intval($field_id) . " AND form_response LIKE '%" . Database::instance()->escape_str(trim($field_value)) . "%')"; } // Make sure there was some valid input in there if ($i > 0) { // Get the valid IDs - faster in a separate query as opposed // to a subquery within the main query $db = new Database(); $rows = $db->query('SELECT DISTINCT incident_id FROM ' . $table_prefix . 'form_response WHERE ' . $where_text); $incident_ids = ''; foreach ($rows as $row) { if ($incident_ids != '') { $incident_ids .= ','; } $incident_ids .= $row->incident_id; } //make sure there are IDs found if ($incident_ids != '') { array_push(self::$params, 'i.id IN (' . $incident_ids . ')'); } else { array_push(self::$params, 'i.id IN (0)'); } } } // End of handling cff // JP: Check if the reports are being filtered via search. if (isset($url_data['q']) and is_string($url_data['q'])) { $filter_search_query = $url_data['q']; if (!empty($filter_search_query)) { $search_query = ""; $keyword_string = ""; $where_string = ""; $plus = ""; $or = ""; $search_info = ""; $html = ""; $pagination = ""; // Stop words that we won't search for // Add words as needed!! $stop_words = array('the', 'and', 'a', 'to', 'of', 'in', 'i', 'is', 'that', 'it', 'on', 'you', 'this', 'for', 'but', 'with', 'are', 'have', 'be', 'at', 'or', 'as', 'was', 'so', 'if', 'out', 'not'); // Phase 1 - Fetch the search string and perform initial sanitization $keyword_raw = preg_replace('#/\\w+/#', '', $filter_search_query); // Phase 2 - Strip the search string of any HTML and PHP tags that may be present for additional safety $keyword_raw = strip_tags($keyword_raw); // Phase 3 - Apply Kohana's XSS cleaning mechanism $keyword_raw = security::xss_clean($keyword_raw); // Database instance $db = new Database(); $keywords = explode(' ', $keyword_raw); if (is_array($keywords) and !empty($keywords)) { array_change_key_case($keywords, CASE_LOWER); $i = 0; foreach ($keywords as $value) { if (!in_array($value, $stop_words) and !empty($value)) { // Escape the string for query safety $chunk = $db->escape_str($value); if ($i > 0) { $plus = ' + '; $or = ' OR '; } $where_string = $where_string . $or . "(incident_title LIKE '%{$chunk}%' OR incident_description LIKE '%{$chunk}%')"; $i++; } } if (!empty($keyword_string) and !empty($where_string)) { // Limit the result set to only those reports that have been approved $where_string = '(' . $where_string . ') AND incident_active = 1'; $search_query = "SELECT *, (" . $keyword_string . ") AS relevance FROM " . $table_prefix . "incident " . "WHERE " . $where_string . " " . "ORDER BY relevance DESC LIMIT ?, ?"; } } $rows = $db->query('SELECT DISTINCT id FROM ' . $table_prefix . 'incident WHERE ' . $where_string); $incident_ids = ''; foreach ($rows as $row) { if ($incident_ids != '') { $incident_ids .= ','; } $incident_ids .= $row->id; } //make sure there are IDs found if ($incident_ids != '') { array_push(self::$params, 'i.id IN (' . $incident_ids . ')'); } else { array_push(self::$params, 'i.id IN (0)'); } } } // In case a plugin or something wants to get in on the parameter fetching fun Event::run('ushahidi_filter.fetch_incidents_set_params', self::$params); //> END PARAMETER FETCH // Check for order and sort params $order_field = NULL; $sort = NULL; $order_options = array('title' => 'i.incident_title', 'date' => 'i.incident_date', 'id' => 'i.id'); if (isset($url_data['order']) and isset($order_options[$url_data['order']])) { $order_field = $order_options[$url_data['order']]; } if (isset($url_data['sort'])) { $sort = strtoupper($url_data['sort']) == 'ASC' ? 'ASC' : 'DESC'; } if ($paginate) { // Fetch incident count $incident_count = Incident_Model::get_incidents(self::$params, false, $order_field, $sort, TRUE); // Set up pagination $page_limit = intval($items_per_page) > 0 ? $items_per_page : intval(Kohana::config('settings.items_per_page')); $total_items = $incident_count->current() ? $incident_count->current()->report_count : 0; $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => $page_limit, 'total_items' => $total_items)); Event::run('ushahidi_filter.pagination', $pagination); self::$pagination = $pagination; // Return paginated results return Incident_Model::get_incidents(self::$params, self::$pagination, $order_field, $sort); } else { // Return return Incident_Model::get_incidents(self::$params, false, $order_field, $sort); } }
/** * Generic function to get reports by given set of parameters * * @param string $where SQL where clause * @return string XML or JSON string */ public function _get_incidents($where = array()) { // STEP 1. // Get the incidents $items = Incident_Model::get_incidents($where, $this->list_limit, $this->order_field, $this->sort); //No record found. if ($items->count() == 0) { return $this->response(4, $this->error_messages); } // Records found - proceed // Set the no. of records returned $this->record_count = $items->count(); // Will hold the XML/JSON string to return $ret_json_or_xml = ''; $json_reports = array(); $json_report_media = array(); $json_report_categories = array(); $json_incident_media = array(); $upload_path = str_replace("media/uploads/", "", Kohana::config('upload.relative_directory') . "/"); //XML elements $xml = new XmlWriter(); $xml->openMemory(); $xml->startDocument('1.0', 'UTF-8'); $xml->startElement('response'); $xml->startElement('payload'); $xml->writeElement('domain', $this->domain); $xml->startElement('incidents'); // Records found, proceed // Store the incident ids $incidents_ids = array(); $custom_field_items = array(); foreach ($items as $item) { $incident_ids[] = $item->incident_id; $thiscustomfields = customforms::get_custom_form_fields($item->incident_id, null, false, "view"); if (!empty($thiscustomfields)) { $custom_field_items[$item->incident_id] = $thiscustomfields; } } // // STEP 2. // Fetch the incident categories // // Execute the query $incident_categories = ORM::factory('category')->select('category.*, incident_category.incident_id')->join('incident_category', 'category.id', 'incident_category.category_id')->in('incident_category.incident_id', $incident_ids)->find_all(); // To hold the incident category items $category_items = array(); // Fetch items into array foreach ($incident_categories as $incident_category) { $category_items[$incident_category->incident_id][] = $incident_category->as_array(); } // Free temporary variables from memory unset($incident_categories); // // STEP 3. // Fetch the media associated with all the incidents // $media_items_result = ORM::factory('media')->in('incident_id', $incident_ids)->find_all(); // To store the fetched media items $media_items = array(); // Fetch items into array foreach ($media_items_result as $media_item) { $media_item_array = $media_item->as_array(); if ($media_item->media_type == 1 and !empty($media_item->media_thumb)) { $media_item_array["media_thumb_url"] = url::convert_uploaded_to_abs($media_item->media_thumb); $media_item_array["media_link_url"] = url::convert_uploaded_to_abs($media_item->media_link); } $media_items[$media_item->incident_id][] = $media_item_array; } // Free temporary variables unset($media_items_result, $media_item_array); // // STEP 4. // Fetch the comments associated with the incidents // if ($this->comments) { // Execute the query $incident_comments = ORM::factory('comment')->in('incident_id', $incident_ids)->where('comment_spam', 0)->find_all(); // To hold the incident category items $comment_items = array(); // Fetch items into array foreach ($incident_comments as $incident_comment) { $comment_items[$incident_comment->incident_id][] = $incident_comment->as_array(); } // Free temporary variables from memory unset($incident_comments); } // // STEP 5. // Return XML // foreach ($items as $item) { // Build xml file $xml->startElement('incident'); $xml->writeElement('id', $item->incident_id); $xml->writeElement('title', $item->incident_title); $xml->writeElement('description', $item->incident_description); $xml->writeElement('date', $item->incident_date); $xml->writeElement('mode', $item->incident_mode); $xml->writeElement('active', $item->incident_active); $xml->writeElement('verified', $item->incident_verified); $xml->startElement('location'); $xml->writeElement('id', $item->location_id); $xml->writeElement('name', $item->location_name); $xml->writeElement('latitude', $item->latitude); $xml->writeElement('longitude', $item->longitude); $xml->endElement(); $xml->startElement('categories'); $json_report_categories[$item->incident_id] = array(); // Check if the incident id exists if (isset($category_items[$item->incident_id])) { foreach ($category_items[$item->incident_id] as $category_item) { if ($this->response_type == 'json' or $this->response_type == 'jsonp') { $json_report_categories[$item->incident_id][] = array("category" => array("id" => $category_item['id'], "title" => $category_item['category_title'])); } else { $xml->startElement('category'); $xml->writeElement('id', $category_item['id']); $xml->writeElement('title', $category_item['category_title']); $xml->endElement(); } } } // End categories $xml->endElement(); $xml->startElement('comments'); $json_report_comments[$item->incident_id] = array(); // Check if the incident id exists if (isset($comment_items[$item->incident_id])) { foreach ($comment_items[$item->incident_id] as $comment_item) { if ($this->response_type == 'json' or $this->response_type == 'jsonp') { $json_report_comments[$item->incident_id][] = array("comment" => $comment_item); } else { $xml->startElement('comment'); $xml->writeElement('id', $comment_item['id']); $xml->writeElement('comment_author', $comment_item['comment_author']); $xml->writeElement('comment_email', $comment_item['comment_email']); $xml->writeElement('comment_description', $comment_item['comment_description']); $xml->writeElement('comment_date', $comment_item['comment_date']); $xml->endElement(); } } } // End comments $xml->endElement(); $json_report_media[$item->incident_id] = array(); if (count($media_items) > 0) { if (isset($media_items[$item->incident_id]) and count($media_items[$item->incident_id]) > 0) { $xml->startElement('mediaItems'); foreach ($media_items[$item->incident_id] as $media_item) { if ($this->response_type == 'json' or $this->response_type == 'jsonp') { $json_media_array = array("id" => $media_item['id'], "type" => $media_item['media_type'], "link" => $media_item['media_link'], "thumb" => $media_item['media_thumb']); // If we are look at certain types of media, add some fields if ($media_item['media_type'] == 1 and isset($media_item['media_thumb_url'])) { // Give a full absolute URL to the image $json_media_array["thumb_url"] = $media_item['media_thumb_url']; $json_media_array["link_url"] = $media_item['media_link_url']; } $json_report_media[$item->incident_id][] = $json_media_array; } else { $xml->startElement('media'); if ($media_item['id'] != "") { $xml->writeElement('id', $media_item['id']); } if ($media_item['media_title'] != "") { $xml->writeElement('title', $media_item['media_title']); } if ($media_item['media_type'] != "") { $xml->writeElement('type', $media_item['media_type']); } if ($media_item['media_link'] != "") { $xml->writeElement('link', $upload_path . $media_item['media_link']); } if ($media_item['media_thumb'] != "") { $xml->writeElement('thumb', $upload_path . $media_item['media_thumb']); } if ($media_item['media_type'] == 1 and isset($media_item['media_thumb_url'])) { $xml->writeElement('thumb_url', $media_item['media_thumb_url']); $xml->writeElement('link_url', $media_item['media_link_url']); } $xml->endElement(); } } $xml->endElement(); // Media } } if (count($custom_field_items) > 0 and $this->response_type != 'json' and $this->response_type != 'jsonp') { if (isset($custom_field_items[$item->incident_id]) and count($custom_field_items[$item->incident_id]) > 0) { $xml->startElement('customFields'); foreach ($custom_field_items[$item->incident_id] as $field_item) { $xml->startElement('field'); foreach ($field_item as $fname => $fval) { $xml->writeElement($fname, $fval); } $xml->endElement(); // field } $xml->endElement(); // customFields } } $xml->endElement(); // End incident // Check for response type if ($this->response_type == 'json' or $this->response_type == 'jsonp') { $json_reports[] = array("incident" => array("incidentid" => $item->incident_id, "incidenttitle" => $item->incident_title, "incidentdescription" => $item->incident_description, "incidentdate" => $item->incident_date, "incidentmode" => $item->incident_mode, "incidentactive" => $item->incident_active, "incidentverified" => $item->incident_verified, "locationid" => $item->location_id, "locationname" => $item->location_name, "locationlatitude" => $item->latitude, "locationlongitude" => $item->longitude), "categories" => $json_report_categories[$item->incident_id], "media" => $json_report_media[$item->incident_id], "comments" => $json_report_comments[$item->incident_id], "customfields" => isset($custom_field_items[$item->incident_id]) ? $custom_field_items[$item->incident_id] : array()); } } // Create the JSON array $data = array("payload" => array("domain" => $this->domain, "incidents" => $json_reports), "error" => $this->api_service->get_error_msg(0)); if ($this->response_type == 'json' or $this->response_type == 'jsonp') { return $this->array_as_json($data); } else { $xml->endElement(); //end incidents $xml->endElement(); // end payload $xml->startElement('error'); $xml->writeElement('code', 0); $xml->writeElement('message', 'No Error'); $xml->endElement(); //end error $xml->endElement(); // end response return $xml->outputMemory(true); } }
/** * Lists the reports. * * @param int $page */ public function index($page = 1) { // If user doesn't have access, redirect to dashboard if (!admin::permissions($this->user, "reports_view")) { url::redirect(url::site() . 'admin/dashboard'); } $this->template->content = new View('admin/reports'); $this->template->content->title = Kohana::lang('ui_admin.reports'); // Database table prefix $table_prefix = Kohana::config('database.default.table_prefix'); // Hook into the event for the reports::fetch_incidents() method Event::add('ushahidi_filter.fetch_incidents_set_params', array($this, '_add_incident_filters')); $status = "0"; if (!empty($_GET['status'])) { $status = $_GET['status']; if (strtolower($status) == 'a') { array_push($this->params, 'i.incident_active = 0'); } elseif (strtolower($status) == 'v') { array_push($this->params, 'i.incident_verified = 0'); } elseif (strtolower($status) == 'o') { array_push($this->params, 'ic.category_id = 5'); } else { $status = "0"; } } // Get Search Keywords (If Any) if (isset($_GET['k'])) { // Brute force input sanitization // Phase 1 - Strip the search string of all non-word characters $keyword_raw = isset($_GET['k']) ? preg_replace('#/\\w+/#', '', $_GET['k']) : ""; // Strip any HTML tags that may have been missed in Phase 1 $keyword_raw = strip_tags($keyword_raw); // Phase 3 - Invoke Kohana's XSS cleaning mechanism just incase an outlier wasn't caught // in the first 2 steps $keyword_raw = $this->input->xss_clean($keyword_raw); $filter = " (" . $this->_get_searchstring($keyword_raw) . ")"; array_push($this->params, $filter); } else { $keyword_raw = ""; } // Check, has the form been submitted? $form_error = FALSE; $form_saved = FALSE; $form_action = ""; if ($_POST) { $post = Validation::factory($_POST); // Add some filters $post->pre_filter('trim', TRUE); // Add some rules, the input field, followed by a list of checks, // carried out in order $post->add_rules('action', 'required', 'alpha', 'length[1,1]'); $post->add_rules('incident_id.*', 'required', 'numeric'); if ($post->validate()) { // Approve Action if ($post->action == 'a') { foreach ($post->incident_id as $item) { // Database instance $db = new Database(); // Query to check if this report is uncategorized i.e categoryless $query = "SELECT ic.* FROM " . $table_prefix . "incident_category ic " . "INNER JOIN " . $table_prefix . "category c ON c.id = ic.category_id " . "INNER JOIN " . $table_prefix . "incident i ON i.id=ic.incident_id " . "WHERE c.category_title =\"NONE\" AND c.category_trusted = '1' " . "AND ic.incident_id = {$item}"; $result = $db->query($query); // Only approve the report IF it's not uncategorized // i.e the query returns a null set if (count($result) == 0) { $update = new Incident_Model($item); if ($update->loaded == TRUE) { $update->incident_active = $update->incident_active == 0 ? '1' : '0'; // Tag this as a report that needs to be sent out as an alert if ($update->incident_alert_status != '2') { // 2 = report that has had an alert sent $update->incident_alert_status = '1'; } $update->save(); $verify = new Verify_Model(); $verify->incident_id = $item; $verify->verified_status = '1'; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); // Action::report_approve - Approve a Report Event::run('ushahidi_action.report_approve', $update); } } $form_action = strtoupper(Kohana::lang('ui_admin.approved')); } } elseif ($post->action == 'u') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); if ($update->loaded == TRUE) { $update->incident_active = '0'; // If Alert hasn't been sent yet, disable it if ($update->incident_alert_status == '1') { $update->incident_alert_status = '0'; } $update->save(); $verify = new Verify_Model(); $verify->incident_id = $item; $verify->verified_status = '0'; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); // Action::report_unapprove - Unapprove a Report Event::run('ushahidi_action.report_unapprove', $update); } } $form_action = strtoupper(Kohana::lang('ui_admin.unapproved')); } elseif ($post->action == 'v') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); $verify = new Verify_Model(); if ($update->loaded == TRUE) { if ($update->incident_verified == '1') { $update->incident_verified = '0'; $verify->verified_status = '0'; } else { $update->incident_verified = '1'; $verify->verified_status = '2'; } $update->save(); $verify->incident_id = $item; // Record 'Verified By' Action $verify->user_id = $_SESSION['auth_user']->id; $verify->verified_date = date("Y-m-d H:i:s", time()); $verify->save(); } } // Set the form action $form_action = strtoupper(Kohana::lang('ui_admin.verified_unverified')); } elseif ($post->action == 'd') { foreach ($post->incident_id as $item) { $update = new Incident_Model($item); if ($update->loaded) { $update->delete(); } } $form_action = strtoupper(Kohana::lang('ui_admin.deleted')); } $form_saved = TRUE; } else { $form_error = TRUE; } } // Fetch all incidents $all_incidents = reports::fetch_incidents(); // Pagination $pagination = new Pagination(array('style' => 'front-end-reports', 'query_string' => 'page', 'items_per_page' => (int) Kohana::config('settings.items_per_page'), 'total_items' => $all_incidents->count())); Event::run('ushahidi_filter.pagination', $pagination); // Reports $incidents = Incident_Model::get_incidents(reports::$params, $pagination); Event::run('ushahidi_filter.filter_incidents', $incidents); $this->template->content->countries = Country_Model::get_countries_list(); $this->template->content->incidents = $incidents; $this->template->content->pagination = $pagination; $this->template->content->form_error = $form_error; $this->template->content->form_saved = $form_saved; $this->template->content->form_action = $form_action; // Total Reports $this->template->content->total_items = $pagination->total_items; // Status Tab $this->template->content->status = $status; // Javascript Header $this->template->js = new View('admin/reports_js'); }
/** * Helper method to load the report listing view */ private function _get_report_listing_view($locale = '') { // Check if the local is empty if (empty($locale)) { $locale = Kohana::config('locale.language.0'); } // Load the report listing view $report_listing = new View('reports_listing'); // Fetch all incidents $all_incidents = reports::fetch_incidents(); // Reports $incidents = Incident_Model::get_incidents(reports::$params); // Swap out category titles with their proper localizations using an array (cleaner way to do this?) $localized_categories = array(); foreach ($incidents as $incident) { $incident = ORM::factory('incident', $incident->incident_id); foreach ($incident->category as $category) { $ct = (string) $category->category_title; if (!isset($localized_categories[$ct])) { $localized_categories[$ct] = Category_Lang_Model::category_title($category->id, $locale); } } } // Set the view content $report_listing->incidents = $incidents; $report_listing->localized_categories = $localized_categories; //Set default as not showing pagination. Will change below if necessary. $report_listing->pagination = ""; // Pagination and Total Num of Report Stats $plural = count($incidents) > 1 ? "" : "s"; $report_listing->stats_breadcrumb = count($incidents) . ' ' . Kohana::lang('ui_admin.reports') . $plural; // Return return $report_listing; }