diff --git a/lang/en/portfolio.php b/lang/en/portfolio.php index 8bdb88e324fa4..d0bf89a67559a 100644 --- a/lang/en/portfolio.php +++ b/lang/en/portfolio.php @@ -145,7 +145,8 @@ $string['mustsetcallbackoptions'] = 'You must set the callback options either in the portfolio_add_button constructor or using the set_callback_options method'; $string['noavailableplugins'] = 'Sorry, but there are no available portfolios for you to export to'; $string['nocallbackclass'] = 'Could not find the callback class to use ({$a})'; -$string['nocallbackfile'] = 'Something in the module you\'re trying to export from is broken - couldn\'t find a required file ({$a})'; +$string['nocallbackcomponent'] = 'Could not find the component specified {$a}.'; +$string['nocallbackfile'] = 'Something in the module you\'re trying to export from is broken - couldn\'t find a required portfolio file'; $string['noclassbeforeformats'] = 'You must set the callback class before calling set_formats in portfolio_button'; $string['nocommonformats'] = 'No common formats between any available portfolio plugin and the calling location {$a->location} (caller supported {$a->formats})'; $string['noinstanceyet'] = 'Not yet selected'; diff --git a/lib/db/install.xml b/lib/db/install.xml old mode 100644 new mode 100755 index 96dc090f9db6e..aee878fddbc64 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -2303,8 +2303,9 @@ - - + + + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 8ade318b874f0..6e904b221755d 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1399,5 +1399,20 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012110201.00); } + if ($oldversion < 2012110700.01) { + + // Define field caller_component to be added to portfolio_log. + $table = new xmldb_table('portfolio_log'); + $field = new xmldb_field('caller_component', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'caller_file'); + + // Conditionally launch add field caller_component. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2012110700.01); + } + return true; } diff --git a/lib/portfolio/exporter.php b/lib/portfolio/exporter.php index 79bfc8f6b4f62..3225ddf6af307 100644 --- a/lib/portfolio/exporter.php +++ b/lib/portfolio/exporter.php @@ -66,10 +66,10 @@ class portfolio_exporter { public $instancefile; /** - * @var string the file to include that contains the class definition of + * @var string the component that contains the class definition of * the caller object used to re-waken the object after sleep */ - public $callerfile; + public $callercomponent; /** @var int the current stage of the export */ private $stage; @@ -115,16 +115,16 @@ class portfolio_exporter { * * @param portfolio_plugin_base $instance portfolio instance (passed by reference) * @param portfolio_caller_base $caller portfolio caller (passed by reference) - * @param string $callerfile path to callerfile (relative to dataroot) + * @param string $callercomponent the name of the callercomponent */ - public function __construct(&$instance, &$caller, $callerfile) { + public function __construct(&$instance, &$caller, $callercomponent) { $this->instance =& $instance; $this->caller =& $caller; if ($instance) { $this->instancefile = 'portfolio/' . $instance->get('plugin') . '/lib.php'; $this->instance->set('exporter', $this); } - $this->callerfile = $callerfile; + $this->callercomponent = $callercomponent; $this->stage = PORTFOLIO_STAGE_CONFIG; $this->caller->set('exporter', $this); $this->alreadystolen = array(); @@ -395,7 +395,13 @@ public function process_stage_confirm() { foreach ($previous as $row) { $previousstr .= userdate($row->time); if ($row->caller_class != get_class($this->caller)) { - require_once($CFG->dirroot . '/' . $row->caller_file); + if (!empty($row->caller_file)) { + portfolio_include_callback_file($row->caller_file); + } else if (!empty($row->caller_component)) { + portfolio_include_callback_file($row->caller_component); + } else { // Ok, that's weird - this should never happen. Is the apocalypse coming? + continue; + } $previousstr .= ' (' . call_user_func(array($row->caller_class, 'display_name')) . ')'; } $previousstr .= '
'; @@ -522,15 +528,16 @@ public function process_stage_send() { public function log_transfer() { global $DB; $l = array( - 'userid' => $this->user->id, - 'portfolio' => $this->instance->get('id'), - 'caller_file' => $this->callerfile, - 'caller_sha1' => $this->caller->get_sha1(), - 'caller_class' => get_class($this->caller), - 'continueurl' => $this->instance->get_static_continue_url(), - 'returnurl' => $this->caller->get_return_url(), - 'tempdataid' => $this->id, - 'time' => time(), + 'userid' => $this->user->id, + 'portfolio' => $this->instance->get('id'), + 'caller_file'=> '', + 'caller_component' => $this->callercomponent, + 'caller_sha1' => $this->caller->get_sha1(), + 'caller_class' => get_class($this->caller), + 'continueurl' => $this->instance->get_static_continue_url(), + 'returnurl' => $this->caller->get_return_url(), + 'tempdataid' => $this->id, + 'time' => time(), ); $DB->insert_record('portfolio_log', $l); } @@ -681,7 +688,14 @@ public static function rewaken_object($id) { if ($exporter->instancefile) { require_once($CFG->dirroot . '/' . $exporter->instancefile); } - require_once($CFG->dirroot . '/' . $exporter->callerfile); + if (!empty($exporter->callerfile)) { + portfolio_include_callback_file($exporter->callerfile); + } else if (!empty($exporter->callercomponent)) { + portfolio_include_callback_file($exporter->callercomponent); + } else { + return; // Should never get here! + } + $exporter = unserialize(serialize($exporter)); if (!$exporter->get('id')) { // workaround for weird case diff --git a/lib/portfoliolib.php b/lib/portfoliolib.php index 04a2223aaf21e..37d91dc0fd158 100644 --- a/lib/portfoliolib.php +++ b/lib/portfoliolib.php @@ -60,12 +60,12 @@ * This class can be used like this: * * $button = new portfolio_add_button(); - * $button->set_callback_options('name_of_caller_class', array('id' => 6), '/your/mod/lib.php'); - * $button->render(PORTFOLIO_ADD_FULL_FORM, get_string('addeverythingtoportfolio', 'yourmodule')); + * $button->set_callback_options('name_of_caller_class', array('id' => 6), 'yourcomponent'); eg. mod_forum + * $button->render(PORTFOLIO_ADD_FULL_FORM, get_string('addeverythingtoportfolio', 'yourcomponent')); * * or like this: * - * $button = new portfolio_add_button(array('callbackclass' => 'name_of_caller_class', 'callbackargs' => array('id' => 6), 'callbackfile' => '/your/mod/lib.php')); + * $button = new portfolio_add_button(array('callbackclass' => 'name_of_caller_class', 'callbackargs' => array('id' => 6), 'callbackcomponent' => 'yourcomponent')); eg. mod_forum * $somehtml .= $button->to_html(PORTFOLIO_ADD_TEXT_LINK); * *{@link http://docs.moodle.org/dev/Adding_a_Portfolio_Button_to_a_page} for more information @@ -84,7 +84,7 @@ class portfolio_add_button { private $callbackargs; /** @var string caller file */ - private $callbackfile; + private $callbackcomponent; /** @var array array of more specific formats (eg based on mime detection) */ private $formats; @@ -105,7 +105,7 @@ class portfolio_add_button { * @param array $options keyed array of options: * key 'callbackclass': name of the caller class (eg forum_portfolio_caller') * key 'callbackargs': the array of callback arguments your caller class wants passed to it in the constructor - * key 'callbackfile': the file containing the class definition of your caller class. + * key 'callbackcomponent': the file containing the class definition of your caller class. * See set_callback_options for more information on these three. * key 'formats': an array of PORTFOLIO_FORMATS this caller will support * See set_formats or set_format_by_file for more information on this. @@ -121,54 +121,42 @@ public function __construct($options=null) { if (empty($options)) { return true; } - $constructoroptions = array('callbackclass', 'callbackargs', 'callbackfile', 'formats'); + $constructoroptions = array('callbackclass', 'callbackargs', 'callbackcomponent'); foreach ((array)$options as $key => $value) { if (!in_array($key, $constructoroptions)) { throw new portfolio_button_exception('invalidbuttonproperty', 'portfolio', $key); } - $this->{$key} = $value; } + + $this->set_callback_options($options['callbackclass'], $options['callbackargs'], $options['callbackcomponent']); } /** * Function to set the callback options * - * @param string $class Name of the class containing the callback functions - * activity modules should ALWAYS use their name_portfolio_caller - * other locations must use something unique + * @param string $class Name of the class containing the callback functions + * activity components should ALWAYS use their name_portfolio_caller + * other locations must use something unique * @param array $argarray This can be an array or hash of arguments to pass - * back to the callback functions (passed by reference) - * these MUST be primatives to be added as hidden form fields. - * and the values get cleaned to PARAM_ALPHAEXT or PARAM_FLOAT or PARAM_PATH - * @param string $file This can be autodetected if it's in the same file as your caller, - * but often, the caller is a script.php and the class in a lib.php - * so you can pass it here if necessary. - * This path should be relative (ie, not include) dirroot, eg '/mod/forum/lib.php' + * back to the callback functions (passed by reference) + * these MUST be primatives to be added as hidden form fields. + * and the values get cleaned to PARAM_ALPHAEXT or PARAM_FLOAT or PARAM_PATH + * @param string $component This is the name of the component in Moodle, eg 'mod_forum' */ - public function set_callback_options($class, array $argarray, $file=null) { + public function set_callback_options($class, array $argarray, $component) { global $CFG; - if (empty($file)) { - $backtrace = debug_backtrace(); - if (!array_key_exists(0, $backtrace) || !array_key_exists('file', $backtrace[0]) || !is_readable($backtrace[0]['file'])) { - throw new portfolio_button_exception('nocallbackfile', 'portfolio'); - } - $file = substr($backtrace[0]['file'], strlen($CFG->dirroot)); - } else if (!is_readable($CFG->dirroot . $file)) { - throw new portfolio_button_exception('nocallbackfile', 'portfolio', '', $file); - } - $this->callbackfile = $file; - require_once($CFG->libdir . '/portfolio/caller.php'); // require the base class first - require_once($CFG->dirroot . $file); - if (!class_exists($class)) { - throw new portfolio_button_exception('nocallbackclass', 'portfolio', '', $class); - } + // Require the base class first before any other files. + require_once($CFG->libdir . '/portfolio/caller.php'); - // this will throw exceptions - // but should not actually do anything other than verify callbackargs + // Include any potential callback files and check for errors. + portfolio_include_callback_file($component, $class); + + // This will throw exceptions but should not actually do anything other than verify callbackargs. $test = new $class($argarray); unset($test); + $this->callbackcomponent = $component; $this->callbackclass = $class; $this->callbackargs = $argarray; } @@ -278,7 +266,7 @@ public function to_html($format=null, $addstr=null) { if (!$this->is_renderable()) { return; } - if (empty($this->callbackclass) || empty($this->callbackfile)) { + if (empty($this->callbackclass) || empty($this->callbackcomponent)) { throw new portfolio_button_exception('mustsetcallbackoptions', 'portfolio'); } if (empty($this->formats)) { @@ -297,7 +285,7 @@ public function to_html($format=null, $addstr=null) { $url->param('ca_' . $key, $value); } $url->param('sesskey', sesskey()); - $url->param('callbackfile', $this->callbackfile); + $url->param('callbackcomponent', $this->callbackcomponent); $url->param('callbackclass', $this->callbackclass); $url->param('course', (!empty($COURSE)) ? $COURSE->id : 0); $url->param('callerformats', implode(',', $this->formats)); @@ -421,12 +409,12 @@ public function get_callbackargs() { } /** - * Getter for $callbackfile property + * Getter for $callbackcomponent property * * @return string */ - public function get_callbackfile() { - return $this->callbackfile; + public function get_callbackcomponent() { + return $this->callbackcomponent; } /** @@ -1271,6 +1259,89 @@ function portfolio_rewrite_pluginfile_url_callback($contextid, $component, $file return $format->file_output($file, $options); } +/** + * Function to require any potential callback files, throwing exceptions + * if an issue occurs. + * + * @param string $component This is the name of the component in Moodle, eg 'mod_forum' + * @param string $class Name of the class containing the callback functions + * activity components should ALWAYS use their name_portfolio_caller + * other locations must use something unique + */ +function portfolio_include_callback_file($component, $class = null) { + global $CFG; + require_once($CFG->libdir . '/adminlib.php'); + + // It's possible that they are passing a file path rather than passing a component. + // We want to try and convert this to a component name, eg. mod_forum. + $pos = strrpos($component, '/'); + if ($pos !== false) { + // Get rid of the first slash (if it exists). + $component = ltrim($component, '/'); + // Get a list of valid plugin types. + $plugintypes = get_plugin_types(false); + // Assume it is not valid for now. + $isvalid = false; + // Go through the plugin types. + foreach ($plugintypes as $type => $path) { + if (strrpos($component, $path) === 0) { + // Found the plugin type. + $isvalid = true; + $plugintype = $type; + $pluginpath = $path; + } + } + // Throw exception if not a valid component. + if (!$isvalid) { + throw new coding_exception('Somehow a non-valid plugin path was passed, could be a hackz0r attempt, exiting.'); + } + // Remove the file name. + $component = trim(substr($component, 0, $pos), '/'); + // Replace the path with the type. + $component = str_replace($pluginpath, $plugintype, $component); + // Ok, replace '/' with '_'. + $component = str_replace('/', '_', $component); + // Place a debug message saying the third parameter should be changed. + debugging('The third parameter sent to the function set_callback_options should be the component name, not a file path, please update this.', DEBUG_DEVELOPER); + } + + // Check that it is a valid component. + if (!get_component_version($component)) { + throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component); + } + + // Obtain the component's location. + if (!$componentloc = get_component_directory($component)) { + throw new portfolio_button_exception('nocallbackcomponent', 'portfolio', '', $component); + } + + // Check if the component contains the necessary file for the portfolio plugin. + // These are locallib.php, portfoliolib.php and portfolio_callback.php. + $filefound = false; + if (file_exists($componentloc . '/locallib.php')) { + $filefound = true; + require_once($componentloc . '/locallib.php'); + } + if (file_exists($componentloc . '/portfoliolib.php')) { + $filefound = true; + debugging('Please standardise your plugin by renaming your portfolio callback file to locallib.php, or if that file already exists moving the portfolio functionality there.', DEBUG_DEVELOPER); + require_once($componentloc . '/portfoliolib.php'); + } + if (file_exists($componentloc . '/portfolio_callback.php')) { + $filefound = true; + debugging('Please standardise your plugin by renaming your portfolio callback file to locallib.php, or if that file already exists moving the portfolio functionality there.', DEBUG_DEVELOPER); + require_once($componentloc . '/portfolio_callback.php'); + } + + // Ensure that we found a file we can use, if not throw an exception. + if (!$filefound) { + throw new portfolio_button_exception('nocallbackfile', 'portfolio', '', $component); + } + + if (!is_null($class) && !class_exists($class)) { + throw new portfolio_button_exception('nocallbackclass', 'portfolio', '', $class); + } +} /** * Go through all the @@PLUGINFILE@@ matches in some text, diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index a4ab9396c5131..ddc9d0135433a 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -61,7 +61,8 @@ require_once($CFG->dirroot.'/mod/assign/gradingtable.php'); /** Include eventslib.php */ require_once($CFG->libdir.'/eventslib.php'); - +/** Include portfolio caller.php */ +require_once($CFG->libdir . '/portfolio/caller.php'); /** * Standard base class for mod_assign (assignment types). @@ -1759,7 +1760,9 @@ public function render_editor_content($filearea, $submissionid, $plugintype, $ed require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('assign_portfolio_caller', array('cmid' => $this->get_course_module()->id, 'sid' => $submissionid, 'plugin' => $plugintype, 'editor' => $editor, 'area'=>$filearea), '/mod/assign/portfolio_callback.php'); + $button->set_callback_options('assign_portfolio_caller', array('cmid' => $this->get_course_module()->id, + 'sid' => $submissionid, 'plugin' => $plugintype, 'editor' => $editor, 'area'=>$filearea), + 'mod_assign'); $fs = get_file_storage(); if ($files = $fs->get_area_files($this->context->id, $component,$filearea, $submissionid, "timemodified", false)) { @@ -4545,3 +4548,250 @@ public static function get_user_id_for_uniqueid_static($assignid, $uniqueid) { } +/** + * portfolio caller class for mod_assign. + * + * @package mod_assign + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class assign_portfolio_caller extends portfolio_module_caller_base { + + /** @var int callback arg - the id of submission we export */ + protected $sid; + + /** @var string component of the submission files we export*/ + protected $component; + + /** @var string callback arg - the area of submission files we export */ + protected $area; + + /** @var int callback arg - the id of file we export */ + protected $fileid; + + /** @var int callback arg - the cmid of the assignment we export */ + protected $cmid; + + /** @var string callback arg - the plugintype of the editor we export */ + protected $plugin; + + /** @var string callback arg - the name of the editor field we export */ + protected $editor; + + /** + * callback arg for a single file export + */ + public static function expected_callbackargs() { + return array( + 'cmid' => true, + 'sid' => false, + 'area' => false, + 'component' => false, + 'fileid' => false, + 'plugin' => false, + 'editor' => false, + ); + } + + /** + * the constructor + * @param array $callbackargs + */ + function __construct($callbackargs) { + parent::__construct($callbackargs); + $this->cm = get_coursemodule_from_id('assign', $this->cmid, 0, false, MUST_EXIST); + } + + /** + * + * Load data needed for the portfolio export + * + * If the assignment type implements portfolio_load_data(), the processing is delegated + * to it. Otherwise, the caller must provide either fileid (to export single file) or + * submissionid and filearea (to export all data attached to the given submission file area) via callback arguments. + * + * @throws portfolio_caller_exception + */ + public function load_data() { + + $context = context_module::instance($this->cmid); + + if (empty($this->fileid)) { + if (empty($this->sid) || empty($this->area)) { + throw new portfolio_caller_exception('invalidfileandsubmissionid', 'mod_assign'); + } + + } + + // export either an area of files or a single file (see function for more detail) + // the first arg is an id or null. If it is an id, the rest of the args are ignored + // if it is null, the rest of the args are used to load a list of files from get_areafiles + $this->set_file_and_format_data($this->fileid, $context->id, $this->component, $this->area, $this->sid, 'timemodified', false); + + } + + /** + * prepares the package up before control is passed to the portfolio plugin. + * + * @throws portfolio_caller_exception + * @return mixed + */ + public function prepare_package() { + + if ($this->plugin && $this->editor) { + $options = portfolio_format_text_options(); + $context = context_module::instance($this->cmid); + $options->context = $context; + + $plugin = $this->get_submission_plugin(); + + $text = $plugin->get_editor_text($this->editor, $this->sid); + $format = $plugin->get_editor_format($this->editor, $this->sid); + + $html = format_text($text, $format, $options); + $html = portfolio_rewrite_pluginfile_urls($html, $context->id, 'mod_assign', $this->area, $this->sid, $this->exporter->get('format')); + + if (in_array($this->exporter->get('formatclass'), array(PORTFOLIO_FORMAT_PLAINHTML, PORTFOLIO_FORMAT_RICHHTML))) { + if ($files = $this->exporter->get('caller')->get('multifiles')) { + foreach ($files as $file) { + $this->exporter->copy_existing_file($file); + } + } + return $this->exporter->write_new_file($html, 'assignment.html', !empty($files)); + } else if ($this->exporter->get('formatclass') == PORTFOLIO_FORMAT_LEAP2A) { + $leapwriter = $this->exporter->get('format')->leap2a_writer(); + $entry = new portfolio_format_leap2a_entry($this->area . $this->cmid, print_context_name($context), 'resource', $html); + + $entry->add_category('web', 'resource_type'); + $entry->author = $this->user; + $leapwriter->add_entry($entry); + if ($files = $this->exporter->get('caller')->get('multifiles')) { + $leapwriter->link_files($entry, $files, $this->area . $this->cmid . 'file'); + foreach ($files as $file) { + $this->exporter->copy_existing_file($file); + } + } + return $this->exporter->write_new_file($leapwriter->to_xml(), $this->exporter->get('format')->manifest_name(), true); + } else { + debugging('invalid format class: ' . $this->exporter->get('formatclass')); + } + + } + + + if ($this->exporter->get('formatclass') == PORTFOLIO_FORMAT_LEAP2A) { + $leapwriter = $this->exporter->get('format')->leap2a_writer(); + $files = array(); + if ($this->singlefile) { + $files[] = $this->singlefile; + } elseif ($this->multifiles) { + $files = $this->multifiles; + } else { + throw new portfolio_caller_exception('invalidpreparepackagefile', 'portfolio', $this->get_return_url()); + } + + $entryids = array(); + foreach ($files as $file) { + $entry = new portfolio_format_leap2a_file($file->get_filename(), $file); + $entry->author = $this->user; + $leapwriter->add_entry($entry); + $this->exporter->copy_existing_file($file); + $entryids[] = $entry->id; + } + if (count($files) > 1) { + $baseid = 'assign' . $this->cmid . $this->area; + $context = context_module::instance($this->cmid); + + // if we have multiple files, they should be grouped together into a folder + $entry = new portfolio_format_leap2a_entry($baseid . 'group', print_context_name($context), 'selection'); + $leapwriter->add_entry($entry); + $leapwriter->make_selection($entry, $entryids, 'Folder'); + } + return $this->exporter->write_new_file($leapwriter->to_xml(), $this->exporter->get('format')->manifest_name(), true); + } + return $this->prepare_package_file(); + } + + /** + * fetch the plugin by its type + * + * @return assign_submission_plugin + */ + private function get_submission_plugin() { + global $CFG; + if (!$this->plugin || !$this->cmid) { + return null; + } + + require_once($CFG->dirroot . '/mod/assign/locallib.php'); + + $context = context_module::instance($this->cmid); + + $assignment = new assign($context, null, null); + return $assignment->get_submission_plugin_by_type($this->plugin); + } + + /** + * get sha1 file + * calculate a sha1 has of either a single file or a list + * of files based on the data set by load_data + * + * @return string + */ + public function get_sha1() { + + if ($this->plugin && $this->editor) { + $plugin = $this->get_submission_plugin(); + $options = portfolio_format_text_options(); + $options->context = context_module::instance($this->cmid); + + $textsha1 = sha1(format_text($plugin->get_editor_text($this->editor, $this->sid), + $plugin->get_editor_format($this->editor, $this->sid), $options)); + $filesha1 = ''; + try { + $filesha1 = $this->get_sha1_file(); + } catch (portfolio_caller_exception $e) {} // no files + return sha1($textsha1 . $filesha1); + } + return $this->get_sha1_file(); + } + + /** + * calculate the time to transfer either a single file or a list + * of files based on the data set by load_data + * + * @return int + */ + public function expected_time() { + return $this->expected_time_file(); + } + + /** + * checking the permissions + * + * @return bool + */ + public function check_permissions() { + $context = context_module::instance($this->cmid); + return has_capability('mod/assign:exportownsubmission', $context); + } + + /** + * display a module name + * + * @return string + */ + public static function display_name() { + return get_string('modulename', 'assign'); + } + + /** + * return array of formats supported by this portfolio call back + * @return array + */ + public static function base_supported_formats() { + + return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_LEAP2A); + + } +} \ No newline at end of file diff --git a/mod/assign/portfolio_callback.php b/mod/assign/portfolio_callback.php deleted file mode 100644 index 71e6d820e5d78..0000000000000 --- a/mod/assign/portfolio_callback.php +++ /dev/null @@ -1,283 +0,0 @@ -. -// -// this file contains all the functions that aren't needed by core moodle -// but start becoming required once we're actually inside the assignment module. - -/** - * This file contains the callback class required by the portfolio api. - * - * @package mod_assign - * @copyright 2012 NetSpot {@link http://www.netspot.com.au} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** Include assign locallib.php */ -require_once($CFG->dirroot . '/mod/assign/locallib.php'); -/** Include portfolio caller.php */ -require_once($CFG->libdir . '/portfolio/caller.php'); - -/** - * portfolio caller class for mod_assign. - * - * @package mod_assign - * @copyright 2012 NetSpot {@link http://www.netspot.com.au} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class assign_portfolio_caller extends portfolio_module_caller_base { - - - /** @var int callback arg - the id of submission we export */ - protected $sid; - - /** @var string component of the submission files we export*/ - protected $component; - - /** @var string callback arg - the area of submission files we export */ - protected $area; - - /** @var int callback arg - the id of file we export */ - protected $fileid; - - /** @var int callback arg - the cmid of the assignment we export */ - protected $cmid; - - /** @var string callback arg - the plugintype of the editor we export */ - protected $plugin; - - /** @var string callback arg - the name of the editor field we export */ - protected $editor; - - /** - * callback arg for a single file export - */ - public static function expected_callbackargs() { - return array( - 'cmid' => true, - 'sid' => false, - 'area' => false, - 'component' => false, - 'fileid' => false, - 'plugin' => false, - 'editor' => false, - ); - } - - /** - * the constructor - * @param array $callbackargs - */ - function __construct($callbackargs) { - parent::__construct($callbackargs); - $this->cm = get_coursemodule_from_id('assign', $this->cmid, 0, false, MUST_EXIST); - } - - /** - * - * Load data needed for the portfolio export - * - * If the assignment type implements portfolio_load_data(), the processing is delegated - * to it. Otherwise, the caller must provide either fileid (to export single file) or - * submissionid and filearea (to export all data attached to the given submission file area) via callback arguments. - * - * @throws portfolio_caller_exception - */ - public function load_data() { - - $context = context_module::instance($this->cmid); - - if (empty($this->fileid)) { - if (empty($this->sid) || empty($this->area)) { - throw new portfolio_caller_exception('invalidfileandsubmissionid', 'mod_assign'); - } - - } - - // export either an area of files or a single file (see function for more detail) - // the first arg is an id or null. If it is an id, the rest of the args are ignored - // if it is null, the rest of the args are used to load a list of files from get_areafiles - $this->set_file_and_format_data($this->fileid, $context->id, $this->component, $this->area, $this->sid, 'timemodified', false); - - } - - /** - * prepares the package up before control is passed to the portfolio plugin. - * - * @throws portfolio_caller_exception - * @return mixed - */ - public function prepare_package() { - - if ($this->plugin && $this->editor) { - $options = portfolio_format_text_options(); - $context = context_module::instance($this->cmid); - $options->context = $context; - - $plugin = $this->get_submission_plugin(); - - $text = $plugin->get_editor_text($this->editor, $this->sid); - $format = $plugin->get_editor_format($this->editor, $this->sid); - - $html = format_text($text, $format, $options); - $html = portfolio_rewrite_pluginfile_urls($html, $context->id, 'mod_assign', $this->area, $this->sid, $this->exporter->get('format')); - - if (in_array($this->exporter->get('formatclass'), array(PORTFOLIO_FORMAT_PLAINHTML, PORTFOLIO_FORMAT_RICHHTML))) { - if ($files = $this->exporter->get('caller')->get('multifiles')) { - foreach ($files as $file) { - $this->exporter->copy_existing_file($file); - } - } - return $this->exporter->write_new_file($html, 'assignment.html', !empty($files)); - } else if ($this->exporter->get('formatclass') == PORTFOLIO_FORMAT_LEAP2A) { - $leapwriter = $this->exporter->get('format')->leap2a_writer(); - $entry = new portfolio_format_leap2a_entry($this->area . $this->cmid, print_context_name($context), 'resource', $html); - - $entry->add_category('web', 'resource_type'); - $entry->author = $this->user; - $leapwriter->add_entry($entry); - if ($files = $this->exporter->get('caller')->get('multifiles')) { - $leapwriter->link_files($entry, $files, $this->area . $this->cmid . 'file'); - foreach ($files as $file) { - $this->exporter->copy_existing_file($file); - } - } - return $this->exporter->write_new_file($leapwriter->to_xml(), $this->exporter->get('format')->manifest_name(), true); - } else { - debugging('invalid format class: ' . $this->exporter->get('formatclass')); - } - - } - - - if ($this->exporter->get('formatclass') == PORTFOLIO_FORMAT_LEAP2A) { - $leapwriter = $this->exporter->get('format')->leap2a_writer(); - $files = array(); - if ($this->singlefile) { - $files[] = $this->singlefile; - } elseif ($this->multifiles) { - $files = $this->multifiles; - } else { - throw new portfolio_caller_exception('invalidpreparepackagefile', 'portfolio', $this->get_return_url()); - } - - $entryids = array(); - foreach ($files as $file) { - $entry = new portfolio_format_leap2a_file($file->get_filename(), $file); - $entry->author = $this->user; - $leapwriter->add_entry($entry); - $this->exporter->copy_existing_file($file); - $entryids[] = $entry->id; - } - if (count($files) > 1) { - $baseid = 'assign' . $this->cmid . $this->area; - $context = context_module::instance($this->cmid); - - // if we have multiple files, they should be grouped together into a folder - $entry = new portfolio_format_leap2a_entry($baseid . 'group', print_context_name($context), 'selection'); - $leapwriter->add_entry($entry); - $leapwriter->make_selection($entry, $entryids, 'Folder'); - } - return $this->exporter->write_new_file($leapwriter->to_xml(), $this->exporter->get('format')->manifest_name(), true); - } - return $this->prepare_package_file(); - } - - /** - * fetch the plugin by its type - * - * @return assign_submission_plugin - */ - private function get_submission_plugin() { - global $CFG; - if (!$this->plugin || !$this->cmid) { - return null; - } - - require_once($CFG->dirroot . '/mod/assign/locallib.php'); - - $context = context_module::instance($this->cmid); - - $assignment = new assign($context, null, null); - return $assignment->get_submission_plugin_by_type($this->plugin); - } - - /** - * get sha1 file - * calculate a sha1 has of either a single file or a list - * of files based on the data set by load_data - * - * @return string - */ - public function get_sha1() { - - if ($this->plugin && $this->editor) { - $plugin = $this->get_submission_plugin(); - $options = portfolio_format_text_options(); - $options->context = context_module::instance($this->cmid); - - $textsha1 = sha1(format_text($plugin->get_editor_text($this->editor, $this->sid), - $plugin->get_editor_format($this->editor, $this->sid), $options)); - $filesha1 = ''; - try { - $filesha1 = $this->get_sha1_file(); - } catch (portfolio_caller_exception $e) {} // no files - return sha1($textsha1 . $filesha1); - } - return $this->get_sha1_file(); - } - - /** - * calculate the time to transfer either a single file or a list - * of files based on the data set by load_data - * - * @return int - */ - public function expected_time() { - return $this->expected_time_file(); - } - - /** - * checking the permissions - * - * @return bool - */ - public function check_permissions() { - $context = context_module::instance($this->cmid); - return has_capability('mod/assign:exportownsubmission', $context); - } - - /** - * display a module name - * - * @return string - */ - public static function display_name() { - return get_string('modulename', 'assign'); - } - - /** - * return array of formats supported by this portfolio call back - * @return array - */ - public static function base_supported_formats() { - - return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_LEAP2A); - - } -} - diff --git a/mod/assign/renderable.php b/mod/assign/renderable.php index 90b16bd6b520b..986f1da3e5a6d 100644 --- a/mod/assign/renderable.php +++ b/mod/assign/renderable.php @@ -547,7 +547,12 @@ public function __construct(context $context, $sid, $filearea, $component) { require_once($CFG->libdir . '/portfoliolib.php'); if (count($files) >= 1 && has_capability('mod/assign:exportownsubmission', $this->context)) { $button = new portfolio_add_button(); - $button->set_callback_options('assign_portfolio_caller', array('cmid' => $this->cm->id, 'sid'=>$sid, 'area'=>$filearea, 'component'=>$component), '/mod/assign/portfolio_callback.php'); + $button->set_callback_options('assign_portfolio_caller', + array('cmid' => $this->cm->id, + 'sid' => $sid, + 'area' => $filearea, + 'component' => $component), + 'mod_assign'); $button->reset_formats(); $this->portfolioform = $button->to_html(PORTFOLIO_ADD_TEXT_LINK); } @@ -594,7 +599,9 @@ public function preprocess($dir, $filearea, $component) { if (!empty($CFG->enableportfolios)) { $button = new portfolio_add_button(); if (has_capability('mod/assign:exportownsubmission', $this->context)) { - $button->set_callback_options('assign_portfolio_caller', array('cmid' => $this->cm->id, 'fileid' => $file->get_id()), '/mod/assign/portfolio_callback.php'); + $button->set_callback_options('assign_portfolio_caller', + array('cmid' => $this->cm->id, 'fileid' => $file->get_id()), + 'mod_assign'); $button->set_format_by_file($file); $file->portfoliobutton = $button->to_html(PORTFOLIO_ADD_ICON_LINK); } diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 33ce9bd24b47f..3198609b0ba49 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -2142,7 +2142,9 @@ function print_user_files($userid=0, $return=false) { $path = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_assignment/submission/'.$submission->id.'/'.$filename); $output .= ''.$OUTPUT->pix_icon(file_file_icon($file), get_mimetype_description($file), 'moodle', array('class' => 'icon')).s($filename).''; if ($CFG->enableportfolios && $this->portfolio_exportable() && has_capability('mod/assignment:exportownsubmission', $this->context)) { - $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'submissionid' => $submission->id, 'fileid' => $file->get_id()), '/mod/assignment/locallib.php'); + $button->set_callback_options('assignment_portfolio_caller', + array('id' => $this->cm->id, 'submissionid' => $submission->id, 'fileid' => $file->get_id()), + 'mod_assignment'); $button->set_format_by_file($file); $output .= $button->to_html(PORTFOLIO_ADD_ICON_LINK); } @@ -2154,7 +2156,9 @@ function print_user_files($userid=0, $return=false) { } } if ($CFG->enableportfolios && count($files) > 1 && $this->portfolio_exportable() && has_capability('mod/assignment:exportownsubmission', $this->context)) { - $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'submissionid' => $submission->id), '/mod/assignment/locallib.php'); + $button->set_callback_options('assignment_portfolio_caller', + array('id' => $this->cm->id, 'submissionid' => $submission->id), + 'mod_assignment'); $output .= '
' . $button->to_html(PORTFOLIO_ADD_TEXT_LINK); } } diff --git a/mod/assignment/renderer.php b/mod/assignment/renderer.php index f514e7f75abad..6545edcf719e3 100644 --- a/mod/assignment/renderer.php +++ b/mod/assignment/renderer.php @@ -100,7 +100,7 @@ public function __construct($context, $itemid, $filearea='submission') { $files = $fs->get_area_files($this->context->id, 'mod_assignment', $filearea, $itemid, "timemodified", false); if (count($files) >= 1 && has_capability('mod/assignment:exportownsubmission', $this->context)) { $button = new portfolio_add_button(); - $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'submissionid' => $itemid), '/mod/assignment/locallib.php'); + $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'submissionid' => $itemid), 'mod_assignment'); $button->reset_formats(); $this->portfolioform = $button->to_html(PORTFOLIO_ADD_TEXT_LINK); } @@ -117,7 +117,7 @@ public function preprocess($dir, $filearea) { if (!empty($CFG->enableportfolios)) { $button = new portfolio_add_button(); if (has_capability('mod/assignment:exportownsubmission', $this->context)) { - $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'fileid' => $file->get_id()), '/mod/assignment/locallib.php'); + $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'fileid' => $file->get_id()), 'mod_assignment'); $button->set_format_by_file($file); $file->portfoliobutton = $button->to_html(PORTFOLIO_ADD_ICON_LINK); } diff --git a/mod/assignment/type/online/assignment.class.php b/mod/assignment/type/online/assignment.class.php index f3cd31be9abfd..a917d31eb4a4e 100644 --- a/mod/assignment/type/online/assignment.class.php +++ b/mod/assignment/type/online/assignment.class.php @@ -117,7 +117,7 @@ function view() { if ($CFG->enableportfolios) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id), '/mod/assignment/locallib.php'); + $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id), 'mod_assignment'); $fs = get_file_storage(); if ($files = $fs->get_area_files($this->context->id, 'mod_assignment', $this->filearea, $submission->id, "timemodified", false)) { $button->set_formats(PORTFOLIO_FORMAT_RICHHTML); diff --git a/mod/chat/report.php b/mod/chat/report.php index 331cc964d2d35..35bd20288a935 100644 --- a/mod/chat/report.php +++ b/mod/chat/report.php @@ -113,7 +113,7 @@ 'end' => $end, ); $button = new portfolio_add_button(); - $button->set_callback_options('chat_portfolio_caller', $buttonoptions, '/mod/chat/locallib.php'); + $button->set_callback_options('chat_portfolio_caller', $buttonoptions, 'mod_chat'); $button->render(); } echo $OUTPUT->box_end(); @@ -239,7 +239,7 @@ 'end' => $sessionend, ); $button = new portfolio_add_button(); - $button->set_callback_options('chat_portfolio_caller', $buttonoptions, '/mod/chat/locallib.php'); + $button->set_callback_options('chat_portfolio_caller', $buttonoptions, 'mod_chat'); $portfoliobutton = $button->to_html(PORTFOLIO_ADD_TEXT_LINK); if (!empty($portfoliobutton)) { echo '
' . $portfoliobutton; @@ -265,7 +265,7 @@ if (!empty($CFG->enableportfolios) && $canexportsess) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('chat_portfolio_caller', array('id' => $cm->id), '/mod/chat/locallib.php'); + $button->set_callback_options('chat_portfolio_caller', array('id' => $cm->id), 'mod_chat'); $button->render(null, get_string('addalltoportfolio', 'portfolio')); } diff --git a/mod/data/lib.php b/mod/data/lib.php index fb0dc5f052281..a1a47038afff9 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -1234,7 +1234,7 @@ function data_print_template($template, $records, $data, $search='', $page=0, $r || (data_isowner($record->id) && has_capability('mod/data:exportownentry', $context))))) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id, 'recordid' => $record->id), '/mod/data/locallib.php'); + $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id, 'recordid' => $record->id), 'mod_data'); list($formats, $files) = data_portfolio_caller::formats($fields, $record); $button->set_formats($formats); $replacement[] = $button->to_html(PORTFOLIO_ADD_ICON_LINK); diff --git a/mod/data/view.php b/mod/data/view.php index 5220e04f16c56..65e512d8a68e5 100644 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -760,7 +760,7 @@ if ($mode == '' && !empty($CFG->enableportfolios)) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id), '/mod/data/locallib.php'); + $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id), 'mod_data'); if (data_portfolio_caller::has_files($data)) { $button->set_formats(array(PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_LEAP2A)); // no plain html for us } diff --git a/mod/forum/discuss.php b/mod/forum/discuss.php index efbb8df0457a7..774e7b0fe559b 100644 --- a/mod/forum/discuss.php +++ b/mod/forum/discuss.php @@ -192,7 +192,7 @@ if (!empty($CFG->enableportfolios) && has_capability('mod/forum:exportdiscussion', $modcontext)) { require_once($CFG->libdir.'/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('forum_portfolio_caller', array('discussionid' => $discussion->id), '/mod/forum/locallib.php'); + $button->set_callback_options('forum_portfolio_caller', array('discussionid' => $discussion->id), 'mod_forum'); $button = $button->to_html(PORTFOLIO_ADD_FULL_FORM, get_string('exportdiscussion', 'mod_forum')); $buttonextraclass = ''; if (empty($button)) { diff --git a/mod/forum/lib.php b/mod/forum/lib.php index d39ad0efb6b62..822e177e45045 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -3347,7 +3347,7 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa $p = array('postid' => $post->id); require_once($CFG->libdir.'/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id), '/mod/forum/locallib.php'); + $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id), 'mod_forum'); if (empty($attachments)) { $button->set_formats(PORTFOLIO_FORMAT_PLAINHTML); } else { @@ -4001,7 +4001,7 @@ function forum_print_attachments($post, $cm, $type) { $output .= "$iconimage "; $output .= "".s($filename).""; if ($canexport) { - $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), '/mod/forum/locallib.php'); + $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), 'mod_forum'); $button->set_format_by_file($file); $output .= $button->to_html(PORTFOLIO_ADD_ICON_LINK); } @@ -4015,7 +4015,7 @@ function forum_print_attachments($post, $cm, $type) { // Image attachments don't get printed as links $imagereturn .= "
\"\""; if ($canexport) { - $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), '/mod/forum/locallib.php'); + $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), 'mod_forum'); $button->set_format_by_file($file); $imagereturn .= $button->to_html(PORTFOLIO_ADD_ICON_LINK); } @@ -4023,7 +4023,7 @@ function forum_print_attachments($post, $cm, $type) { $output .= "$iconimage "; $output .= format_text("".s($filename)."", FORMAT_HTML, array('context'=>$context)); if ($canexport) { - $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), '/mod/forum/locallib.php'); + $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id, 'attachment' => $file->get_id()), 'mod_forum'); $button->set_format_by_file($file); $output .= $button->to_html(PORTFOLIO_ADD_ICON_LINK); } diff --git a/mod/glossary/export.php b/mod/glossary/export.php index 773fd7f730721..8abcaea9b4629 100644 --- a/mod/glossary/export.php +++ b/mod/glossary/export.php @@ -70,7 +70,7 @@ if (!empty($CFG->enableportfolios) && $DB->count_records('glossary_entries', array('glossaryid' => $glossary->id))) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('glossary_full_portfolio_caller', array('id' => $cm->id), '/mod/glossary/locallib.php'); + $button->set_callback_options('glossary_full_portfolio_caller', array('id' => $cm->id), 'mod_glossary'); $button->render(); } echo $OUTPUT->box_end(); diff --git a/mod/glossary/lib.php b/mod/glossary/lib.php index 49f4c3fc16925..3c3f46379c588 100644 --- a/mod/glossary/lib.php +++ b/mod/glossary/lib.php @@ -1273,7 +1273,7 @@ function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$h if (!empty($CFG->enableportfolios) && (has_capability('mod/glossary:exportentry', $context) || ($iscurrentuser && has_capability('mod/glossary:exportownentry', $context)))) { require_once($CFG->libdir . '/portfoliolib.php'); $button = new portfolio_add_button(); - $button->set_callback_options('glossary_entry_portfolio_caller', array('id' => $cm->id, 'entryid' => $entry->id), '/mod/glossary/locallib.php'); + $button->set_callback_options('glossary_entry_portfolio_caller', array('id' => $cm->id, 'entryid' => $entry->id), 'mod_glossary'); $filecontext = $context; if ($entry->sourceglossaryid == $cm->instance) { diff --git a/portfolio/add.php b/portfolio/add.php index 8cca63565bfe8..8a22e6fc60332 100644 --- a/portfolio/add.php +++ b/portfolio/add.php @@ -33,18 +33,18 @@ require_once($CFG->libdir . '/portfolio/caller.php'); require_once($CFG->libdir . '/portfolio/plugin.php'); -$dataid = optional_param('id', 0, PARAM_INT); // id of partially completed export. corresponds to a record in portfolio_tempdata -$type = optional_param('type', null, PARAM_SAFEDIR); // if we're returning from an external system (postcontrol) for a single-export only plugin -$cancel = optional_param('cancel', 0, PARAM_RAW); // user has cancelled the request -$cancelsure = optional_param('cancelsure', 0, PARAM_BOOL); // make sure they confirm first -$logreturn = optional_param('logreturn', 0, PARAM_BOOL); // when cancelling, we can also come from the log page, rather than the caller -$instanceid = optional_param('instance', 0, PARAM_INT); // instanceof of configured portfolio plugin -$courseid = optional_param('course', 0, PARAM_INT); // courseid the data being exported belongs to (caller object should provide this later) -$stage = optional_param('stage', PORTFOLIO_STAGE_CONFIG, PARAM_INT); // stage of the export we're at (stored in the exporter) -$postcontrol = optional_param('postcontrol', 0, PARAM_INT); // when returning from some bounce to an external system, this gets passed -$callbackfile = optional_param('callbackfile', null, PARAM_PATH); // callback file eg /mod/forum/lib.php - the location of the exporting content -$callbackclass = optional_param('callbackclass', null, PARAM_ALPHAEXT); // callback class eg forum_portfolio_caller - the class to handle the exporting content. -$callerformats = optional_param('callerformats', null, PARAM_TAGLIST); // comma separated list of formats the specific place exporting content supports +$dataid = optional_param('id', 0, PARAM_INT); // The ID of partially completed export, corresponds to a record in portfolio_tempdata. +$type = optional_param('type', null, PARAM_SAFEDIR); // If we're returning from an external system (postcontrol) for a single-export only plugin. +$cancel = optional_param('cancel', 0, PARAM_RAW); // User has cancelled the request. +$cancelsure = optional_param('cancelsure', 0, PARAM_BOOL); // Make sure they confirm first. +$logreturn = optional_param('logreturn', 0, PARAM_BOOL); // When cancelling, we can also come from the log page, rather than the caller. +$instanceid = optional_param('instance', 0, PARAM_INT); // The instance of configured portfolio plugin. +$courseid = optional_param('course', 0, PARAM_INT); // The courseid the data being exported belongs to (caller object should provide this later). +$stage = optional_param('stage', PORTFOLIO_STAGE_CONFIG, PARAM_INT); // Stage of the export we're at (stored in the exporter). +$postcontrol = optional_param('postcontrol', 0, PARAM_INT); // When returning from some bounce to an external system, this gets passed. +$callbackcomponent = optional_param('callbackcomponent', null, PARAM_PATH); // Callback component eg mod_forum - the component of the exporting content. +$callbackclass = optional_param('callbackclass', null, PARAM_ALPHAEXT); // Callback class eg forum_portfolio_caller - the class to handle the exporting content. +$callerformats = optional_param('callerformats', null, PARAM_TAGLIST); // Comma separated list of formats the specific place exporting content supports. require_login(); // this is selectively called again with $course later when we know for sure which one we're in. $PAGE->set_context(get_system_context()); @@ -152,7 +152,7 @@ // we must be passed this from the caller, we cannot start a new export // without knowing information about what part of moodle we come from. - if (empty($callbackfile) || empty($callbackclass)) { + if (empty($callbackcomponent) || empty($callbackclass)) { debugging('no callback file or class'); portfolio_exporter::print_expired_export(); } @@ -173,13 +173,10 @@ $callbackargs[substr($key, 3)] = $value; } } - // righto, now we have the callback args set up - // load up the caller file and class and tell it to set up all the data - // it needs - require_once($CFG->dirroot . $callbackfile); - if (!class_exists($callbackclass) || !is_subclass_of($callbackclass, 'portfolio_caller_base')) { - throw new portfolio_caller_exception('callbackclassinvalid', 'portfolio'); - } + + // Ensure that we found a file we can use, if not throw an exception. + portfolio_include_callback_file($callbackcomponent, $callbackclass); + $caller = new $callbackclass($callbackargs); $caller->set('user', $USER); if ($formats = explode(',', $callerformats)) { @@ -194,7 +191,7 @@ portfolio_export_pagesetup($PAGE, $caller); // this calls require_login($course) if it can.. // finally! set up the exporter object with the portfolio instance, and caller information elements - $exporter = new portfolio_exporter($instance, $caller, $callbackfile); + $exporter = new portfolio_exporter($instance, $caller, $callbackcomponent); // set the export-specific variables, and save. $exporter->set('user', $USER); diff --git a/portfolio/upgrade.txt b/portfolio/upgrade.txt index efc88ea345e6c..460df3dbe6ff4 100644 --- a/portfolio/upgrade.txt +++ b/portfolio/upgrade.txt @@ -7,3 +7,20 @@ required changes: * The following methods must now be declared static for php5 compatibility: - admin_config_form - admin_config_validation + +=== 2.4 === + +The set_callback_options function's third parameter has been changed from a file path +to the component name - see MDL-33791. However, if any existing code passes a file path +Moodle will attempt to obtain the component name from the file path provided. Also, the +callback class should be located in the module's locallib.php file. + +Example of change: + +This: + +$button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'fileid' => $file->get_id()), '/mod/assignment/locallib.php'); + +Now becomes: + +$button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'fileid' => $file->get_id()), 'mod_assignment'); \ No newline at end of file diff --git a/user/portfoliologs.php b/user/portfoliologs.php index d9f60355ebd67..1fa544b43deef 100644 --- a/user/portfoliologs.php +++ b/user/portfoliologs.php @@ -117,7 +117,13 @@ ); $logs = $DB->get_records('portfolio_log', array('userid' => $USER->id), 'time DESC', '*', ($page * $perpage), $perpage); foreach ($logs as $log) { - require_once($CFG->dirroot . $log->caller_file); + if (!empty($log->caller_file)) { + portfolio_include_callback_file($log->caller_file); + } else if (!empty($log->caller_component)) { + portfolio_include_callback_file($log->caller_component); + } else { // Errrmahgerrrd - this should never happen. Skipping. + continue; + } $class = $log->caller_class; $pluginname = ''; try { diff --git a/version.php b/version.php index b6cffad1e958a..6e7cade5b3950 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012110700.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012110700.01; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes