2 ///////////////////////////////////////////////////////////////////////////
4 // NOTICE OF COPYRIGHT //
6 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
7 // http://moodle.org //
9 // Copyright (C) 1999-onwards Moodle Pty Ltd http://moodle.com //
11 // This program is free software; you can redistribute it and/or modify //
12 // it under the terms of the GNU General Public License as published by //
13 // the Free Software Foundation; either version 2 of the License, or //
14 // (at your option) any later version. //
16 // This program is distributed in the hope that it will be useful, //
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
19 // GNU General Public License for more details: //
21 // http://www.gnu.org/copyleft/gpl.html //
23 ///////////////////////////////////////////////////////////////////////////
25 class data_field_latlong
extends data_field_base
{
26 var $type = 'latlong';
28 // This is an array of URL schemes for linking out to services, using the float values of lat and long.
29 // In each scheme, the special markers @lat@ and @long@ will be replaced by the float values.
30 // The config options for the field store each service name that should be displayed, in a comma-separated
31 // field. Therefore please DO NOT include commas in the service names if you are adding extra services.
33 // Parameter data used:
34 // "param1" is a comma-separated list of the linkout service names that are enabled for this instance
35 // "param2" indicates the label that will be used in generating Google Earth KML files: -1 for item #, -2 for lat/long, positive number for the (text) field to use.
37 var $linkoutservices = array(
38 "Google Maps" => "http://maps.google.com/maps?q=@lat@,+@long@&iwloc=A&hl=en",
39 "Google Earth" => "@wwwroot@/mod/data/field/latlong/kml.php?d=@dataid@&fieldid=@fieldid@&rid=@recordid@",
40 "Geabios" => "http://www.geabios.com/html/services/maps/PublicMap.htm?lat=@lat@&lon=@long@&fov=0.3&title=Moodle%20data%20item",
41 "OpenStreetMap" => "http://www.openstreetmap.org/index.html?lat=@lat@&lon=@long@&zoom=11",
42 "Multimap" => "http://www.multimap.com/map/browse.cgi?scale=200000&lon=@long@&lat=@lat@&icon=x"
44 // Other map sources listed at http://kvaleberg.com/extensions/mapsources/index.php?params=51_30.4167_N_0_7.65_W_region:earth
46 function display_add_field($recordid = 0, $formdata = null) {
47 global $CFG, $DB, $OUTPUT;
52 $fieldname = 'field_' . $this->field
->id
. '_0';
53 $lat = $formdata->$fieldname;
54 $fieldname = 'field_' . $this->field
->id
. '_1';
55 $long = $formdata->$fieldname;
56 } else if ($recordid) {
57 if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field
->id
, 'recordid'=>$recordid))) {
58 $lat = $content->content
;
59 $long = $content->content1
;
62 $str = '<div title="'.s($this->field
->description
).'">';
63 $str .= '<fieldset><legend><span class="accesshide">'.$this->field
->name
.'</span></legend>';
64 $str .= '<table class="form-inline"><tr><td align="right">';
65 $classes = 'mod-data-input form-control-static';
66 $str .= '<label for="field_'.$this->field
->id
.'_0" class="' . $classes . '">' . get_string('latitude', 'data');
67 if ($this->field
->required
) {
68 $str .= $OUTPUT->pix_icon('req', get_string('requiredelement', 'form'));
70 $classes = 'form-control m-x-1';
71 $str .= '</label></td><td>';
72 $str .= '<input class="' . $classes . '" type="text" name="field_'.$this->field
->id
.'_0" ';
73 $str .= ' id="field_'.$this->field
->id
.'_0" value="';
74 $str .= s($lat).'" size="10" />°N</td></tr>';
75 $classes = 'mod-data-input form-control-static';
76 $str .= '<tr><td align="right"><label for="field_'.$this->field
->id
.'_1" class="' . $classes . '">';
77 $str .= get_string('longitude', 'data');
78 if ($this->field
->required
) {
79 $str .= $OUTPUT->pix_icon('req', get_string('requiredelement', 'form'));
81 $classes = 'form-control m-x-1';
82 $str .= '</label></td><td><input class="' . $classes . '" type="text" ';
83 $str .= 'name="field_'.$this->field
->id
.'_1" id="field_'.$this->field
->id
.'_1" value="';
84 $str .= s($long).'" size="10" />°E</td>';
87 $str .= '</fieldset>';
92 function display_search_field($value = '') {
95 $varcharlat = $DB->sql_compare_text('content');
96 $varcharlong= $DB->sql_compare_text('content1');
97 $latlongsrs = $DB->get_recordset_sql(
98 "SELECT DISTINCT $varcharlat AS la, $varcharlong AS lo
101 ORDER BY $varcharlat, $varcharlong", array($this->field
->id
));
104 foreach ($latlongsrs as $latlong) {
105 $latitude = format_float($latlong->la
, 4);
106 $longitude = format_float($latlong->lo
, 4);
107 $options[$latlong->la
. ',' . $latlong->lo
] = $latitude . ' ' . $longitude;
109 $latlongsrs->close();
111 $classes = array('class' => 'accesshide');
112 $return = html_writer
::label(get_string('latlong', 'data'), 'menuf_'.$this->field
->id
, false, $classes);
113 $classes = array('class' => 'custom-select');
114 $return .= html_writer
::select($options, 'f_'.$this->field
->id
, $value, null, $classes);
118 public function parse_search_field($defaults = null) {
119 $param = 'f_'.$this->field
->id
;
120 if (empty($defaults[$param])) {
121 $defaults = array($param => '');
123 return optional_param($param, $defaults[$param], PARAM_NOTAGS
);
126 function generate_sql($tablealias, $value) {
131 $name1 = "df_latlong1_$i";
132 $name2 = "df_latlong2_$i";
133 $varcharlat = $DB->sql_compare_text("{$tablealias}.content");
134 $varcharlong= $DB->sql_compare_text("{$tablealias}.content1");
139 $latlong = explode (',', $value, 2);
140 return array(" ({$tablealias}.fieldid = {$this->field->id} AND $varcharlat = :$name1 AND $varcharlong = :$name2) ",
141 array($name1=>$latlong[0], $name2=>$latlong[1]));
144 function display_browse_field($recordid, $template) {
146 if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field
->id
, 'recordid'=>$recordid))) {
147 $lat = $content->content
;
148 if (strlen($lat) < 1) {
151 $long = $content->content1
;
152 if (strlen($long) < 1) {
155 // We use format_float to display in the regional format.
157 $compasslat = format_float(-$lat, 4) . '°S';
159 $compasslat = format_float($lat, 4) . '°N';
162 $compasslong = format_float(-$long, 4) . '°W';
164 $compasslong = format_float($long, 4) . '°E';
167 // Now let's create the jump-to-services link
168 $servicesshown = explode(',', $this->field
->param1
);
170 // These are the different things that can be magically inserted into URL schemes
171 $urlreplacements = array(
174 '@wwwroot@'=> $CFG->wwwroot
,
175 '@contentid@'=> $content->id
,
176 '@dataid@'=> $this->data
->id
,
177 '@courseid@'=> $this->data
->course
,
178 '@fieldid@'=> $content->fieldid
,
179 '@recordid@'=> $content->recordid
,
182 if(sizeof($servicesshown)==1 && $servicesshown[0]) {
184 . str_replace(array_keys($urlreplacements), array_values($urlreplacements), $this->linkoutservices
[$servicesshown[0]])
185 ."' title='$servicesshown[0]'>$compasslat $compasslong</a>";
186 } elseif (sizeof($servicesshown)>1) {
187 $str = '<form id="latlongfieldbrowse">';
188 $str .= "$compasslat, $compasslong\n";
189 $str .= "<label class='accesshide' for='jumpto'>". get_string('jumpto') ."</label>";
190 $str .= '<select id="jumpto" name="jumpto" class="custom-select">';
191 foreach($servicesshown as $servicename){
192 // Add a link to a service
193 $str .= "\n <option value='"
194 . str_replace(array_keys($urlreplacements), array_values($urlreplacements), $this->linkoutservices
[$servicename])
195 . "'>".htmlspecialchars($servicename)."</option>";
197 // NB! If you are editing this, make sure you don't break the javascript reference "previousSibling"
198 // which allows the "Go" button to refer to the drop-down selector.
199 $str .= '\n</select><input type="button" class="btn m-l-1 btn-secondary" value="' . get_string('go');
200 $str .= '" onclick="if(previousSibling.value){self.location=previousSibling.value}"/>';
203 $str = "$compasslat, $compasslong";
211 function update_content_import($recordid, $value, $name='') {
212 $values = explode(" ", $value, 2);
214 foreach ($values as $index => $value) {
215 $this->update_content($recordid, $value, $name . '_' . $index);
219 function update_content($recordid, $value, $name='') {
222 $content = new stdClass();
223 $content->fieldid
= $this->field
->id
;
224 $content->recordid
= $recordid;
225 // When updating these values (which might be region formatted) we should format
226 // the float to allow for a consistent float format in the database.
227 $value = unformat_float($value);
228 $value = trim($value);
229 if (strlen($value) > 0) {
230 $value = floatval($value);
234 $names = explode('_', $name);
238 $content->content
= $value;
242 $content->content1
= $value;
247 if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field
->id
, 'recordid'=>$recordid))) {
248 $content->id
= $oldcontent->id
;
249 return $DB->update_record('data_content', $content);
251 return $DB->insert_record('data_content', $content);
255 function get_sort_sql($fieldname) {
257 return $DB->sql_cast_char2real($fieldname, true);
260 function export_text_value($record) {
261 // The content here is from the database and does not require location formating.
262 return sprintf('%01.4f', $record->content
) . ' ' . sprintf('%01.4f', $record->content1
);
266 * Check if a field from an add form is empty
268 * @param mixed $value
272 function notemptyfield($value, $name) {
273 return isset($value) && !($value == '');
277 * Validate values for this field.
278 * Both the Latitude and the Longitude fields need to be filled in.
280 * @param array $values The entered values for the lat. and long.
281 * @return string|bool Error message or false.
283 public function field_validation($values) {
285 // The lat long class has two values that need to be checked.
286 foreach ($values as $value) {
287 if (isset($value->value
) && !($value->value
== '')) {
291 // If we have nothing filled in or both filled in then everything is okay.
292 if ($valuecount == 0 ||
$valuecount == 2) {
295 // If we get here then only one field has been filled in.
296 return get_string('latlongboth', 'data');
300 * Return the plugin configs for external functions.
302 * @return array the list of config parameters
305 public function get_config_for_external() {
306 // Return all the config parameters.
308 for ($i = 1; $i <= 10; $i++
) {
309 $configs["param$i"] = $this->field
->{"param$i"};