/** * Tests CountyModel::get_country_by_name * @test */ public function testGetCountryByName() { // Use valid country $valid = Country_Model::get_country_by_name('Kenya'); $this->assertEquals(TRUE, $valid instanceof Country_Model, sprintf('Invalid country object type (%s) returned', get_class($valid))); $this->assertGreaterThanOrEqual(1, $valid->id); // Use invalid country $invalid = Country_Model::get_country_by_name('Nairobi'); $this->assertNull($invalid); }
/** * Model Validation * * @param array $array values to check * @param boolean $save save[Optional] the record when validation succeeds * @return boolean */ public function validate(array &$post, $save = FALSE) { // Initialise the validation library and setup some rules $post = Validation::factory($post)->pre_filter('trim')->add_rules('alert_mobile', 'numeric', 'length[6,20]')->add_rules('alert_email', 'email', 'length[3,64]')->add_rules('alert_lat', 'required', 'between[-90,90]')->add_rules('alert_lon', 'required', 'between[-180,180]')->add_rules('alert_radius', 'required', 'in_array[1,5,10,20,50,100]')->add_callbacks('alert_mobile', array($this, '_mobile_or_email'))->add_callbacks('alert_mobile', array($this, '_mobile_check'))->add_callbacks('alert_email', array($this, '_email_check')); // If deployment is a single country deployment, check that the location mapped is in the default country if (!Kohana::config('settings.multi_country')) { $country = Country_Model::get_country_by_name($post->alert_country); if ($country and $country->id != Kohana::config('settings.default_country')) { $post->add_error('alert_country', 'single_country'); } } return parent::validate($post, $save); }
/** * Function to save report location * * @param Validation $post * @param Location_Model $location Instance of the location model */ public static function save_location($post, $location) { // Load the country $country = isset($post->country_name) ? Country_Model::get_country_by_name($post->country_name) : new Country_Model(Kohana::config('settings.default_country')); // Fetch the country id $country_id = (!empty($country) and $country->loaded) ? $country->id : 0; // Assign country_id retrieved $post->country_id = $country_id; $location->location_name = $post->location_name; $location->latitude = $post->latitude; $location->longitude = $post->longitude; $location->country_id = $country_id; $location->location_date = date("Y-m-d H:i:s", time()); $location->save(); // Garbage collection unset($country, $country_id); }
/** * Edit a report * @param bool|int $id The id no. of the report * @param bool|string $saved */ function edit($id = false, $saved = false) { $db = new Database(); $this->template->content = new View('members/reports_edit'); $this->template->content->title = Kohana::lang('ui_admin.create_report'); // setup and initialize form field names $form = array('location_id' => '', 'form_id' => '', 'locale' => '', 'incident_title' => '', 'incident_description' => '', 'incident_date' => '', 'incident_hour' => '', 'incident_minute' => '', 'incident_ampm' => '', 'latitude' => '', 'longitude' => '', 'geometry' => array(), 'location_name' => '', 'country_id' => '', 'country_name' => '', 'incident_category' => array(), 'incident_news' => array(), 'incident_video' => array(), 'incident_photo' => array(), 'person_first' => '', 'person_last' => '', 'person_email' => '', 'custom_field' => array(), 'incident_source' => '', 'incident_information' => '', 'incident_zoom' => ''); // copy the form as errors, so the errors will be stored with keys corresponding to the form field names $errors = $form; $form_error = FALSE; if ($saved == 'saved') { $form_saved = TRUE; } else { $form_saved = FALSE; } // Initialize Default Values $form['locale'] = Kohana::config('locale.language'); //$form['latitude'] = Kohana::config('settings.default_lat'); //$form['longitude'] = Kohana::config('settings.default_lon'); $form['country_id'] = Kohana::config('settings.default_country'); $form['incident_date'] = date("m/d/Y", time()); $form['incident_hour'] = date('h'); $form['incident_minute'] = date('i'); $form['incident_ampm'] = date('a'); // initialize custom field array $form['custom_field'] = $this->_get_custom_form_fields($id, '', true); // Locale (Language) Array $this->template->content->locale_array = Kohana::config('locale.all_languages'); // Create Categories $this->template->content->categories = Category_Model::get_categories(); // Time formatting $this->template->content->hour_array = $this->_hour_array(); $this->template->content->minute_array = $this->_minute_array(); $this->template->content->ampm_array = $this->_ampm_array(); $this->template->content->stroke_width_array = $this->_stroke_width_array(); // Get Countries $countries = array(); foreach (ORM::factory('country')->orderby('country')->find_all() as $country) { // Create a list of all categories $this_country = $country->country; if (strlen($this_country) > 35) { $this_country = substr($this_country, 0, 35) . "..."; } $countries[$country->id] = $this_country; } $this->template->content->countries = $countries; // Initialize Default Value for Hidden Field Country Name, just incase Reverse Geo coding yields no result $form['country_name'] = $countries[$form['country_id']]; //GET custom forms $forms = array(); foreach (ORM::factory('form')->where('form_active', 1)->find_all() as $custom_forms) { $forms[$custom_forms->id] = $custom_forms->form_title; } $this->template->content->forms = $forms; // Retrieve thumbnail photos (if edit); //XXX: fix _get_thumbnails $this->template->content->incident = $this->_get_thumbnails($id); // Are we creating this report from a Checkin? if (isset($_GET['cid']) && !empty($_GET['cid'])) { $checkin_id = (int) $_GET['cid']; $checkin = ORM::factory('checkin', $checkin_id); if ($checkin->loaded) { // Has a report already been created for this Checkin? if ((int) $checkin->incident_id > 0) { // Redirect to report url::redirect('members/reports/edit/' . $checkin->incident_id); } $incident_description = $checkin->checkin_description; $incident_title = text::limit_chars(strip_tags($incident_description), 100, "...", true); $form['incident_title'] = $incident_title; $form['incident_description'] = $incident_description; $form['incident_date'] = date('m/d/Y', strtotime($checkin->checkin_date)); $form['incident_hour'] = date('h', strtotime($checkin->checkin_date)); $form['incident_minute'] = date('i', strtotime($checkin->checkin_date)); $form['incident_ampm'] = date('a', strtotime($checkin->checkin_date)); // Does the sender of this message have a location? if ($checkin->location->loaded) { $form['location_id'] = $checkin->location_id; $form['latitude'] = $checkin->location->latitude; $form['longitude'] = $checkin->location->longitude; $form['location_name'] = $checkin->location->location_name; } } } // 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 = Validation::factory(array_merge($_POST, $_FILES)); // 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('locale','required','alpha_dash','length[5]'); $post->add_rules('location_id', 'numeric'); $post->add_rules('message_id', 'numeric'); $post->add_rules('incident_title', 'required', 'length[3,200]'); $post->add_rules('incident_description', 'required'); $post->add_rules('incident_date', 'required', 'date_mmddyyyy'); $post->add_rules('incident_hour', 'required', 'between[1,12]'); $post->add_rules('incident_minute', 'required', 'between[0,59]'); if ($_POST['incident_ampm'] != "am" && $_POST['incident_ampm'] != "pm") { $post->add_error('incident_ampm', 'values'); } $post->add_rules('latitude', 'required', 'between[-90,90]'); // Validate for maximum and minimum latitude values $post->add_rules('longitude', 'required', 'between[-180,180]'); // Validate for maximum and minimum longitude values $post->add_rules('location_name', 'required', 'length[3,200]'); //XXX: Hack to validate for no checkboxes checked if (!isset($_POST['incident_category'])) { $post->incident_category = ""; $post->add_error('incident_category', 'required'); } else { $post->add_rules('incident_category.*', 'required', 'numeric'); } // Validate only the fields that are filled in if (!empty($_POST['incident_news'])) { foreach ($_POST['incident_news'] as $key => $url) { if (!empty($url) and !(bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) { $post->add_error('incident_news', 'url'); } } } // Validate only the fields that are filled in if (!empty($_POST['incident_video'])) { foreach ($_POST['incident_video'] as $key => $url) { if (!empty($url) and !(bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) { $post->add_error('incident_video', 'url'); } } } // Validate photo uploads $post->add_rules('incident_photo', 'upload::valid', 'upload::type[gif,jpg,png]', 'upload::size[2M]'); // Validate Personal Information if (!empty($_POST['person_first'])) { $post->add_rules('person_first', 'length[3,100]'); } if (!empty($_POST['person_last'])) { $post->add_rules('person_last', 'length[3,100]'); } if (!empty($_POST['person_email'])) { $post->add_rules('person_email', 'email', 'length[3,100]'); } // Validate Custom Fields if (isset($post->custom_field) && !$this->_validate_custom_form_fields($post->custom_field)) { $post->add_error('custom_field', 'values'); } // If deployment is a single country deployment, check that the location mapped is in the default country if (!Kohana::config('settings.multi_country')) { $country = Country_Model::get_country_by_name($post->country_name); if ($country and $country->id != Kohana::config('settings.default_country')) { $post->add_error('country_name', 'single_country'); } } $post->add_rules('incident_source', 'numeric', 'length[1,1]'); $post->add_rules('incident_information', 'numeric', 'length[1,1]'); // Test to see if things passed the rule checks if ($post->validate()) { // STEP 1: SAVE LOCATION $location = new Location_Model(); reports::save_location($post, $location); // STEP 2: SAVE INCIDENT $incident = new Incident_Model(); reports::save_report($post, $incident, $location->id); // STEP 3: SAVE CATEGORIES reports::save_category($post, $incident); // STEP 4: SAVE MEDIA reports::save_media($post, $incident); // STEP 5: SAVE CUSTOM FORM FIELDS reports::save_custom_fields($post, $incident); // STEP 6: SAVE PERSONAL INFORMATION reports::save_personal_info($post, $incident); // If creating a report from a checkin if (isset($checkin_id) and $checkin_id != "") { $checkin = ORM::factory('checkin', $checkin_id); if ($checkin->loaded) { $checkin->incident_id = $incident->id; $checkin->save(); // Attach all the media items in this checkin to the report foreach ($checkin->media as $media) { $media->incident_id = $incident->id; $media->save(); } } } // Action::report_add / report_submit_members - Added a New Report //++ Do we need two events for this? Or will one suffice? //Event::run('ushahidi_action.report_add', $incident); Event::run('ushahidi_action.report_submit_members', $post); // SAVE AND CLOSE? if ($post->save == 1) { url::redirect('members/reports/edit/' . $incident->id . '/saved'); } else { url::redirect('members/reports/'); } } else { // repopulate the form fields $form = arr::overwrite($form, $post->as_array()); // populate the error fields, if any $errors = arr::overwrite($errors, $post->errors('report')); $form_error = TRUE; } } else { if ($id) { // Retrieve Current Incident $incident = ORM::factory('incident')->where('user_id', $this->user->id)->find($id); if ($incident->loaded == true) { // Retrieve Categories $incident_category = array(); foreach ($incident->incident_category as $category) { $incident_category[] = $category->category_id; } // Retrieve Media $incident_news = array(); $incident_video = array(); $incident_photo = array(); foreach ($incident->media as $media) { if ($media->media_type == 4) { $incident_news[] = $media->media_link; } elseif ($media->media_type == 2) { $incident_video[] = $media->media_link; } elseif ($media->media_type == 1) { $incident_photo[] = $media->media_link; } } // Get Geometries via SQL query as ORM can't handle Spatial Data $sql = "SELECT AsText(geometry) as geometry, geometry_label, \n\t\t\t\t\t\tgeometry_comment, geometry_color, geometry_strokewidth \n\t\t\t\t\t\tFROM " . Kohana::config('database.default.table_prefix') . "geometry \n\t\t\t\t\t\tWHERE incident_id=" . $id; $query = $db->query($sql); foreach ($query as $item) { $geometry = array("geometry" => $item->geometry, "label" => $item->geometry_label, "comment" => $item->geometry_comment, "color" => $item->geometry_color, "strokewidth" => $item->geometry_strokewidth); $form['geometry'][] = json_encode($geometry); } // Combine Everything $incident_arr = array('location_id' => $incident->location->id, 'form_id' => $incident->form_id, 'locale' => $incident->locale, 'incident_title' => $incident->incident_title, 'incident_description' => $incident->incident_description, 'incident_date' => date('m/d/Y', strtotime($incident->incident_date)), 'incident_hour' => date('h', strtotime($incident->incident_date)), 'incident_minute' => date('i', strtotime($incident->incident_date)), 'incident_ampm' => date('a', strtotime($incident->incident_date)), 'latitude' => $incident->location->latitude, 'longitude' => $incident->location->longitude, 'location_name' => $incident->location->location_name, 'country_id' => $incident->location->country_id, 'incident_category' => $incident_category, 'incident_news' => $incident_news, 'incident_video' => $incident_video, 'incident_photo' => $incident_photo, 'person_first' => $incident->incident_person->person_first, 'person_last' => $incident->incident_person->person_last, 'person_email' => $incident->incident_person->person_email, 'custom_field' => $this->_get_custom_form_fields($id, $incident->form_id, true), 'incident_source' => $incident->incident_source, 'incident_information' => $incident->incident_information, 'incident_zoom' => $incident->incident_zoom); // Merge To Form Array For Display $form = arr::overwrite($form, $incident_arr); } else { // Redirect url::redirect('members/reports/'); } } } $this->template->content->id = $id; $this->template->content->form = $form; $this->template->content->errors = $errors; $this->template->content->form_error = $form_error; $this->template->content->form_saved = $form_saved; // Retrieve Custom Form Fields Structure $disp_custom_fields = $this->_get_custom_form_fields($id, $form['form_id'], false); $this->template->content->disp_custom_fields = $disp_custom_fields; // Retrieve Previous & Next Records $previous = ORM::factory('incident')->where('id < ', $id)->orderby('id', 'desc')->find(); $previous_url = $previous->loaded ? url::base() . 'members/reports/edit/' . $previous->id : url::base() . 'members/reports/'; $next = ORM::factory('incident')->where('id > ', $id)->orderby('id', 'desc')->find(); $next_url = $next->loaded ? url::base() . 'members/reports/edit/' . $next->id : url::base() . 'members/reports/'; $this->template->content->previous_url = $previous_url; $this->template->content->next_url = $next_url; // Javascript Header $this->template->map_enabled = TRUE; $this->template->colorpicker_enabled = TRUE; $this->template->treeview_enabled = TRUE; $this->template->json2_enabled = TRUE; $this->template->js = new View('reports_submit_edit_js'); $this->template->js->edit_mode = FALSE; $this->template->js->default_map = Kohana::config('settings.default_map'); $this->template->js->default_zoom = Kohana::config('settings.default_zoom'); if (!$form['latitude'] || !$form['latitude']) { $this->template->js->latitude = Kohana::config('settings.default_lat'); $this->template->js->longitude = Kohana::config('settings.default_lon'); } else { $this->template->js->latitude = $form['latitude']; $this->template->js->longitude = $form['longitude']; } $this->template->js->incident_zoom = $form['incident_zoom']; $this->template->js->geometries = $form['geometry']; // Inline Javascript $this->template->content->date_picker_js = $this->_date_picker_js(); $this->template->content->color_picker_js = $this->_color_picker_js(); // Pack Javascript $myPacker = new javascriptpacker($this->template->js, 'Normal', false, false); $this->template->js = $myPacker->pack(); }
/** * Finds country on deployment database by name * @param string Country Name * @return int Country Id if exists, 0 if not * */ static function getCountryId($country_name) { // Grab country_id $country = Country_Model::get_country_by_name($country_name); return (!empty($country) and $country->loaded) ? $country->id : 0; }
/** * Model Validation * * @param array $array values to check * @param boolean $save save[Optional] the record when validation succeeds * @return bool TRUE when validation succeeds, FALSE otherwise */ public function validate(array &$post, $save = FALSE) { // Initialise the validation library and setup some rules $post = Validation::factory($post)->pre_filter('trim')->add_rules('alert_mobile', 'numeric', 'length[6,20]')->add_rules('alert_email', 'email', 'length[3,64]')->add_rules('alert_lat', 'required', 'between[-90,90]')->add_rules('alert_lon', 'required', 'between[-180,180]')->add_rules('alert_radius', 'required', 'in_array[1,5,10,20,50,100]')->add_rules('alert_confirmed', 'required', 'in_array[0,1]'); // TODO Callbacks to check for duplicate alert subscription - same // subscriber for the same lat/lon //$post->add_callbacks('alert_mobile', array($this, '_mobile_check')); //$post->add_callbacks('alert_email', array($this, '_email_check')); // Check if a recipient mobile phone no. or email address has been // specified if (empty($post->alert_mobile) and empty($post->alert_email)) { $post->add_rules('alert_recipient', 'required'); } // If deployment is a single country deployment, check that the location mapped is in the default country if (!Kohana::config('settings.multi_country')) { $country = Country_Model::get_country_by_name($post->alert_country); if ($country and $country->id != Kohana::config('settings.default_country')) { $post->add_error('alert_country', 'single_country'); return FALSE; } } return parent::validate($post, $save); }
/** * GeoCode An Address * * @author * @param string $address * @return array $geocodes - lat/lon */ public static function geocode($address = NULL) { if ($address) { $payload = FALSE; $url = Kohana::config('config.external_site_protocol') . '://maps.google.com/maps/api/geocode/json?sensor=false&address=' . rawurlencode($address); $result = FALSE; if ($result = @file_get_contents($url)) { $payload = json_decode($result); } // Verify that the request succeeded if (!isset($payload->status)) { return FALSE; } if ($payload->status != 'OK') { return FALSE; } // Convert the Geocoder's results to an array $all_components = json_decode(json_encode($payload->results), TRUE); $location = $all_components[0]['geometry']['location']; // Find the country $address_components = $all_components[0]['address_components']; $country_name = NULL; foreach ($address_components as $component) { if (in_array('country', $component['types'])) { $country_name = $component['long_name']; break; } } // If no country has been found, use the formatted address if (empty($country_name)) { $country_name = $all_components[0]['formatted_address']; } // Grab country_id $country = Country_Model::get_country_by_name($country_name); $country_id = (!empty($country) and $country->loaded) ? $country->id : 0; $geocodes = array('country' => $country_name, 'country_id' => $country_id, 'location_name' => $all_components[0]['formatted_address'], 'latitude' => $location['lat'], 'longitude' => $location['lng']); return $geocodes; } else { return FALSE; } }