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