36bcd55bc05a7699e8900366b1f6ed6113c556dc
[moodle.git] / mod / data / field / picture / field.class.php
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 ///////////////////////////////////////////////////////////////////////////
25 class data_field_picture extends data_field_base {
26     var $type = 'picture';
27     var $previewwidth  = 50;
28     var $previewheight = 50;
30     function display_add_field($recordid = 0, $formdata = null) {
31         global $CFG, $DB, $OUTPUT, $USER, $PAGE;
33         $file        = false;
34         $content     = false;
35         $displayname = '';
36         $alttext     = '';
37         $itemid = null;
38         $fs = get_file_storage();
40         if ($formdata) {
41             $fieldname = 'field_' . $this->field->id . '_file';
42             $itemid = $formdata->$fieldname;
43             $fieldname = 'field_' . $this->field->id . '_alttext';
44             if (isset($formdata->$fieldname)) {
45                 $alttext = $formdata->$fieldname;
46             }
47         } else if ($recordid) {
48             if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
49                 file_prepare_draft_area($itemid, $this->context->id, 'mod_data', 'content', $content->id);
50                 if (!empty($content->content)) {
51                     if ($file = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', $content->content)) {
52                         $usercontext = context_user::instance($USER->id);
53                         if (!$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $itemid, 'id DESC', false)) {
54                             return false;
55                         }
56                         if ($thumbfile = $fs->get_file($usercontext->id, 'user', 'draft', $itemid, '/', 'thumb_'.$content->content)) {
57                             $thumbfile->delete();
58                         }
59                         if (empty($content->content1)) {
60                             // Print icon if file already exists
61                             $src = moodle_url::make_draftfile_url($itemid, '/', $file->get_filename());
62                             $displayname = $OUTPUT->pix_icon(file_file_icon($file), get_mimetype_description($file), 'moodle', array('class' => 'icon')). '<a href="'.$src.'" >'.s($file->get_filename()).'</a>';
64                         } else {
65                             $displayname = get_string('nofilesattached', 'repository');
66                         }
67                     }
68                 }
69                 $alttext = $content->content1;
70             }
71         } else {
72             $itemid = file_get_unused_draft_itemid();
73         }
74         $str = '<div title="' . s($this->field->description) . '">';
75         $str .= '<fieldset><legend><span class="accesshide">'.$this->field->name;
77         if ($this->field->required) {
78             $str .= '&nbsp;' . get_string('requiredelement', 'form') . '</span></legend>';
79             $image = html_writer::img($OUTPUT->pix_url('req'), get_string('requiredelement', 'form'),
80                                       array('class' => 'req', 'title' => get_string('requiredelement', 'form')));
81             $str .= html_writer::div($image, 'inline-req');
82         } else {
83             $str .= '</span></legend>';
84         }
85         $str .= '<noscript>';
86         if ($file) {
87             $src = file_encode_url($CFG->wwwroot.'/pluginfile.php/', $this->context->id.'/mod_data/content/'.$content->id.'/'.$file->get_filename());
88             $str .= '<img width="'.s($this->previewwidth).'" height="'.s($this->previewheight).'" src="'.$src.'" alt="" />';
89         }
90         $str .= '</noscript>';
92         $options = new stdClass();
93         $options->maxbytes  = $this->field->param3;
94         $options->maxfiles  = 1; // Only one picture permitted.
95         $options->itemid    = $itemid;
96         $options->accepted_types = array('web_image');
97         $options->return_types = FILE_INTERNAL;
98         $options->context = $PAGE->context;
99         if (!empty($file)) {
100             $options->filename = $file->get_filename();
101             $options->filepath = '/';
102         }
104         $fm = new form_filemanager($options);
105         // Print out file manager.
107         $output = $PAGE->get_renderer('core', 'files');
108         $str .= '<div class="mod-data-input">';
109         $str .= $output->render($fm);
111         $str .= '<div class="mdl-left">';
112         $str .= '<input type="hidden" name="field_'.$this->field->id.'_file" value="'.$itemid.'" />';
113         $str .= '<label for="field_'.$this->field->id.'_alttext">'.get_string('alttext','data') .'</label>&nbsp;<input type="text" name="field_'
114                 .$this->field->id.'_alttext" id="field_'.$this->field->id.'_alttext" value="'.s($alttext).'" />';
115         $str .= '</div>';
116         $str .= '</div>';
118         $str .= '</fieldset>';
119         $str .= '</div>';
121         return $str;
122     }
124     // TODO delete this function and instead subclass data_field_file - see MDL-16493
126     function get_file($recordid, $content=null) {
127         global $DB;
128         if (empty($content)) {
129             if (!$content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
130                 return null;
131             }
132         }
133         $fs = get_file_storage();
134         if (!$file = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', $content->content)) {
135             return null;
136         }
138         return $file;
139     }
141     function display_search_field($value = '') {
142         return '<label class="accesshide" for="f_'.$this->field->id.'">' . get_string('fieldname', 'data') . '</label>' .
143                '<input type="text" size="16" id="f_'.$this->field->id.'" name="f_'.$this->field->id.'" value="'.$value.'" />';
144     }
146     function parse_search_field() {
147         return optional_param('f_'.$this->field->id, '', PARAM_NOTAGS);
148     }
150     function generate_sql($tablealias, $value) {
151         global $DB;
153         static $i=0;
154         $i++;
155         $name = "df_picture_$i";
156         return array(" ({$tablealias}.fieldid = {$this->field->id} AND ".$DB->sql_like("{$tablealias}.content", ":$name", false).") ", array($name=>"%$value%"));
157     }
159     function display_browse_field($recordid, $template) {
160         global $CFG, $DB;
162         if (!$content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
163             return false;
164         }
166         if (empty($content->content)) {
167             return '';
168         }
170         $alt   = $content->content1;
171         $title = $alt;
173         if ($template == 'listtemplate') {
174             $src = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_data/content/'.$content->id.'/'.'thumb_'.$content->content);
175             // no need to add width/height, because the thumb is resized properly
176             $str = '<a href="view.php?d='.$this->field->dataid.'&amp;rid='.$recordid.'"><img src="'.$src.'" alt="'.s($alt).'" title="'.s($title).'" class="list_picture"/></a>';
178         } else {
179             $src = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_data/content/'.$content->id.'/'.$content->content);
180             $width  = $this->field->param1 ? ' width="'.s($this->field->param1).'" ':' ';
181             $height = $this->field->param2 ? ' height="'.s($this->field->param2).'" ':' ';
182             $str = '<a href="'.$src.'"><img '.$width.$height.' src="'.$src.'" alt="'.s($alt).'" title="'.s($title).'" class="list_picture"/></a>';
183         }
185         return $str;
186     }
188     function update_field() {
189         global $DB, $OUTPUT;
191         // Get the old field data so that we can check whether the thumbnail dimensions have changed
192         $oldfield = $DB->get_record('data_fields', array('id'=>$this->field->id));
193         $DB->update_record('data_fields', $this->field);
195         // Have the thumbnail dimensions changed?
196         if ($oldfield && ($oldfield->param4 != $this->field->param4 || $oldfield->param5 != $this->field->param5)) {
197             // Check through all existing records and update the thumbnail
198             if ($contents = $DB->get_records('data_content', array('fieldid'=>$this->field->id))) {
199                 $fs = get_file_storage();
200                 if (count($contents) > 20) {
201                     echo $OUTPUT->notification(get_string('resizingimages', 'data'), 'notifysuccess');
202                     echo "\n\n";
203                     // To make sure that ob_flush() has the desired effect
204                     ob_flush();
205                 }
206                 foreach ($contents as $content) {
207                     if (!$file = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', $content->content)) {
208                         continue;
209                     }
210                     if ($thumbfile = $fs->get_file($this->context->id, 'mod_data', 'content', $content->id, '/', 'thumb_'.$content->content)) {
211                         $thumbfile->delete();
212                     }
213                     core_php_time_limit::raise(300);
214                     // Might be slow!
215                     $this->update_thumbnail($content, $file);
216                 }
217             }
218         }
219         return true;
220     }
222     function update_content($recordid, $value, $name='') {
223         global $CFG, $DB, $USER;
225         if (!$content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
226         // Quickly make one now!
227             $content = new stdClass();
228             $content->fieldid  = $this->field->id;
229             $content->recordid = $recordid;
230             $id = $DB->insert_record('data_content', $content);
231             $content = $DB->get_record('data_content', array('id'=>$id));
232         }
234         $names = explode('_', $name);
235         switch ($names[2]) {
236             case 'file':
237                 $fs = get_file_storage();
238                 file_save_draft_area_files($value, $this->context->id, 'mod_data', 'content', $content->id);
239                 $usercontext = context_user::instance($USER->id);
240                 $files = $fs->get_area_files(
241                     $this->context->id,
242                     'mod_data', 'content',
243                     $content->id,
244                     'itemid, filepath, filename',
245                     false);
247                 // We expect no or just one file (maxfiles = 1 option is set for the form_filemanager).
248                 if (count($files) == 0) {
249                     $content->content = null;
250                 } else {
251                     $file = array_values($files)[0];
253                     if (count($files) > 1) {
254                         // This should not happen with a consistent database. Inform admins/developers about the inconsistency.
255                         debugging('more then one file found in mod_data instance {$this->data->id} picture field (field id: {$this->field->id}) area during update data record {$recordid} (content id: {$content->id})', DEBUG_NORMAL);
256                     }
258                     if ($file->get_imageinfo() === false) {
259                         $url = new moodle_url('/mod/data/edit.php', array('d' => $this->field->dataid));
260                         redirect($url, get_string('invalidfiletype', 'error', $file->get_filename()));
261                     }
262                     $content->content = $file->get_filename();
263                     $this->update_thumbnail($content, $file);
264                 }
265                 $DB->update_record('data_content', $content);
267                 break;
269             case 'alttext':
270                 // only changing alt tag
271                 $content->content1 = clean_param($value, PARAM_NOTAGS);
272                 $DB->update_record('data_content', $content);
273                 break;
275             default:
276                 break;
277         }
278     }
280     function update_thumbnail($content, $file) {
281         // (Re)generate thumbnail image according to the dimensions specified in the field settings.
282         // If thumbnail width and height are BOTH not specified then no thumbnail is generated, and
283         // additionally an attempted delete of the existing thumbnail takes place.
284         $fs = get_file_storage();
285         $file_record = array('contextid'=>$file->get_contextid(), 'component'=>$file->get_component(), 'filearea'=>$file->get_filearea(),
286                              'itemid'=>$file->get_itemid(), 'filepath'=>$file->get_filepath(),
287                              'filename'=>'thumb_'.$file->get_filename(), 'userid'=>$file->get_userid());
288         try {
289             // this may fail for various reasons
290             $fs->convert_image($file_record, $file, $this->field->param4, $this->field->param5, true);
291             return true;
292         } catch (Exception $e) {
293             debugging($e->getMessage());
294             return false;
295         }
296     }
298     function text_export_supported() {
299         return false;
300     }
302     function file_ok($path) {
303         return true;
304     }
306     /**
307      * Custom notempty function
308      *
309      * @param string $value
310      * @param string $name
311      * @return bool
312      */
313     function notemptyfield($value, $name) {
314         global $USER;
316         $names = explode('_', $name);
317         if ($names[2] == 'file') {
318             $usercontext = context_user::instance($USER->id);
319             $fs = get_file_storage();
320             $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $value);
321             return count($files) >= 2;
322         }
323         return false;
324     }