Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
///////////////////////////////////////////////////////////////////////////
3
//                                                                       //
4
// NOTICE OF COPYRIGHT                                                   //
5
//                                                                       //
6
// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
7
//          http://moodle.org                                            //
8
//                                                                       //
9
// Copyright (C) 1999-onwards Moodle Pty Ltd  http://moodle.com          //
10
//                                                                       //
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.                                   //
15
//                                                                       //
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:                          //
20
//                                                                       //
21
//          http://www.gnu.org/copyleft/gpl.html                         //
22
//                                                                       //
23
///////////////////////////////////////////////////////////////////////////
24
 
25
class data_field_latlong extends data_field_base {
26
    var $type = 'latlong';
27
 
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.
32
 
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.
36
 
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"
43
    );
44
    // Other map sources listed at http://kvaleberg.com/extensions/mapsources/index.php?params=51_30.4167_N_0_7.65_W_region:earth
45
 
46
    public function supports_preview(): bool {
47
        return true;
48
    }
49
 
50
    public function get_data_content_preview(int $recordid): stdClass {
51
        return (object)[
52
            'id' => 0,
53
            'fieldid' => $this->field->id,
54
            'recordid' => $recordid,
55
            'content' => 41.391205,
56
            'content1' => 2.163873,
57
            'content2' => null,
58
            'content3' => null,
59
            'content4' => null,
60
        ];
61
    }
62
 
63
    function display_add_field($recordid = 0, $formdata = null) {
64
        global $CFG, $DB, $OUTPUT;
65
 
66
        $lat = '';
67
        $long = '';
68
        if ($formdata) {
69
            $fieldname = 'field_' . $this->field->id . '_0';
70
            $lat = $formdata->$fieldname;
71
            $fieldname = 'field_' . $this->field->id . '_1';
72
            $long = $formdata->$fieldname;
73
        } else if ($recordid) {
74
            if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
75
                $lat  = $content->content;
76
                $long = $content->content1;
77
            }
78
        }
79
        $str = '<div title="'.s($this->field->description).'">';
80
        $str .= '<fieldset><legend><span class="accesshide">'.s($this->field->name).'</span></legend>';
81
        $str .= '<table class="d-flex flex-wrap align-items-center"><tr><td align="right">';
82
        $classes = 'mod-data-input form-control-static';
83
        $str .= '<label for="field_'.$this->field->id.'_0" class="' . $classes . '">' . get_string('latitude', 'data');
84
        if ($this->field->required) {
85
            $str .= $OUTPUT->pix_icon('req', get_string('requiredelement', 'form'));
86
        }
87
        $classes = 'form-control mx-1';
88
        $str .= '</label></td><td>';
89
        $str .= '<input class="' . $classes . '" type="text" name="field_'.$this->field->id.'_0" ';
90
        $str .= ' id="field_'.$this->field->id.'_0" value="';
91
        $str .= s($lat).'" size="10" />°N</td></tr>';
92
        $classes = 'mod-data-input form-control-static';
93
        $str .= '<tr><td align="right"><label for="field_'.$this->field->id.'_1" class="' . $classes . '">';
94
        $str .= get_string('longitude', 'data');
95
        if ($this->field->required) {
96
            $str .= $OUTPUT->pix_icon('req', get_string('requiredelement', 'form'));
97
        }
98
        $classes = 'form-control mx-1';
99
        $str .= '</label></td><td><input class="' . $classes . '" type="text" ';
100
        $str .= 'name="field_'.$this->field->id.'_1" id="field_'.$this->field->id.'_1" value="';
101
        $str .= s($long).'" size="10" />°E</td>';
102
        $str .= '</tr>';
103
        $str .= '</table>';
104
        $str .= '</fieldset>';
105
        $str .= '</div>';
106
        return $str;
107
    }
108
 
109
    function display_search_field($value = '') {
110
        global $CFG, $DB;
111
 
112
        $varcharlat = $DB->sql_compare_text('content');
113
        $varcharlong= $DB->sql_compare_text('content1');
114
        $latlongsrs = $DB->get_recordset_sql(
115
            "SELECT DISTINCT $varcharlat AS la, $varcharlong AS lo
116
               FROM {data_content}
117
              WHERE fieldid = ?
118
             ORDER BY $varcharlat, $varcharlong", array($this->field->id));
119
 
120
        $options = array();
121
        foreach ($latlongsrs as $latlong) {
122
            $latitude = format_float($latlong->la, 4);
123
            $longitude = format_float($latlong->lo, 4);
124
            if ($latitude && $longitude) {
125
                $options[$latlong->la . ',' . $latlong->lo] = $latitude . ' ' . $longitude;
126
            }
127
        }
128
        $latlongsrs->close();
129
 
130
        $classes = array('class' => 'accesshide');
131
        $return = html_writer::label(get_string('latlong', 'data'), 'menuf_'.$this->field->id, false, $classes);
132
        $classes = array('class' => 'custom-select');
133
        $return .= html_writer::select($options, 'f_'.$this->field->id, $value, array('' => get_string('menuchoose', 'data')),
134
            $classes);
135
       return $return;
136
    }
137
 
138
    public function parse_search_field($defaults = null) {
139
        $param = 'f_'.$this->field->id;
140
        if (empty($defaults[$param])) {
141
            $defaults = array($param => '');
142
        }
143
        return optional_param($param, $defaults[$param], PARAM_NOTAGS);
144
    }
145
 
146
    function generate_sql($tablealias, $value) {
147
        global $DB;
148
 
149
        static $i=0;
150
        $i++;
151
        $name1 = "df_latlong1_$i";
152
        $name2 = "df_latlong2_$i";
153
        $varcharlat = $DB->sql_compare_text("{$tablealias}.content");
154
        $varcharlong= $DB->sql_compare_text("{$tablealias}.content1");
155
 
156
 
157
        $latlong[0] = '';
158
        $latlong[1] = '';
159
        $latlong = explode (',', $value, 2);
160
        return array(" ({$tablealias}.fieldid = {$this->field->id} AND $varcharlat = :$name1 AND $varcharlong = :$name2) ",
161
                     array($name1=>$latlong[0], $name2=>$latlong[1]));
162
    }
163
 
164
    function display_browse_field($recordid, $template) {
165
        global $CFG;
166
 
167
        $content = $this->get_data_content($recordid);
168
        if (!$content) {
169
            return '';
170
        }
171
 
172
        $lat = $content->content;
173
        if (strlen($lat ?? '') < 1) {
174
            return '';
175
        }
176
        $long = $content->content1;
177
        if (strlen($long ?? '') < 1) {
178
            return '';
179
        }
180
        // We use format_float to display in the regional format.
181
        if ($lat < 0) {
182
            $compasslat = format_float(-$lat, 4) . '°S';
183
        } else {
184
            $compasslat = format_float($lat, 4) . '°N';
185
        }
186
        if ($long < 0) {
187
            $compasslong = format_float(-$long, 4) . '°W';
188
        } else {
189
            $compasslong = format_float($long, 4) . '°E';
190
        }
191
 
192
        // Now let's create the jump-to-services link.
193
        $servicesshown = explode(',', $this->field->param1);
194
 
195
        // These are the different things that can be magically inserted into URL schemes.
196
        $urlreplacements = array(
197
            '@lat@' => $lat,
198
            '@long@' => $long,
199
            '@wwwroot@' => $CFG->wwwroot,
200
            '@contentid@' => $content->id,
201
            '@dataid@' => $this->data->id,
202
            '@courseid@' => $this->data->course,
203
            '@fieldid@' => $content->fieldid,
204
            '@recordid@' => $content->recordid,
205
        );
206
 
207
        if (count($servicesshown) == 1 && $servicesshown[0]) {
208
            $str = " <a class=\"data-field-link\" href='"
209
                        . str_replace(
210
                            array_keys($urlreplacements),
211
                            array_values($urlreplacements),
212
                            $this->linkoutservices[$servicesshown[0]]
213
                        ) . "' title='$servicesshown[0]'>$compasslat $compasslong</a>";
214
        } else if (count($servicesshown) > 1) {
215
            $str = '<form id="latlongfieldbrowse" class="data-field-html">';
216
            $str .= "$compasslat, $compasslong\n";
217
            $str .= "<label class='accesshide' for='jumpto'>". get_string('jumpto') ."</label>";
218
            $str .= '<select id="jumpto" name="jumpto" class="custom-select">';
219
            foreach ($servicesshown as $servicename) {
220
                // Add a link to a service.
221
                $str .= "\n  <option value='"
222
                            . str_replace(
223
                                array_keys($urlreplacements),
224
                                array_values($urlreplacements),
225
                                $this->linkoutservices[$servicename]
226
                            ) . "'>".htmlspecialchars($servicename, ENT_COMPAT)."</option>";
227
            }
228
            // NB! If you are editing this, make sure you don't break the javascript reference "previousSibling"
229
            // which allows the "Go" button to refer to the drop-down selector.
230
            $str .= '\n</select><input type="button" class="btn ml-1 btn-secondary" value="' . get_string('go');
231
            $str .= '" onclick="if(previousSibling.value){self.location=previousSibling.value}"/>';
232
            $str .= '</form>';
233
        } else {
234
            $str = "$compasslat, $compasslong";
235
        }
236
 
237
        return $str;
238
    }
239
 
240
    function update_content_import($recordid, $value, $name='') {
241
        $values = explode(" ", $value, 2);
242
 
243
        foreach ($values as $index => $value) {
244
            $this->update_content($recordid, $value, $name . '_' . $index);
245
        }
246
    }
247
 
248
    function update_content($recordid, $value, $name='') {
249
        global $DB;
250
 
251
        $content = new stdClass();
252
        $content->fieldid = $this->field->id;
253
        $content->recordid = $recordid;
254
        // When updating these values (which might be region formatted) we should format
255
        // the float to allow for a consistent float format in the database.
256
        $value = unformat_float($value);
257
        $value = trim($value ?? '');
258
        if (strlen($value) > 0) {
259
            $value = floatval($value);
260
        } else {
261
            $value = null;
262
        }
263
        $names = explode('_', $name);
264
        switch ($names[2]) {
265
            case 0:
266
                // update lat
267
                $content->content = $value;
268
                break;
269
            case 1:
270
                // update long
271
                $content->content1 = $value;
272
                break;
273
            default:
274
                break;
275
        }
276
        if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
277
            $content->id = $oldcontent->id;
278
            return $DB->update_record('data_content', $content);
279
        } else {
280
            return $DB->insert_record('data_content', $content);
281
        }
282
    }
283
 
284
    function get_sort_sql($fieldname) {
285
        global $DB;
286
        return $DB->sql_cast_char2real($fieldname, true);
287
    }
288
 
289
    function export_text_value($record) {
290
        // The content here is from the database and does not require location formating.
291
        return sprintf('%01.4f', $record->content) . ' ' . sprintf('%01.4f', $record->content1);
292
    }
293
 
294
    /**
295
     * Check if a field from an add form is empty
296
     *
297
     * @param mixed $value
298
     * @param mixed $name
299
     * @return bool
300
     */
301
    function notemptyfield($value, $name) {
302
        return isset($value) && !($value == '');
303
    }
304
 
305
    /**
306
     * Validate values for this field.
307
     * Both the Latitude and the Longitude fields need to be filled in.
308
     *
309
     * @param array $values The entered values for the lat. and long.
310
     * @return string|bool Error message or false.
311
     */
312
    public function field_validation($values) {
313
        $valuecount = 0;
314
        // The lat long class has two values that need to be checked.
315
        foreach ($values as $value) {
316
            if (isset($value->value) && !($value->value == '')) {
317
                $valuecount++;
318
            }
319
        }
320
        // If we have nothing filled in or both filled in then everything is okay.
321
        if ($valuecount == 0 || $valuecount == 2) {
322
            return false;
323
        }
324
        // If we get here then only one field has been filled in.
325
        return get_string('latlongboth', 'data');
326
    }
327
 
328
    /**
329
     * Return the plugin configs for external functions.
330
     *
331
     * @return array the list of config parameters
332
     * @since Moodle 3.3
333
     */
334
    public function get_config_for_external() {
335
        // Return all the config parameters.
336
        $configs = [];
337
        for ($i = 1; $i <= 10; $i++) {
338
            $configs["param$i"] = $this->field->{"param$i"};
339
        }
340
        return $configs;
341
    }
342
 
343
    public function get_field_params(): array {
344
        global $DB;
345
 
346
        $data = parent::get_field_params();
347
        $data['dataid'] = $this->data->id;
348
 
349
        if (isset($this->field->param1)) {
350
            $data["param1"] = $this->field->param1;
351
            if (isset($this->linkoutservices)) {
352
                $serviceschosen = explode(',', htmlspecialchars($this->field->param1));
353
                foreach ($this->linkoutservices as $servicename => $serviceurl) {
354
                    $servicename = htmlspecialchars($servicename);
355
                    $data['latlonglinkservices'][] = [
356
                        'name' => $servicename,
357
                        'selected' => in_array($servicename, $serviceschosen),
358
                    ];
359
                    unset($serviceschosen[$servicename]);
360
                }
361
                $data['latlonglinkservicessize'] = count($this->linkoutservices);
362
            }
363
        }
364
 
365
        $data["otherfields"][] = [
366
            'value' => -1,
367
            'name' => get_string('entry', 'data') . " #",
368
            'selected' => $this->field->param2 == -1,
369
        ];
370
        $data['otherfields'][] = [
371
            'value' => -2,
372
            'name' => get_string('latitude', 'data') . "/" . get_string('longitude', 'data'),
373
            'selected' => $this->field->param2 == -2,
374
        ];
375
 
376
        // Fetch all "suitable" other fields that exist for this database.
377
        $textfields = $DB->get_records('data_fields', ['dataid' => $this->data->id, 'type' => 'text']);
378
        if (count($textfields) > 0) {
379
            $data['otherfieldsoptgroups']['label'] = get_string('latlongotherfields', 'data') . ":";
380
            foreach ($textfields as $textfield) {
381
                $data['otherfieldsoptgroups']['options'][] = [
382
                    'value' => $textfield->id,
383
                    'name' => $textfield->name,
384
                    'selected' => $this->field->param2 == $textfield->id,
385
                ];
386
            }
387
        }
388
        if (isset($data['otherfieldsoptgroups'])) {
389
            $data['otherfields'][] = $data['otherfieldsoptgroups'];
390
        }
391
        if (isset($this->field->id)) {
392
            $data['fieldid'] = $this->field->id;
393
        }
394
 
395
        return $data;
396
    }
397
}