Example #1
0
 /**
  * Download Reports in CSV format
  * JP: Added filter by search option. Also added HTML download.
  */
 public function download()
 {
     // If user doesn't have access, redirect to dashboard
     if (!$this->auth->has_permission("reports_download")) {
         url::redirect(url::site() . 'admin/dashboard');
     }
     $this->template->content = new View('admin/reports/download');
     $this->template->content->title = Kohana::lang('ui_admin.download_reports');
     $errors = $form = array('format' => '', 'data_active' => array(), 'data_verified' => array(), 'data_include' => array(), 'from_date' => '', 'to_date' => '', 'form_auth_token' => '', 'filter_search' => '');
     // Default to all selected
     $form['data_active'] = array(0, 1);
     $form['data_verified'] = array(0, 1);
     $form['data_include'] = array(1, 2, 3, 4, 5, 6, 7);
     $form_error = FALSE;
     // Check, has the form been submitted, if so, setup validation
     if ($_POST) {
         // Instantiate Validation, use $post, so we don't overwrite $_POST fields with our own things
         $post = array_merge($_POST, $_FILES);
         // Test to see if things passed the rule checks
         if (download::validate($post)) {
             // Set filter
             $filter = '( ';
             // Report Type Filter
             $show_active = FALSE;
             $show_inactive = FALSE;
             $show_verified = FALSE;
             $show_not_verified = FALSE;
             $filter_search = FALSE;
             if (in_array(1, $post->data_active)) {
                 $show_active = TRUE;
             }
             if (in_array(0, $post->data_active)) {
                 $show_inactive = TRUE;
             }
             if (in_array(1, $post->data_verified)) {
                 $show_verified = TRUE;
             }
             if (in_array(0, $post->data_verified)) {
                 $show_not_verified = TRUE;
             }
             if (!empty($post->filter_search)) {
                 $filter_search = TRUE;
             }
             // Handle active or not active
             if ($show_active && !$show_inactive) {
                 $filter .= ' incident_active = 1 ';
             } elseif (!$show_active && $show_inactive) {
                 $filter .= '  incident_active = 0 ';
             } elseif ($show_active && $show_inactive) {
                 $filter .= ' (incident_active = 1 OR incident_active = 0) ';
             } elseif (!$show_active && !$show_inactive) {
                 // Equivalent to 1 = 0
                 $filter .= ' (incident_active = 0 AND incident_active = 1) ';
             }
             $filter .= ' AND ';
             // Handle verified
             if ($show_verified && !$show_not_verified) {
                 $filter .= ' incident_verified = 1 ';
             } elseif (!$show_verified && $show_not_verified) {
                 $filter .= ' incident_verified = 0 ';
             } elseif ($show_verified && $show_not_verified) {
                 $filter .= ' (incident_verified = 0 OR incident_verified = 1) ';
             } elseif (!$show_verified && !$show_not_verified) {
                 $filter .= ' (incident_verified = 0 AND incident_verified = 1) ';
             }
             $filter .= ') ';
             // Report Date Filter
             if (!empty($post->from_date)) {
                 $filter .= " AND incident_date >= '" . date("Y-m-d H:i:s", strtotime($post->from_date)) . "' ";
             }
             if (!empty($post->to_date)) {
                 $filter .= " AND incident_date <= '" . date("Y-m-d H:i:s", strtotime($post->to_date)) . "' ";
             }
             // JP: Search Filter
             if ($filter_search) {
                 $where_string = "";
                 $or = "";
                 // 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+/#', '', $post->filter_search);
                 // 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 = $this->input->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) {
                                 $or = ' OR ';
                             }
                             $where_string = $where_string . $or . "(incident_title LIKE '%{$chunk}%' OR incident_description LIKE '%{$chunk}%')";
                             $i++;
                         }
                     }
                 }
                 $filter .= " AND " . $where_string;
             }
             // Retrieve reports
             $incidents = ORM::factory('incident')->where($filter)->orderby('incident_dateadd', 'desc')->find_all();
             // Retrieve categories
             $categories = Category_Model::get_categories(FALSE, FALSE, FALSE);
             // Retrieve Forms
             $forms = ORM::Factory('form')->find_all();
             // Retrieve Custom forms
             $custom_forms = customforms::get_custom_form_fields();
             // If CSV format is selected
             if ($post->format == 'csv') {
                 $report_csv = download::download_csv($post, $incidents, $custom_forms);
                 // Output to browser
                 header("Content-type: text/x-csv");
                 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                 header("Content-Disposition: attachment; filename=" . time() . ".csv");
                 header("Content-Length: " . strlen($report_csv));
                 echo $report_csv;
                 exit;
             }
             // If XML format is selected
             if ($post->format == 'xml') {
                 header('Content-type: text/xml; charset=UTF-8');
                 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                 header("Content-Disposition: attachment; filename=" . time() . ".xml");
                 $content = download::download_xml($post, $incidents, $categories, $forms);
                 echo $content;
                 exit;
             }
             // JP: If HTML format is selected...
             if ($post->format == 'html') {
                 $content = download::download_html($post, $incidents, $custom_forms);
                 header("Content-type: text/html; charset=UTF-8");
                 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                 header("Content-Disposition: attachment; filename=" . time() . ".html");
                 header("Content-Length: " . strlen($content));
                 echo $content;
                 exit;
             }
         } else {
             // Repopulate the form fields
             $form = arr::overwrite($form, $post->as_array());
             // Populate the error fields, if any
             $errors = arr::merge($errors, $post->errors('report'));
             $form_error = TRUE;
         }
     }
     $this->template->content->form = $form;
     $this->template->content->errors = $errors;
     $this->template->content->form_error = $form_error;
     // Javascript Header
     $this->themes->js = new View('admin/reports/download_js');
     $this->themes->js->calendar_img = url::base() . "media/img/icon-calendar.gif";
 }
Example #2
0
 /**
  * Get the number of reports by date for dashboard chart
  *
  * @param int $range No. of days in the past
  * @param int $user_id
  * @return array
  */
 public static function get_number_reports_by_date($range = NULL, $user_id = NULL)
 {
     // Table Prefix
     $table_prefix = Kohana::config('database.default.table_prefix');
     // Database instance
     $db = new Database();
     // Filter by User
     $user_id = (int) $user_id;
     $u_sql = $user_id ? " AND user_id = " . $user_id . " " : "";
     // Query to generate the report count
     $sql = 'SELECT COUNT(id) as count, DATE(incident_date) as date, MONTH(incident_date) as month, DAY(incident_date) as day, ' . 'YEAR(incident_date) as year ' . 'FROM ' . $table_prefix . 'incident ';
     // Check if the range has been specified and is non-zero then add predicates to the query
     if ($range != NULL and intval($range) > 0) {
         $sql .= 'WHERE incident_date >= DATE_SUB(CURDATE(), INTERVAL ' . $db->escape_str($range) . ' DAY) ';
     } else {
         $sql .= 'WHERE 1=1 ';
     }
     // Group and order the records
     $sql .= $u_sql . 'GROUP BY date ORDER BY incident_date ASC';
     $query = $db->query($sql);
     $result = $query->result_array(FALSE);
     $array = array();
     foreach ($result as $row) {
         $timestamp = mktime(0, 0, 0, $row['month'], $row['day'], $row['year']) * 1000;
         $array["{$timestamp}"] = $row['count'];
     }
     return $array;
 }
Example #3
0
 /**
  * Function that saves incident geometries
  *
  * @param Incident_Model $incident
  * @param mixed $incident
  *
  */
 public static function save_report_geometry($post, $incident)
 {
     // Delete all current geometry
     ORM::factory('geometry')->where('incident_id', $incident->id)->delete_all();
     if (isset($post->geometry)) {
         // Database object
         $db = new Database();
         // SQL for creating the incident geometry
         $sql = "INSERT INTO " . Kohana::config('database.default.table_prefix') . "geometry " . "(incident_id, geometry, geometry_label, geometry_comment, geometry_color, geometry_strokewidth) " . "VALUES(%d, GeomFromText('%s'), '%s', '%s', '%s', %s)";
         foreach ($post->geometry as $item) {
             if (!empty($item)) {
                 //Decode JSON
                 $item = json_decode($item);
                 //++ TODO - validate geometry
                 $geometry = isset($item->geometry) ? $db->escape_str($item->geometry) : "";
                 $label = isset($item->label) ? $db->escape_str(substr($item->label, 0, 150)) : "";
                 $comment = isset($item->comment) ? $db->escape_str(substr($item->comment, 0, 255)) : "";
                 $color = isset($item->color) ? $db->escape_str(substr($item->color, 0, 6)) : "";
                 $strokewidth = (isset($item->strokewidth) and (double) $item->strokewidth) ? (double) $item->strokewidth : "2.5";
                 if ($geometry) {
                     // 	Format the SQL string
                     $sql = sprintf($sql, $incident->id, $geometry, $label, $comment, $color, $strokewidth);
                     // Execute the query
                     $db->query($sql);
                 }
             }
         }
     }
 }
Example #4
0
 /**
  * Build a search query with relevancy
  * Stop word control included
  */
 public function index($page = 1)
 {
     $this->template->content = new View('search');
     $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');
     if ($_GET) {
         /**
          * NOTES: 15/10/2010 - Emmanuel Kala <*****@*****.**>
          *
          * The search string undergoes a 3-phase sanitization process. This is not optimal
          * but it works for now. The Kohana provided XSS cleaning mechanism does not expel
          * content contained in between HTML tags this the "bruteforce" input sanitization.
          *
          * However, XSS is attempted using Javascript tags, Kohana's routing mechanism strips
          * the "<script>" tags from the URL variables and passes inline text as part of the URL
          * variable - This has to be fixed
          */
         // Phase 1 - Fetch the search string and perform initial sanitization
         $keyword_raw = isset($_GET['k']) ? preg_replace('#/\\w+/#', '', $_GET['k']) : "";
         // 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 = $this->input->xss_clean($keyword_raw);
     } else {
         $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 ';
                 }
                 // Give relevancy weighting
                 // Title weight = 2
                 // Description weight = 1
                 $keyword_string = $keyword_string . $plus . "(CASE WHEN incident_title LIKE '%{$chunk}%' THEN 2 ELSE 0 END) + " . "(CASE WHEN incident_description LIKE '%{$chunk}%' THEN 1 ELSE 0 END) ";
                 $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 " . $this->table_prefix . "incident " . "WHERE " . $where_string . " " . "ORDER BY relevance DESC LIMIT ";
         }
     }
     if (!empty($search_query)) {
         // Pagination
         $pagination = new Pagination(array('query_string' => 'page', 'items_per_page' => (int) Kohana::config('settings.items_per_page'), 'total_items' => ORM::factory('incident')->where($where_string)->count_all()));
         $query = $db->query($search_query . $pagination->sql_offset . "," . (int) Kohana::config('settings.items_per_page'));
         // Results Bar
         if ($pagination->total_items != 0) {
             $search_info .= "<div class=\"search_info\">" . Kohana::lang('ui_admin.showing_results') . ' ' . ($pagination->sql_offset + 1) . ' ' . Kohana::lang('ui_admin.to') . ' ' . ((int) Kohana::config('settings.items_per_page') + $pagination->sql_offset) . ' ' . Kohana::lang('ui_admin.of') . ' ' . $pagination->total_items . ' ' . Kohana::lang('ui_admin.searching_for') . ' <strong>' . $keyword_raw . "</strong>" . "</div>";
         } else {
             $search_info .= "<div class=\"search_info\">0 " . Kohana::lang('ui_admin.results') . "</div>";
             $html .= "<div class=\"search_result\">";
             $html .= "<h3>" . Kohana::lang('ui_admin.your_search_for') . "<strong> " . $keyword_raw . "</strong> " . Kohana::lang('ui_admin.match_no_documents') . "</h3>";
             $html .= "</div>";
             $pagination = "";
         }
         foreach ($query as $search) {
             $incident_id = $search->id;
             $incident_title = strip_tags($search->incident_title);
             $highlight_title = "";
             $incident_title_arr = explode(' ', $incident_title);
             foreach ($incident_title_arr as $value) {
                 if (in_array(strtolower($value), $keywords) and !in_array(strtolower($value), $stop_words)) {
                     $highlight_title .= "<span class=\"search_highlight\">" . $value . "</span> ";
                 } else {
                     $highlight_title .= $value . " ";
                 }
             }
             // Remove any markup, otherwise trimming below will mess things up
             $incident_description = strip_tags($search->incident_description);
             // Trim to 180 characters without cutting words
             if (strlen($incident_description) > 180 and strlen($incident_description) > 1) {
                 $whitespaceposition = strpos($incident_description, " ", 175) - 1;
                 $incident_description = substr($incident_description, 0, $whitespaceposition);
             }
             $highlight_description = "";
             $incident_description_arr = explode(' ', $incident_description);
             foreach ($incident_description_arr as $value) {
                 if (in_array(strtolower($value), $keywords) && !in_array(strtolower($value), $stop_words)) {
                     $highlight_description .= "<span class=\"search_highlight\">" . $value . "</span> ";
                 } else {
                     $highlight_description .= $value . " ";
                 }
             }
             $incident_date = date('D M j Y g:i:s a', strtotime($search->incident_date));
             $html .= "<div class=\"search_result\">";
             $html .= "<h3><a href=\"" . url::base() . "reports/view/" . $incident_id . "\">" . $highlight_title . "</a></h3>";
             $html .= $highlight_description . " ...";
             $html .= "<div class=\"search_date\">" . $incident_date . " | " . Kohana::lang('ui_admin.relevance') . ": <strong>+" . $search->relevance . "</strong></div>";
             $html .= "</div>";
         }
     } else {
         // Results Bar
         $search_info .= "<div class=\"search_info\">0 " . Kohana::lang('ui_admin.results') . "</div>";
         $html .= "<div class=\"search_result\">";
         $html .= "<h3>" . Kohana::lang('ui_admin.your_search_for') . "<strong>" . $keyword_raw . "</strong> " . Kohana::lang('ui_admin.match_no_documents') . "</h3>";
         $html .= "</div>";
     }
     $html .= $pagination;
     $this->template->content->search_info = $search_info;
     $this->template->content->search_results = $html;
     // Rebuild Header Block
     $this->template->header->header_block = $this->themes->header_block();
     $this->template->footer->footer_block = $this->themes->footer_block();
 }
 /**
  * Save user-specific plugin settings
  *
  * @param unknown_type $user_id
  * @param string $settings JSON-encoded string, to be stored directly in the database
  */
 function setUserSettings($user_id, $settings)
 {
     if (is_null($this->instance)) {
         trigger_error("YOU MUST set the container first before trying to set a user's settings!");
     }
     $db = new Database();
     $db->query("DELETE FROM user_plugin_settings WHERE user_id = " . $db->escape($user_id) . " AND plugin_name = '{$this->name}' AND container_id='{$this->container}'");
     $db->query("INSERT INTO user_plugin_settings (plugin_name, user_id, container_id, settings) VALUES ('{$this->name}', " . $db->escape($user_id) . ", " . $db->escape($this->container) . ", '" . $db->escape_str($settings) . "')");
 }
Example #6
0
 /**
  * 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);
     }
 }
Example #7
0
 function index()
 {
     $this->template->this_page = 'download';
     $this->template->header->this_page = 'download';
     $this->template->content = new View('download_reports');
     $this->template->content->calendar_img = url::base() . "media/img/icon-calendar.gif";
     $this->template->content->title = Kohana::lang('ui_admin.download_reports');
     // Javascript Header
     $this->themes->js = new View('download_reports_js');
     $this->themes->js->calendar_img = url::base() . "media/img/icon-calendar.gif";
     $this->themes->treeview_enabled = TRUE;
     $this->template->header->header_block = $this->themes->header_block();
     $this->template->footer->footer_block = $this->themes->footer_block();
     // Select first and last incident
     $from = orm::factory('incident')->orderby('incident_date', 'asc')->find();
     $to = orm::factory('incident')->orderby('incident_date', 'desc')->find();
     $from_date = substr($from->incident_date, 5, 2) . "/" . substr($from->incident_date, 8, 2) . "/" . substr($from->incident_date, 0, 4);
     $to_date = substr($to->incident_date, 5, 2) . "/" . substr($to->incident_date, 8, 2) . "/" . substr($to->incident_date, 0, 4);
     $form = array('category' => '', 'verified' => '', 'category_all' => '', 'from_date' => '', 'to_date' => '', 'filter_search' => '');
     $errors = $form;
     $form_error = FALSE;
     $form['from_date'] = $from_date;
     $form['to_date'] = $to_date;
     if ($_POST) {
         // Instantiate Validation, use $post, so we don't overwrite $_POST fields with our own things
         $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('category.*', 'required', 'numeric');
         $post->add_rules('verified.*', 'required', 'numeric', 'between[0,1]');
         $post->add_rules('formato', 'required', 'numeric', 'between[0,2]');
         $post->add_rules('from_date', 'required', 'date_mmddyyyy');
         $post->add_rules('to_date', 'required', 'date_mmddyyyy');
         // Validate the report dates, if included in report filter
         if (!empty($_POST['from_date']) && !empty($_POST['to_date'])) {
             // TO Date not greater than FROM Date?
             if (strtotime($_POST['from_date']) > strtotime($_POST['to_date'])) {
                 $post->add_error('to_date', 'range_greater');
             }
         }
         // $post validate check
         if ($post->validate()) {
             // Check child categories too
             $categories = ORM::factory('category')->select('id')->in('parent_id', $post->category)->find_all();
             foreach ($categories as $cat) {
                 $post->category[] = $cat->id;
             }
             $incident_query = ORM::factory('incident')->select('DISTINCT incident.id')->select('incident.*')->where('incident_active', 1);
             $incident_query->in('category_id', $post->category);
             // If only unverified selected
             if (in_array('0', $post->verified) && !in_array('1', $post->verified)) {
                 $incident_query->where('incident_verified', 0);
             } elseif (!in_array('0', $post->verified) && in_array('1', $post->verified)) {
                 $incident_query->where('incident_verified', 1);
             }
             // else - do nothing
             // Report Date Filter
             if (!empty($post->from_date) && !empty($post->to_date)) {
                 // JP: Added the times 00:00:00 for the from_date and 23:59:59 for the to_date; this fixes the bug where reports made on the day of the to_date would not be included since the time was not specified.
                 $incident_query->where(array('incident_date >=' => date("Y-m-d 00:00:00", strtotime($post->from_date)), 'incident_date <=' => date("Y-m-d 23:59:59", strtotime($post->to_date))));
             }
             // JP: Search Filter
             if (!empty($post->filter_search)) {
                 $where_string = "";
                 $or = "";
                 // 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+/#', '', $post->filter_search);
                 // 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 = $this->input->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) {
                                 $or = ' OR ';
                             }
                             $where_string = $where_string . $or . "(incident_title LIKE '%{$chunk}%' OR incident_description LIKE '%{$chunk}%')";
                             $i++;
                         }
                     }
                 }
                 $incident_query->where($where_string);
             }
             $incidents = $incident_query->join('incident_category', 'incident_category.incident_id', 'incident.id', 'INNER')->orderby('incident_date', 'desc')->find_all();
             // CSV selected
             if ($post->formato == 0) {
                 $report_csv = "#,INCIDENT TITLE,INCIDENT DATE,LOCATION,DESCRIPTION,CATEGORY,LATITUDE,LONGITUDE,APPROVED,VERIFIED\n";
                 foreach ($incidents as $incident) {
                     $new_report = array();
                     array_push($new_report, '"' . $incident->id . '"');
                     array_push($new_report, '"' . $this->_csv_text($incident->incident_title) . '"');
                     array_push($new_report, '"' . $incident->incident_date . '"');
                     array_push($new_report, '"' . $this->_csv_text($incident->location->location_name) . '"');
                     array_push($new_report, '"' . $this->_csv_text($incident->incident_description) . '"');
                     $catstring = '"';
                     $catcnt = 0;
                     foreach ($incident->incident_category as $category) {
                         if ($catcnt > 0) {
                             $catstring .= ",";
                         }
                         if ($category->category->category_title) {
                             $catstring .= $this->_csv_text($category->category->category_title);
                         }
                         $catcnt++;
                     }
                     $catstring .= '"';
                     array_push($new_report, $catstring);
                     array_push($new_report, '"' . $incident->location->latitude . '"');
                     array_push($new_report, '"' . $incident->location->longitude . '"');
                     if ($incident->incident_active) {
                         array_push($new_report, "YES");
                     } else {
                         array_push($new_report, "NO");
                     }
                     if ($incident->incident_verified) {
                         array_push($new_report, "YES");
                     } else {
                         array_push($new_report, "NO");
                     }
                     array_push($new_report, "\n");
                     $repcnt = 0;
                     foreach ($new_report as $column) {
                         if ($repcnt > 0) {
                             $report_csv .= ",";
                         }
                         $report_csv .= $column;
                         $repcnt++;
                     }
                 }
                 // Output to browser
                 header("Content-type: text/x-csv");
                 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                 header("Content-Disposition: attachment; filename=" . time() . ".csv");
                 header("Content-Length: " . strlen($report_csv));
                 echo $report_csv;
                 exit;
             } else {
                 if ($post->formato == 1) {
                     $categories = ORM::factory('category')->where('category_visible', 1)->find_all();
                     header("Content-Type: application/vnd.google-earth.kml+xml");
                     header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                     header("Content-Disposition: attachment; filename=" . time() . ".kml");
                     $view = new View("kml");
                     $view->kml_name = htmlspecialchars(Kohana::config('settings.site_name'));
                     $view->items = $incidents;
                     $view->categories = $categories;
                     $view->render(TRUE);
                     exit;
                 } else {
                     $h = array();
                     $h[] = '<!DOCTYPE html>';
                     $h[] = '  <head>';
                     $h[] = '    <title>';
                     $h[] = '      Downloaded Reports';
                     $h[] = '    </title>';
                     $h[] = '    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
                     $h[] = '    <style>';
                     $h[] = '      table { border-collapse: collapse; }';
                     $h[] = '      table thead tr { background: #CCCCCC; }';
                     $h[] = '      table thead tr th, table tbody tr td { padding: 0.75em; border: 1px solid #AAAAAA; }';
                     $h[] = '      table tbody tr.even, table tbody tr.alt, table tbody tr:nth-of-type(even) { background: #DDDDDD; }';
                     $h[] = '    </style>';
                     $h[] = '  </head>';
                     $h[] = '  <body>';
                     $h[] = '    <table>';
                     $h[] = '      <thead>';
                     $h[] = '        <tr>';
                     $h[] = '          <th>';
                     $h[] = '            #';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            TITLE';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            DATE';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            LOCATION';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            DESCRIPTION';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            CATEGORY';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            LATITUDE';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            LONGITUDE';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            APPROVED';
                     $h[] = '          </th>';
                     $h[] = '          <th>';
                     $h[] = '            VERIFIED';
                     $h[] = '          </th>';
                     $h[] = '        </tr>';
                     $h[] = '      </thead>';
                     $h[] = '      <tbody>';
                     foreach ($incidents as $r) {
                         $h[] = '        <tr>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->id;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->incident_title;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->incident_date;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->location->location_name;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->incident_description;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $cats = '';
                         $cnt = 0;
                         foreach ($r->incident_category as $cat) {
                             if ($cnt > 0) {
                                 $cats .= ", ";
                             }
                             if ($cat->category->category_title) {
                                 $cats .= $cat->category->category_title;
                             }
                             $cnt++;
                         }
                         $h[] = '            ' . $cats;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->location->latitude;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         $h[] = '            ' . $r->location->longitude;
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         if ($r->incident_active) {
                             $h[] = '            YES';
                         } else {
                             $h[] = '            NO';
                         }
                         $h[] = '          </td>';
                         $h[] = '          <td>';
                         if ($r->incident_verified) {
                             $h[] = '            YES';
                         } else {
                             $h[] = '            NO';
                         }
                         $h[] = '          </td>';
                         $h[] = '        </tr>';
                     }
                     $h[] = '      </tbody>';
                     $h[] = '    </table>';
                     $h[] = '  </body>';
                     $h[] = '</html>';
                     $f = implode("\n", $h);
                     header("Content-type: text/html; charset=UTF-8");
                     header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                     header("Content-Disposition: attachment; filename=" . time() . ".html");
                     header("Content-Length: " . strlen($f));
                     echo $f;
                     exit;
                 }
             }
         } else {
             // repopulate the form fields
             $form = arr::overwrite($form, $post->as_array());
             // populate the error fields, if any
             $errors = arr::overwrite($errors, $post->errors('download_reports'));
             $form_error = TRUE;
         }
     }
     $this->template->content->form = $form;
     $this->template->content->errors = $errors;
     $this->template->content->form_error = $form_error;
 }