Commit | Line | Data |
---|---|---|
87fcac8d | 1 | <?php |
93dd2725 RW |
2 | // This file is part of Moodle - http://moodle.org/ |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
87fcac8d | 17 | /** |
87fcac8d | 18 | * This file contains the base classes for portfolio plugins to inherit from: |
93dd2725 | 19 | * |
87fcac8d | 20 | * portfolio_plugin_pull_base and portfolio_plugin_push_base |
21 | * which both in turn inherit from portfolio_plugin_base. | |
93dd2725 RW |
22 | * {@link http://docs.moodle.org/dev/Writing_a_Portfolio_Plugin} |
23 | * | |
24 | * @package core_portfolio | |
25 | * @copyright 2008 Penny Leach <penny@catalyst.net.nz>, | |
26 | * Martin Dougiamas <http://dougiamas.com> | |
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
87fcac8d | 28 | */ |
29 | ||
0972665f PS |
30 | defined('MOODLE_INTERNAL') || die(); |
31 | ||
87fcac8d | 32 | /** |
93dd2725 | 33 | * The base class for portfolio plugins. |
18cdcdbf | 34 | * |
93dd2725 | 35 | * All plugins must subclass this |
18cdcdbf SH |
36 | * either via portfolio_plugin_pull_base or portfolio_plugin_push_base |
37 | * @see portfolio_plugin_pull_base | |
38 | * @see portfolio_plugin_push_base | |
93dd2725 RW |
39 | * |
40 | * @package core_portfolio | |
41 | * @category portfolio | |
42 | * @copyright 2008 Penny Leach <penny@catalyst.net.nz> | |
43 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
44 | */ | |
87fcac8d | 45 | abstract class portfolio_plugin_base { |
46 | ||
93dd2725 | 47 | /** @var bool whether this object needs writing out to the database */ |
87fcac8d | 48 | protected $dirty; |
49 | ||
93dd2725 | 50 | /** @var integer id of instance */ |
87fcac8d | 51 | protected $id; |
52 | ||
93dd2725 | 53 | /** @var string name of instance */ |
87fcac8d | 54 | protected $name; |
55 | ||
93dd2725 | 56 | /** @var string plugin this instance belongs to */ |
87fcac8d | 57 | protected $plugin; |
58 | ||
93dd2725 | 59 | /** @var bool whether this instance is visible or not */ |
87fcac8d | 60 | protected $visible; |
61 | ||
93dd2725 | 62 | /** @var array admin configured config use {@link set_config} and {@get_config} to access */ |
87fcac8d | 63 | protected $config; |
64 | ||
93dd2725 | 65 | /** @var array user config cache. keyed on userid and then on config field => value use {@link get_user_config} and {@link set_user_config} to access. */ |
87fcac8d | 66 | protected $userconfig; |
67 | ||
93dd2725 | 68 | /** @var array export config during export use {@link get_export_config} and {@link set export_config} to access. */ |
87fcac8d | 69 | protected $exportconfig; |
70 | ||
93dd2725 | 71 | /** @var stdClass user currently exporting data */ |
87fcac8d | 72 | protected $user; |
73 | ||
93dd2725 | 74 | /** @var stdClass a reference to the exporter object */ |
87fcac8d | 75 | protected $exporter; |
76 | ||
77 | /** | |
93dd2725 RW |
78 | * Array of formats this portfolio supports |
79 | * the intersection of what this function returns | |
80 | * and what the caller supports will be used. | |
81 | * Use the constants PORTFOLIO_FORMAT_* | |
82 | * | |
83 | * @return array list of formats | |
84 | */ | |
38652d90 | 85 | public function supported_formats() { |
59dd457e | 86 | return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_RICH); |
6be1dcae | 87 | } |
88 | ||
89 | /** | |
93dd2725 RW |
90 | * Override this if you are supporting the 'file' type (or a subformat) |
91 | * but have restrictions on mimetypes | |
92 | * | |
93 | * @param string $mimetype file type or subformat | |
94 | * @return bool | |
95 | */ | |
6be1dcae | 96 | public static function file_mime_check($mimetype) { |
97 | return true; | |
87fcac8d | 98 | } |
99 | ||
100 | ||
101 | /** | |
93dd2725 RW |
102 | * How long does this reasonably expect to take.. |
103 | * Should we offer the user the option to wait.. | |
104 | * This is deliberately nonstatic so it can take filesize into account | |
105 | * | |
106 | * @param string $callertime - what the caller thinks | |
107 | * the portfolio plugin instance | |
108 | * is given the final say | |
109 | * because it might be (for example) download. | |
110 | */ | |
87fcac8d | 111 | public abstract function expected_time($callertime); |
112 | ||
113 | /** | |
93dd2725 RW |
114 | * Is this plugin push or pull. |
115 | * If push, cleanup will be called directly after send_package | |
116 | * If not, cleanup will be called after portfolio/file.php is requested | |
117 | */ | |
87fcac8d | 118 | public abstract function is_push(); |
119 | ||
086831a6 | 120 | /** |
93dd2725 RW |
121 | * Returns the user-friendly name for this plugin. |
122 | * Usually just get_string('pluginname', 'portfolio_something') | |
086831a6 | 123 | */ |
7c109ea3 PS |
124 | public static function get_name() { |
125 | throw new coding_exception('get_name() method needs to be overridden in each subclass of portfolio_plugin_base'); | |
126 | } | |
87fcac8d | 127 | |
128 | /** | |
93dd2725 RW |
129 | * Check sanity of plugin. |
130 | * If this function returns something non empty, ALL instances of your plugin | |
131 | * will be set to invisble and not be able to be set back until it's fixed | |
132 | * | |
133 | * @return string|int|bool - string = error string KEY (must be inside portfolio_$yourplugin) or 0/false if you're ok | |
134 | */ | |
87fcac8d | 135 | public static function plugin_sanity_check() { |
136 | return 0; | |
137 | } | |
138 | ||
139 | /** | |
93dd2725 RW |
140 | * Check sanity of instances. |
141 | * If this function returns something non empty, the instance will be | |
142 | * set to invislbe and not be able to be set back until it's fixed. | |
143 | * | |
144 | * @return int|string|bool - string = error string KEY (must be inside portfolio_$yourplugin) or 0/false if you're ok | |
145 | */ | |
87fcac8d | 146 | public function instance_sanity_check() { |
147 | return 0; | |
148 | } | |
149 | ||
150 | /** | |
93dd2725 RW |
151 | * Does this plugin need any configuration by the administrator? |
152 | * If you override this to return true, | |
18cdcdbf SH |
153 | * you <b>must</b> implement admin_config_form. |
154 | * @see admin_config_form | |
93dd2725 RW |
155 | * |
156 | * @return bool | |
157 | */ | |
87fcac8d | 158 | public static function has_admin_config() { |
159 | return false; | |
160 | } | |
161 | ||
162 | /** | |
93dd2725 RW |
163 | * Can this plugin be configured by the user in their profile? |
164 | * If you override this to return true, | |
18cdcdbf SH |
165 | * you <b>must</b> implement user_config_form |
166 | * @see user_config_form | |
93dd2725 RW |
167 | * |
168 | * @return bool | |
169 | */ | |
87fcac8d | 170 | public function has_user_config() { |
171 | return false; | |
172 | } | |
173 | ||
174 | /** | |
93dd2725 RW |
175 | * Does this plugin need configuration during export time? |
176 | * If you override this to return true, | |
18cdcdbf SH |
177 | * you <b>must</b> implement export_config_form. |
178 | * @see export_config_form | |
93dd2725 RW |
179 | * |
180 | * @return bool | |
181 | */ | |
87fcac8d | 182 | public function has_export_config() { |
183 | return false; | |
184 | } | |
185 | ||
186 | /** | |
93dd2725 RW |
187 | * Just like the moodle form validation function. |
188 | * This is passed in the data array from the form | |
189 | * and if a non empty array is returned, form processing will stop. | |
190 | * | |
191 | * @param array $data data from form. | |
192 | */ | |
6a2640d2 | 193 | public function export_config_validation(array $data) {} |
87fcac8d | 194 | |
195 | /** | |
93dd2725 RW |
196 | * Just like the moodle form validation function. |
197 | * This is passed in the data array from the form | |
198 | * and if a non empty array is returned, form processing will stop. | |
199 | * | |
200 | * @param array $data data from form. | |
201 | */ | |
6a2640d2 | 202 | public function user_config_validation(array $data) {} |
87fcac8d | 203 | |
204 | /** | |
93dd2725 RW |
205 | * Sets the export time config from the moodle form. |
206 | * You can also use this to set export config that | |
207 | * isn't actually controlled by the user. | |
208 | * Eg: things that your subclasses want to keep in state | |
209 | * across the export. | |
18cdcdbf | 210 | * Keys must be in get_allowed_export_config |
93dd2725 | 211 | * This is deliberately not final (see boxnet plugin) |
18cdcdbf | 212 | * @see get_allowed_export_config |
93dd2725 RW |
213 | * |
214 | * @param array $config named array of config items to set. | |
215 | */ | |
87fcac8d | 216 | public function set_export_config($config) { |
217 | $allowed = array_merge( | |
218 | array('wait', 'hidewait', 'format', 'hideformat'), | |
219 | $this->get_allowed_export_config() | |
220 | ); | |
221 | foreach ($config as $key => $value) { | |
222 | if (!in_array($key, $allowed)) { | |
223 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
a55d94d4 | 224 | throw new portfolio_export_exception($this->get('exporter'), 'invalidexportproperty', 'portfolio', null, $a); |
87fcac8d | 225 | } |
226 | $this->exportconfig[$key] = $value; | |
227 | } | |
228 | } | |
229 | ||
230 | /** | |
93dd2725 RW |
231 | * Gets an export time config value. |
232 | * Subclasses should not override this. | |
233 | * | |
234 | * @param string $key field to fetch | |
235 | * @return null|string config value | |
236 | */ | |
87fcac8d | 237 | public final function get_export_config($key) { |
238 | $allowed = array_merge( | |
239 | array('hidewait', 'wait', 'format', 'hideformat'), | |
240 | $this->get_allowed_export_config() | |
241 | ); | |
242 | if (!in_array($key, $allowed)) { | |
243 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
a55d94d4 | 244 | throw new portfolio_export_exception($this->get('exporter'), 'invalidexportproperty', 'portfolio', null, $a); |
87fcac8d | 245 | } |
246 | if (!array_key_exists($key, $this->exportconfig)) { | |
247 | return null; | |
248 | } | |
249 | return $this->exportconfig[$key]; | |
250 | } | |
251 | ||
252 | /** | |
93dd2725 RW |
253 | * After the user submits their config, |
254 | * they're given a confirm screen | |
255 | * summarising what they've chosen. | |
256 | * This function should return a table of nice strings => values | |
257 | * of what they've chosen | |
258 | * to be displayed in a table. | |
259 | * | |
260 | * @return bool | |
261 | */ | |
87fcac8d | 262 | public function get_export_summary() { |
263 | return false; | |
264 | } | |
265 | ||
266 | /** | |
93dd2725 RW |
267 | * Called after the caller has finished having control |
268 | * of its prepare_package function. | |
269 | * This function should read all the files from the portfolio | |
270 | * working file area and zip them and send them or whatever it wants. | |
18cdcdbf SH |
271 | * get_tempfiles to get the list of files. |
272 | * @see get_tempfiles | |
93dd2725 RW |
273 | * |
274 | */ | |
87fcac8d | 275 | public abstract function prepare_package(); |
276 | ||
277 | /** | |
93dd2725 RW |
278 | * This is the function that is responsible for sending |
279 | * the package to the remote system, | |
280 | * or whatever request is necessary to initiate the transfer. | |
281 | * | |
282 | * @return bool success | |
283 | */ | |
87fcac8d | 284 | public abstract function send_package(); |
285 | ||
286 | ||
287 | /** | |
93dd2725 RW |
288 | * Once everything is done and the user |
289 | * has the finish page displayed to them. | |
290 | * The base class takes care of printing them | |
291 | * "return to where you are" or "continue to portfolio" links. | |
292 | * This function allows for exta finish options from the plugin | |
293 | * | |
294 | * @return bool | |
295 | */ | |
87fcac8d | 296 | public function get_extra_finish_options() { |
297 | return false; | |
298 | } | |
299 | ||
300 | /** | |
93dd2725 RW |
301 | * The url for the user to continue to their portfolio |
302 | * during the lifecycle of the request | |
303 | */ | |
5d0dbf13 PL |
304 | public abstract function get_interactive_continue_url(); |
305 | ||
306 | /** | |
93dd2725 RW |
307 | * The url to save in the log as the continue url. |
308 | * This is passed through resolve_static_continue_url() | |
5d0dbf13 | 309 | * at display time to the user. |
93dd2725 RW |
310 | * |
311 | * @return string | |
5d0dbf13 PL |
312 | */ |
313 | public function get_static_continue_url() { | |
314 | return $this->get_interactive_continue_url(); | |
315 | } | |
316 | ||
317 | /** | |
93dd2725 RW |
318 | * Override this function if you need to add something on to the url |
319 | * for post-export continues (eg from the log page). | |
320 | * Mahara does this, for example, to start a jump session. | |
321 | * | |
322 | * @param string $url static continue url | |
323 | * @return string | |
5d0dbf13 PL |
324 | */ |
325 | public function resolve_static_continue_url($url) { | |
326 | return $url; | |
327 | } | |
87fcac8d | 328 | |
329 | /** | |
93dd2725 RW |
330 | * mform to display to the user in their profile |
331 | * if your plugin can't be configured by the user, | |
18cdcdbf | 332 | * @see has_user_config. |
93dd2725 RW |
333 | * Don't bother overriding this function |
334 | * | |
335 | * @param moodleform $mform passed by reference, add elements to it | |
336 | */ | |
87fcac8d | 337 | public function user_config_form(&$mform) {} |
338 | ||
339 | /** | |
93dd2725 RW |
340 | * mform to display to the admin configuring the plugin. |
341 | * If your plugin can't be configured by the admin, | |
18cdcdbf | 342 | * @see has_admin_config |
93dd2725 RW |
343 | * Don't bother overriding this function. |
344 | * This function can be called statically or non statically, | |
345 | * depending on whether it's creating a new instance (statically), | |
346 | * or editing an existing one (non statically) | |
347 | * | |
348 | * @param moodleform $mform passed by reference, add elements to it. | |
349 | */ | |
87fcac8d | 350 | public function admin_config_form(&$mform) {} |
351 | ||
352 | /** | |
93dd2725 RW |
353 | * Just like the moodle form validation function, |
354 | * this is passed in the data array from the form | |
355 | * and if a non empty array is returned, form processing will stop. | |
356 | * | |
357 | * @param array $data data from form. | |
358 | */ | |
87fcac8d | 359 | public function admin_config_validation($data) {} |
93dd2725 | 360 | |
87fcac8d | 361 | /** |
93dd2725 RW |
362 | * mform to display to the user exporting data using this plugin. |
363 | * If your plugin doesn't need user input at this time, | |
18cdcdbf | 364 | * @see has_export_config. |
93dd2725 RW |
365 | * Don't bother overrideing this function |
366 | * | |
367 | * @param moodleform $mform passed by reference, add elements to it. | |
368 | */ | |
87fcac8d | 369 | public function export_config_form(&$mform) {} |
370 | ||
371 | /** | |
93dd2725 RW |
372 | * Override this if your plugin doesn't allow multiple instances |
373 | * | |
374 | * @return bool | |
375 | */ | |
384ba38a | 376 | public static function allows_multiple_instances() { |
87fcac8d | 377 | return true; |
378 | } | |
379 | ||
380 | /** | |
93dd2725 RW |
381 | * If at any point the caller wants to steal control, |
382 | * it can, by returning something that isn't false | |
383 | * in this function | |
384 | * The controller will redirect to whatever url | |
385 | * this function returns. | |
386 | * Afterwards, you can redirect back to portfolio/add.php?postcontrol=1 | |
18cdcdbf | 387 | * and post_control is called before the rest of the processing |
93dd2725 | 388 | * for the stage is done, |
18cdcdbf | 389 | * @see post_control |
93dd2725 RW |
390 | * |
391 | * @param int $stage to steal control *before* (see constants PARAM_STAGE_*} | |
392 | * @return bool | |
393 | */ | |
87fcac8d | 394 | public function steal_control($stage) { |
395 | return false; | |
396 | } | |
397 | ||
398 | /** | |
93dd2725 RW |
399 | * After a plugin has elected to steal control, |
400 | * and control returns to portfolio/add.php|postcontrol=1, | |
401 | * this function is called, and passed the stage that was stolen control from | |
402 | * and the request (get and post but not cookie) parameters. | |
403 | * This is useful for external systems that need to redirect the user back | |
404 | * with some extra data in the url (like auth tokens etc) | |
405 | * for an example implementation, see boxnet portfolio plugin. | |
406 | * | |
407 | * @param int $stage the stage before control was stolen | |
408 | * @param array $params a merge of $_GET and $_POST | |
409 | */ | |
87fcac8d | 410 | public function post_control($stage, $params) { } |
411 | ||
412 | /** | |
93dd2725 RW |
413 | * This function creates a new instance of a plugin |
414 | * saves it in the database, saves the config | |
415 | * and returns it. | |
416 | * You shouldn't need to override it | |
417 | * unless you're doing something really funky | |
418 | * | |
419 | * @param string $plugin portfolio plugin to create | |
420 | * @param string $name name of new instance | |
421 | * @param array $config what the admin config form returned | |
422 | * @return object subclass of portfolio_plugin_base | |
423 | */ | |
87fcac8d | 424 | public static function create_instance($plugin, $name, $config) { |
425 | global $DB, $CFG; | |
426 | $new = (object)array( | |
427 | 'plugin' => $plugin, | |
428 | 'name' => $name, | |
429 | ); | |
384ba38a | 430 | if (!portfolio_static_function($plugin, 'allows_multiple_instances')) { |
87fcac8d | 431 | // check we don't have one already |
432 | if ($DB->record_exists('portfolio_instance', array('plugin' => $plugin))) { | |
384ba38a | 433 | throw new portfolio_exception('multipleinstancesdisallowed', 'portfolio', '', $plugin); |
87fcac8d | 434 | } |
435 | } | |
436 | $newid = $DB->insert_record('portfolio_instance', $new); | |
edf1fc35 | 437 | require_once($CFG->dirroot . '/portfolio/' . $plugin . '/lib.php'); |
87fcac8d | 438 | $classname = 'portfolio_plugin_' . $plugin; |
439 | $obj = new $classname($newid); | |
440 | $obj->set_config($config); | |
6010eda2 | 441 | $obj->save(); |
87fcac8d | 442 | return $obj; |
443 | } | |
444 | ||
445 | /** | |
93dd2725 RW |
446 | * Construct a plugin instance. |
447 | * Subclasses should not need to override this unless they're doing something special | |
448 | * and should call parent::__construct afterwards. | |
449 | * | |
450 | * @param int $instanceid id of plugin instance to construct | |
451 | * @param mixed $record stdclass object or named array - use this if you already have the record to avoid another query | |
452 | * @return portfolio_plugin_base | |
453 | */ | |
87fcac8d | 454 | public function __construct($instanceid, $record=null) { |
455 | global $DB; | |
456 | if (!$record) { | |
457 | if (!$record = $DB->get_record('portfolio_instance', array('id' => $instanceid))) { | |
458 | throw new portfolio_exception('invalidinstance', 'portfolio'); | |
459 | } | |
460 | } | |
461 | foreach ((array)$record as $key =>$value) { | |
462 | if (property_exists($this, $key)) { | |
463 | $this->{$key} = $value; | |
464 | } | |
465 | } | |
466 | $this->config = new StdClass; | |
467 | $this->userconfig = array(); | |
468 | $this->exportconfig = array(); | |
469 | foreach ($DB->get_records('portfolio_instance_config', array('instance' => $instanceid)) as $config) { | |
470 | $this->config->{$config->name} = $config->value; | |
471 | } | |
287efec6 | 472 | $this->init(); |
87fcac8d | 473 | return $this; |
474 | } | |
475 | ||
287efec6 | 476 | /** |
93dd2725 | 477 | * Called after __construct - allows plugins to perform initialisation tasks |
287efec6 PL |
478 | * without having to override the constructor. |
479 | */ | |
480 | protected function init() { } | |
481 | ||
87fcac8d | 482 | /** |
93dd2725 RW |
483 | * A list of fields that can be configured per instance. |
484 | * This is used for the save handlers of the config form | |
485 | * and as checks in set_config and get_config. | |
486 | * | |
487 | * @return array array of strings (config item names) | |
488 | */ | |
87fcac8d | 489 | public static function get_allowed_config() { |
490 | return array(); | |
491 | } | |
492 | ||
493 | /** | |
93dd2725 RW |
494 | * A list of fields that can be configured by the user. |
495 | * This is used for the save handlers in the config form | |
496 | * and as checks in set_user_config and get_user_config. | |
497 | * | |
498 | * @return array array of strings (config field names) | |
499 | */ | |
87fcac8d | 500 | public function get_allowed_user_config() { |
501 | return array(); | |
502 | } | |
503 | ||
504 | /** | |
93dd2725 RW |
505 | * A list of fields that can be configured by the user. |
506 | * This is used for the save handlers in the config form | |
507 | * and as checks in set_export_config and get_export_config. | |
508 | * | |
509 | * @return array array of strings (config field names) | |
510 | */ | |
87fcac8d | 511 | public function get_allowed_export_config() { |
512 | return array(); | |
513 | } | |
514 | ||
515 | /** | |
93dd2725 RW |
516 | * Saves (or updates) the config stored in portfolio_instance_config. |
517 | * You shouldn't need to override this unless you're doing something funky. | |
518 | * | |
519 | * @param array $config array of config items. | |
520 | */ | |
87fcac8d | 521 | public final function set_config($config) { |
522 | global $DB; | |
523 | foreach ($config as $key => $value) { | |
524 | // try set it in $this first | |
525 | try { | |
526 | $this->set($key, $value); | |
527 | continue; | |
528 | } catch (portfolio_exception $e) { } | |
529 | if (!in_array($key, $this->get_allowed_config())) { | |
530 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
531 | throw new portfolio_export_exception($this->get('exporter'), 'invalidconfigproperty', 'portfolio', null, $a); | |
532 | } | |
533 | if (!isset($this->config->{$key})) { | |
534 | $DB->insert_record('portfolio_instance_config', (object)array( | |
535 | 'instance' => $this->id, | |
536 | 'name' => $key, | |
537 | 'value' => $value, | |
538 | )); | |
539 | } else if ($this->config->{$key} != $value) { | |
540 | $DB->set_field('portfolio_instance_config', 'value', $value, array('name' => $key, 'instance' => $this->id)); | |
541 | } | |
542 | $this->config->{$key} = $value; | |
543 | } | |
544 | } | |
545 | ||
546 | /** | |
93dd2725 RW |
547 | * Gets the value of a particular config item |
548 | * | |
549 | * @param string $key key to fetch | |
550 | * @return null|mixed the corresponding value | |
551 | */ | |
87fcac8d | 552 | public final function get_config($key) { |
553 | if (!in_array($key, $this->get_allowed_config())) { | |
554 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
555 | throw new portfolio_export_exception($this->get('exporter'), 'invalidconfigproperty', 'portfolio', null, $a); | |
556 | } | |
557 | if (isset($this->config->{$key})) { | |
558 | return $this->config->{$key}; | |
559 | } | |
560 | return null; | |
561 | } | |
562 | ||
563 | /** | |
93dd2725 RW |
564 | * Get the value of a config item for a particular user. |
565 | * | |
566 | * @param string $key key to fetch | |
567 | * @param int $userid id of user (defaults to current) | |
568 | * @return string the corresponding value | |
569 | * | |
570 | */ | |
87fcac8d | 571 | public final function get_user_config($key, $userid=0) { |
572 | global $DB; | |
573 | ||
574 | if (empty($userid)) { | |
575 | $userid = $this->user->id; | |
576 | } | |
577 | ||
578 | if ($key != 'visible') { // handled by the parent class | |
579 | if (!in_array($key, $this->get_allowed_user_config())) { | |
580 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
581 | throw new portfolio_export_exception($this->get('exporter'), 'invaliduserproperty', 'portfolio', null, $a); | |
582 | } | |
583 | } | |
584 | if (!array_key_exists($userid, $this->userconfig)) { | |
585 | $this->userconfig[$userid] = (object)array_fill_keys(array_merge(array('visible'), $this->get_allowed_user_config()), null); | |
586 | foreach ($DB->get_records('portfolio_instance_user', array('instance' => $this->id, 'userid' => $userid)) as $config) { | |
587 | $this->userconfig[$userid]->{$config->name} = $config->value; | |
588 | } | |
589 | } | |
590 | if ($this->userconfig[$userid]->visible === null) { | |
591 | $this->set_user_config(array('visible' => 1), $userid); | |
592 | } | |
593 | return $this->userconfig[$userid]->{$key}; | |
594 | ||
595 | } | |
596 | ||
597 | /** | |
93dd2725 RW |
598 | * Sets config options for a given user. |
599 | * | |
600 | * @param array $config array containing key/value pairs to set | |
601 | * @param int $userid userid to set config for (defaults to current) | |
602 | * | |
603 | */ | |
87fcac8d | 604 | public final function set_user_config($config, $userid=0) { |
605 | global $DB; | |
606 | ||
607 | if (empty($userid)) { | |
608 | $userid = $this->user->id; | |
609 | } | |
610 | ||
611 | foreach ($config as $key => $value) { | |
612 | if ($key != 'visible' && !in_array($key, $this->get_allowed_user_config())) { | |
613 | $a = (object)array('property' => $key, 'class' => get_class($this)); | |
614 | throw new portfolio_export_exception($this->get('exporter'), 'invaliduserproperty', 'portfolio', null, $a); | |
615 | } | |
616 | if (!$existing = $DB->get_record('portfolio_instance_user', array('instance'=> $this->id, 'userid' => $userid, 'name' => $key))) { | |
617 | $DB->insert_record('portfolio_instance_user', (object)array( | |
618 | 'instance' => $this->id, | |
619 | 'name' => $key, | |
620 | 'value' => $value, | |
621 | 'userid' => $userid, | |
622 | )); | |
623 | } else if ($existing->value != $value) { | |
624 | $DB->set_field('portfolio_instance_user', 'value', $value, array('name' => $key, 'instance' => $this->id, 'userid' => $userid)); | |
625 | } | |
626 | $this->userconfig[$userid]->{$key} = $value; | |
627 | } | |
628 | ||
629 | } | |
630 | ||
631 | /** | |
93dd2725 RW |
632 | * Generic getter for properties belonging to this instance |
633 | * <b>outside</b> the subclasses | |
634 | * like name, visible etc. | |
635 | * | |
636 | * @param string $field property name | |
637 | * @return array|string|int|boolean value of the field | |
638 | */ | |
87fcac8d | 639 | public final function get($field) { |
640 | if (property_exists($this, $field)) { | |
641 | return $this->{$field}; | |
642 | } | |
643 | $a = (object)array('property' => $field, 'class' => get_class($this)); | |
644 | throw new portfolio_export_exception($this->get('exporter'), 'invalidproperty', 'portfolio', null, $a); | |
645 | } | |
646 | ||
647 | /** | |
93dd2725 RW |
648 | * Generic setter for properties belonging to this instance |
649 | * <b>outside</b> the subclass | |
650 | * like name, visible, etc. | |
651 | * | |
652 | * @param string $field property's name | |
653 | * @param string $value property's value | |
654 | * @return bool | |
655 | */ | |
87fcac8d | 656 | public final function set($field, $value) { |
657 | if (property_exists($this, $field)) { | |
658 | $this->{$field} =& $value; | |
659 | $this->dirty = true; | |
660 | return true; | |
661 | } | |
662 | $a = (object)array('property' => $field, 'class' => get_class($this)); | |
a200c487 | 663 | if ($this->get('exporter')) { |
664 | throw new portfolio_export_exception($this->get('exporter'), 'invalidproperty', 'portfolio', null, $a); | |
665 | } | |
666 | throw new portfolio_exception('invalidproperty', 'portfolio', null, $a); // this happens outside export (eg admin settings) | |
87fcac8d | 667 | |
668 | } | |
669 | ||
670 | /** | |
93dd2725 RW |
671 | * Saves stuff that's been stored in the object to the database. |
672 | * You shouldn't need to override this | |
673 | * unless you're doing something really funky. | |
674 | * and if so, call parent::save when you're done. | |
675 | * | |
676 | * @return bool | |
677 | */ | |
87fcac8d | 678 | public function save() { |
679 | global $DB; | |
680 | if (!$this->dirty) { | |
681 | return true; | |
682 | } | |
683 | $fordb = new StdClass(); | |
684 | foreach (array('id', 'name', 'plugin', 'visible') as $field) { | |
685 | $fordb->{$field} = $this->{$field}; | |
686 | } | |
687 | $DB->update_record('portfolio_instance', $fordb); | |
688 | $this->dirty = false; | |
689 | return true; | |
690 | } | |
691 | ||
692 | /** | |
93dd2725 RW |
693 | * Deletes everything from the database about this plugin instance. |
694 | * You shouldn't need to override this unless you're storing stuff | |
695 | * in your own tables. and if so, call parent::delete when you're done. | |
696 | * | |
697 | * @return bool | |
698 | */ | |
87fcac8d | 699 | public function delete() { |
700 | global $DB; | |
701 | $DB->delete_records('portfolio_instance_config', array('instance' => $this->get('id'))); | |
702 | $DB->delete_records('portfolio_instance_user', array('instance' => $this->get('id'))); | |
e1b9ac3e | 703 | $DB->delete_records('portfolio_tempdata', array('instance' => $this->get('id'))); |
87fcac8d | 704 | $DB->delete_records('portfolio_instance', array('id' => $this->get('id'))); |
705 | $this->dirty = false; | |
706 | return true; | |
707 | } | |
708 | ||
709 | /** | |
93dd2725 RW |
710 | * Perform any required cleanup functions |
711 | * | |
712 | * @return bool | |
713 | */ | |
87fcac8d | 714 | public function cleanup() { |
715 | return true; | |
716 | } | |
717 | ||
c95a6095 | 718 | /** |
93dd2725 | 719 | * Whether this plugin supports multiple exports in the same session |
c95a6095 PL |
720 | * most plugins should handle this, but some that require a redirect for authentication |
721 | * and then don't support dynamically constructed urls to return to (eg box.net) | |
722 | * need to override this to return false. | |
93dd2725 | 723 | * This means that moodle will prevent multiple exports of this *type* of plugin |
c95a6095 PL |
724 | * occurring in the same session. |
725 | * | |
93dd2725 | 726 | * @return bool |
c95a6095 PL |
727 | */ |
728 | public static function allows_multiple_exports() { | |
729 | return true; | |
730 | } | |
11fbe3fc PL |
731 | |
732 | /** | |
93dd2725 RW |
733 | * Return a string to put at the header summarising this export |
734 | * by default, just the plugin instance name | |
735 | * | |
736 | * @return string | |
737 | */ | |
11fbe3fc PL |
738 | public function heading_summary() { |
739 | return get_string('exportingcontentto', 'portfolio', $this->name); | |
740 | } | |
87fcac8d | 741 | } |
742 | ||
743 | /** | |
93dd2725 | 744 | * Class to inherit from for 'push' type plugins |
18cdcdbf | 745 | * |
93dd2725 RW |
746 | * Eg: those that send the file via a HTTP post or whatever |
747 | * | |
748 | * @package core_portfolio | |
749 | * @category portfolio | |
750 | * @copyright 2008 Penny Leach <penny@catalyst.net.nz> | |
751 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
752 | */ | |
87fcac8d | 753 | abstract class portfolio_plugin_push_base extends portfolio_plugin_base { |
754 | ||
93dd2725 RW |
755 | /** |
756 | * Get the capability to push | |
757 | * | |
758 | * @return bool | |
759 | */ | |
87fcac8d | 760 | public function is_push() { |
761 | return true; | |
762 | } | |
763 | } | |
764 | ||
765 | /** | |
93dd2725 | 766 | * Class to inherit from for 'pull' type plugins. |
18cdcdbf | 767 | * |
93dd2725 RW |
768 | * Eg: those that write a file and wait for the remote system to request it |
769 | * from portfolio/file.php. | |
770 | * If you're using this you must do $this->set('file', $file) so that it can be served. | |
771 | * | |
772 | * @package core_portfolio | |
773 | * @category portfolio | |
774 | * @copyright 2008 Penny Leach <penny@catalyst.net.nz> | |
775 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
776 | */ | |
87fcac8d | 777 | abstract class portfolio_plugin_pull_base extends portfolio_plugin_base { |
778 | ||
93dd2725 | 779 | /** @var stdclass single file */ |
87fcac8d | 780 | protected $file; |
781 | ||
93dd2725 RW |
782 | /** |
783 | * return the enablelity to push | |
784 | * | |
785 | * @return bool | |
786 | */ | |
87fcac8d | 787 | public function is_push() { |
788 | return false; | |
789 | } | |
790 | ||
d5d9b239 | 791 | /** |
93dd2725 RW |
792 | * The base part of the download file url to pull files from |
793 | * your plugin might need to add &foo=bar on the end | |
18cdcdbf | 794 | * @see verify_file_request_params |
93dd2725 RW |
795 | * |
796 | * @return string the url | |
797 | */ | |
d5d9b239 | 798 | public function get_base_file_url() { |
799 | global $CFG; | |
800 | return $CFG->wwwroot . '/portfolio/file.php?id=' . $this->exporter->get('id'); | |
801 | } | |
87fcac8d | 802 | |
803 | /** | |
93dd2725 RW |
804 | * Before sending the file when the pull is requested, verify the request parameters. |
805 | * These might include a token of some sort of whatever | |
806 | * | |
807 | * @param array $params request parameters (POST wins over GET) | |
808 | */ | |
87fcac8d | 809 | public abstract function verify_file_request_params($params); |
810 | ||
811 | /** | |
93dd2725 RW |
812 | * Called from portfolio/file.php. |
813 | * This function sends the stored file out to the browser. | |
814 | * The default is to just use send_stored_file, | |
815 | * but other implementations might do something different, | |
816 | * for example, send back the file base64 encoded and encrypted | |
817 | * mahara does this but in the response to an xmlrpc request | |
818 | * rather than through file.php | |
819 | */ | |
87fcac8d | 820 | public function send_file() { |
821 | $file = $this->get('file'); | |
822 | if (!($file instanceof stored_file)) { | |
823 | throw new portfolio_export_exception($this->get('exporter'), 'filenotfound', 'portfolio'); | |
824 | } | |
796495fe DM |
825 | // don't die(); afterwards, so we can clean up. |
826 | send_stored_file($file, 0, 0, true, array('dontdie' => true)); | |
de01a507 | 827 | $this->get('exporter')->log_transfer(); |
87fcac8d | 828 | } |
829 | ||
830 | } |