Portfolio MDL-19356 removal of session reliance completely.

For plugins that don't support it, we can work around the external
redirect issue by returning to a special url.

This also adds on selective cancelling/continuing of current exports.

It needs a lot of testing, but seems to be working reasonably well.

Some plugins need updating now, however
This commit is contained in:
Penny Leach 2009-11-17 14:01:25 +00:00
parent f1d2641df6
commit c95a609597
9 changed files with 186 additions and 172 deletions

View File

@ -13,6 +13,7 @@ $string['callercouldnotpackage'] = 'Failed to package up your data for export: o
$string['cannotsetvisible'] = 'Cannot set this to visible - the plugin has been completely disabled because of a misconfiguration';
$string['configexport'] = 'Configure exported data';
$string['configplugin'] = 'Configure portfolio plugin';
$string['confirmcancel'] = 'Are you sure you wish you cancel this export?';
$string['confirmexport'] = 'Please confirm this export';
$string['confirmsummary'] = 'Summary of your export';
$string['configure'] = 'Configure';
@ -102,6 +103,9 @@ $string['nocallbackfile'] = 'Something in the module you\'re trying to export fr
$string['nocallbackclass'] = 'Could not find the callback class to use ($a)';
$string['nocommonformats'] = 'No common formats between any available portfolio plugin and the calling location $a';
$string['noclassbeforeformats'] = 'You must set the callback class before calling set_formats in portfolio_button';
$string['noinstanceyet'] = 'Not yet selected';
$string['nologs'] = 'There are no logs to display!';
$string['nomultipleexports'] = 'Sorry, but the portfolio destination ($a->plugin) doesn\'t support multiple exports at the same time. Please <a href=\"$a->link\">finish the current one first</a> and try again';
$string['nopermissions'] = 'Sorry but you do not have the required permissions to export files from this area';
$string['nonprimative'] = 'A non primative value was passed as a callback argument to portfolio_add_button. Refusing to continue. The key was $a->key and the value was $a->value';
$string['notexportable'] = 'Sorry, but the type of content you are trying to export is not exportable';
@ -120,6 +124,7 @@ $string['save'] = 'Save';
$string['selectedformat'] = 'Selected export format';
$string['selectedwait'] = 'Selected to wait?';
$string['selectplugin'] = 'Select destination';
$string['singleinstancenomultiallowed'] = 'Only a single portfolio plugin instance is available, it doesn\'t support multiple exports per session, and there\'s already an active export in the session using this plugin!';
$string['someinstancesdisabled'] = 'Some configured portfolio plugin instances have been disabled either because they are misconfigured or rely on something else that is';
$string['somepluginsdisabled'] = 'Some entire portfolio plugins have been disabled because they are either misconfigured or rely on something else that is:';
$string['sure'] = 'Are you sure you want to delete \'$a\'? This cannot be undone.';

View File

@ -59,11 +59,6 @@ class portfolio_export_exception extends portfolio_exception {
// but I think if there's always an exception, we should clean up
// rather than force the user to resolve the export later.
$exporter->process_stage_cleanup();
} else {
global $SESSION;
if (!empty($SESSION->portfolioexport)) {
debugging(get_string('exportexceptionnoexporter', 'portfolio'));
}
}
parent::__construct($errorcode, $module, $continue, $a);
}

View File

@ -89,12 +89,6 @@ class portfolio_exporter {
*/
private $id;
/**
* the session key during the export
* used to avoid hijacking transfers
*/
private $sesskey;
/**
* array of stages that have had the portfolio plugin already steal control from them
*/
@ -113,6 +107,16 @@ class portfolio_exporter {
*/
private $format;
/**
* queued - this is set after the event is triggered
*/
private $queued = false;
/**
* expiry time - set the first time the object is saved out
*/
private $expirytime;
/**
* construct a new exporter for use
*
@ -286,6 +290,7 @@ class portfolio_exporter {
if ($pluginobj || $callerobj || count($formats) > 1 || ($expectedtime != PORTFOLIO_TIME_LOW && $expectedtime != PORTFOLIO_TIME_FORCEQUEUE)) {
$customdata = array(
'instance' => $this->instance,
'id' => $this->id,
'plugin' => $pluginobj,
'caller' => $callerobj,
'userid' => $this->user->id,
@ -371,8 +376,9 @@ class portfolio_exporter {
return true;
}
$strconfirm = get_string('confirmexport', 'portfolio');
$yesurl = $CFG->wwwroot . '/portfolio/add.php?stage=' . PORTFOLIO_STAGE_QUEUEORWAIT;
$nourl = $CFG->wwwroot . '/portfolio/add.php?cancel=1';
$baseurl = $CFG->wwwroot . '/portfolio/add.php?sesskey=' . sesskey() . '&id=' . $this->get('id');
$yesurl = $baseurl . '&stage=' . PORTFOLIO_STAGE_QUEUEORWAIT;
$nourl = $baseurl . '&cancel=1';
$this->print_header('confirmexport');
echo $OUTPUT->box_start();
echo $OUTPUT->heading(get_string('confirmsummary', 'portfolio'), 4);
@ -420,11 +426,10 @@ class portfolio_exporter {
* @return boolean whether or not to process the next stage. this is important as the control function is called recursively.
*/
public function process_stage_queueorwait() {
global $SESSION;
$wait = $this->instance->get_export_config('wait');
if (empty($wait)) {
events_trigger('portfolio_send', $this->id);
unset($SESSION->portfolioexport);
$this->queued = true;
return $this->process_stage_finished(true);
}
return true;
@ -465,10 +470,9 @@ class portfolio_exporter {
* @return boolean whether or not to process the next stage. this is important as the control function is called recursively.
*/
public function process_stage_cleanup($pullok=false) {
global $CFG, $DB, $SESSION;
global $CFG, $DB;
if (!$pullok && $this->get('instance') && !$this->get('instance')->is_push()) {
unset($SESSION->portfolioexport);
return true;
}
if ($this->get('instance')) {
@ -478,7 +482,6 @@ class portfolio_exporter {
$DB->delete_records('portfolio_tempdata', array('id' => $this->id));
$fs = get_file_storage();
$fs->delete_area_files(SYSCONTEXTID, 'portfolio_exporter', $this->id);
unset($SESSION->portfolioexport);
return true;
}
@ -590,11 +593,15 @@ class portfolio_exporter {
* cancels a potfolio request and cleans up the tempdata
* and redirects the user back to where they started
*/
public function cancel_request() {
public function cancel_request($logreturn=false) {
global $CFG;
if (!isset($this)) {
return;
}
$this->process_stage_cleanup(true);
if ($logreturn) {
redirect($CFG->wwwroot . '/user/portfoliologs.php');
}
redirect($this->caller->get_return_url());
exit;
}
@ -612,6 +619,7 @@ class portfolio_exporter {
'instance' => (empty($this->instance)) ? null : $this->instance->get('id'),
);
$this->id = $DB->insert_record('portfolio_tempdata', $r);
$this->expirytime = $r->expirytime;
$this->save(); // call again so that id gets added to the save data.
} else {
$r = $DB->get_record('portfolio_tempdata', array('id' => $this->id));
@ -641,6 +649,13 @@ class portfolio_exporter {
}
require_once($CFG->dirroot . '/' . $exporter->callerfile);
$exporter = unserialize(serialize($exporter));
if (!$exporter->get('id')) {
// workaround for weird case
// where the id doesn't get saved between a new insert
// and the subsequent call that sets this field in the serialised data
$exporter->set('id', $id);
$exporter->save();
}
return $exporter;
}
@ -669,14 +684,21 @@ class portfolio_exporter {
* @throws portfolio_exception
*/
public function verify_rewaken($readonly=false) {
global $USER;
if ($this->get('user')->id != $USER->id) {
global $USER, $CFG;
if ($this->get('user')->id != $USER->id) { // make sure it belongs to the right user
throw new portfolio_exception('notyours', 'portfolio');
}
if (!$readonly && !confirm_sesskey($this->get('sesskey'))) {
throw new portfolio_exception('confirmsesskeybad');
if (!$readonly && $this->get('instance') && !$this->get('instance')->allows_multiple_exports()
&& ($already = portfolio_exporter::existing_exports($this->get('user')->id, $this->get('instance')->get('plugin')))
&& array_shift(array_keys($already)) != $this->get('id')
) {
$a = (object)array(
'plugin' => $this->get('instance')->get('plugin'),
'link' => $CFG->wwwroot . '/user/portfoliologs.php',
);
throw new portfolio_exception('nomultipleexports', 'portfolio', '', $a);
}
if (!$this->caller->check_permissions()) {
if (!$this->caller->check_permissions()) { // recall the caller permission check
throw new portfolio_caller_exception('nopermissions', 'portfolio', $this->caller->get_return_url());
}
}
@ -799,4 +821,37 @@ class portfolio_exporter {
exit;
}
/**
* return a list of current exports for the given user
* this will not go through and call rewaken_object, because it's heavy
* it's really just used to figure out what exports are currently happening.
* this is useful for plugins that don't support multiple exports per session
*
* @param int $userid the user to check for
* @param string $type (optional) the portfolio plugin to filter by
*
* @return array
*/
public static function existing_exports($userid, $type=null) {
global $DB;
$sql = 'SELECT t.*,t.instance,i.plugin,i.name FROM {portfolio_tempdata} t JOIN {portfolio_instance} i ON t.instance = i.id WHERE t.userid = ? ';
$values = array($userid);
if ($type) {
$sql .= ' AND i.plugin = ?';
$values[] = $type;
}
return $DB->get_records_sql($sql, $values);
}
/**
* Return an array of existing exports by type for a given user.
* This is much more lightweight than {@see existing_exports} because it only returns the types, rather than the whole serialised data
* so can be used for checking availability of multiple plugins at the same time.
*/
public static function existing_exports_by_plugin($userid) {
global $DB;
$sql = 'SELECT t.instance,i.plugin FROM {portfolio_tempdata} t JOIN {portfolio_instance} i ON t.instance = i.id WHERE t.userid = ? ';
$values = array($userid);
return $DB->get_records_sql_menu($sql, $values);
}
}

View File

@ -45,9 +45,11 @@ final class portfolio_export_form extends moodleform {
$mform =& $this->_form;
$mform->addElement('hidden', 'stage', PORTFOLIO_STAGE_CONFIG);
$mform->setType('stage', PARAM_INT);
$mform->addElement('hidden', 'id', $this->_customdata['id']);
$mform->addElement('hidden', 'instance', $this->_customdata['instance']->get('id'));
$mform->setType('instance', PARAM_INT);
$mform->setType('stage', PARAM_INT);
$mform->setType('id', PARAM_INT);
if (array_key_exists('formats', $this->_customdata) && is_array($this->_customdata['formats'])) {
if (count($this->_customdata['formats']) > 1) {
@ -260,12 +262,16 @@ class portfolio_instance_select extends moodleform {
true,
true
);
// TODO maybe add on some information to the user if they're already exporting
// and some of the options were skipped because they are for plugins that don't support
// multiple exports per session
if (empty($options)) {
debugging('noavailableplugins', 'portfolio');
return false;
}
$mform =& $this->_form;
$mform->addElement('select', 'instance', get_string('selectplugin', 'portfolio'), $options);
$mform->addElement('hidden', 'id', $this->_customdata['id']);
$this->add_action_buttons(true, get_string('next'));
}
}

View File

@ -717,6 +717,20 @@ abstract class portfolio_plugin_base {
public static function mnet_publishes() {
return array();
}
/**
* whether this plugin supports multiple exports in the same session
* most plugins should handle this, but some that require a redirect for authentication
* and then don't support dynamically constructed urls to return to (eg box.net)
* need to override this to return false.
* this means that moodle will prevent multiple exports of this *type* of plugin
* occurring in the same session.
*
* @return boolean
*/
public static function allows_multiple_exports() {
return true;
}
}
/**

View File

@ -66,7 +66,6 @@ require_once($CFG->libdir . '/portfolio/caller.php'); // the base classes f
*/
class portfolio_add_button {
private $alreadyexporting;
private $callbackclass;
private $callbackargs;
private $callbackfile;
@ -87,14 +86,11 @@ class portfolio_add_button {
*/
public function __construct($options=null) {
global $SESSION, $CFG;
if (isset($SESSION->portfolioexport)) {
$this->alreadyexporting = true;
return;
}
$this->instances = portfolio_instances();
if (empty($options)) {
return true;
}
$constructoroptions = array('callbackclass', 'callbackargs', 'callbackfile', 'formats');
foreach ((array)$options as $key => $value) {
if (!in_array($key, $constructoroptions)) {
throw new portfolio_button_exception('invalidbuttonproperty', 'portfolio', $key);
@ -117,9 +113,6 @@ class portfolio_add_button {
* this path should be relative (ie, not include) dirroot, eg '/mod/forum/lib.php'
*/
public function set_callback_options($class, array $argarray, $file=null) {
if ($this->alreadyexporting) {
return;
}
global $CFG;
if (empty($file)) {
$backtrace = debug_backtrace();
@ -159,9 +152,6 @@ class portfolio_add_button {
* {@see portfolio_format_from_file} for how to get the appropriate formats to pass here for uploaded files.
*/
public function set_formats($formats=null) {
if ($this->alreadyexporting) {
return;
}
if (is_string($formats)) {
$formats = array($formats);
}
@ -198,9 +188,6 @@ class portfolio_add_button {
* this is whole string, not key. optional, defaults to 'Add to portfolio';
*/
public function to_html($format=null, $addstr=null) {
if ($this->alreadyexporting) {
return $this->already_exporting($format, $addstr);
}
global $CFG, $COURSE, $OUTPUT;
if (!$this->is_renderable()) {
return;
@ -235,7 +222,7 @@ class portfolio_add_button {
if (count($this->instances) == 1) {
$tmp = array_values($this->instances);
$instance = $tmp[0];
//$instance = array_shift($this->instances);
$formats = portfolio_supported_formats_intersect($this->formats, $instance->supported_formats());
if (count($formats) == 0) {
// bail. no common formats.
@ -247,6 +234,10 @@ class portfolio_add_button {
debugging(get_string('instancemisconfigured', 'portfolio', get_string($error[$instance->get('id')], 'portfolio_' . $instance->get('plugin'))));
return;
}
if (!$instance->allows_multiple_exports() && $already = portfolio_exporter::existing_exports($USER->id, $instance->get('plugin'))) {
debugging(get_string('singleinstancenomultiallowed', 'portfolio'));
return;
}
$formoutput .= "\n" . '<input type="hidden" name="instance" value="' . $instance->get('id') . '" />';
$linkoutput .= '&amp;instance=' . $instance->get('id');
}
@ -336,33 +327,6 @@ class portfolio_add_button {
public function get_callbackclass() {
return $this->callbackclass;
}
private function already_exporting($format, $addstr) {
global $CFG, $OUTPUT;
$url = $CFG->wwwroot . '/portfolio/already.php';
$icon = $OUTPUT->old_icon_url('t/portfoliono') . '';
$alt = get_string('alreadyalt', 'portfolio');
if (empty($format)) {
$format = PORTFOLIO_ADD_FULL_FORM;
}
if (empty($addstr)) {
$addstr = get_string('addtoportfolio', 'portfolio');
}
switch ($format) {
case PORTFOLIO_ADD_FULL_FORM:
return '<form action="' . $url . '">' . "\n"
. '<input type="submit" value="' . $addstr . '" />' . "\n"
. '<img src="' . $icon . '" alt="' . $alt . '" />' . "\n"
. ' </form>';
case PORTFOLIO_ADD_ICON_FORM:
case PORTFOLIO_ADD_ICON_LINK:
return '<a href="' . $url . '"><img src="' . $icon . '" alt="' . $alt . '" /></a>';
case PORTFOLIO_ADD_TEXT_LINK:
return '<a href="' . $url . '">' . $addstr . '(!) </a>';
default:
debugging(get_string('invalidaddformat', 'portfolio', $format));
}
}
}
/**
@ -378,7 +342,7 @@ class portfolio_add_button {
* @return string the html, from <select> to </select> inclusive.
*/
function portfolio_instance_select($instances, $callerformats, $callbackclass, $selectname='instance', $return=false, $returnarray=false) {
global $CFG;
global $CFG, $USER;
if (empty($CFG->enableportfolios)) {
return;
@ -389,6 +353,7 @@ function portfolio_instance_select($instances, $callerformats, $callbackclass, $
$count = 0;
$selectoutput = "\n" . '<select name="' . $selectname . '">' . "\n";
$existingexports = portfolio_exporter::existing_exports_by_plugin($USER->id);
foreach ($instances as $instance) {
$formats = portfolio_supported_formats_intersect($callerformats, $instance->supported_formats());
if (count($formats) == 0) {
@ -404,6 +369,11 @@ function portfolio_instance_select($instances, $callerformats, $callbackclass, $
debugging(get_string('pluginismisconfigured', 'portfolio', get_string($pinsane[$instance->get('plugin')], 'portfolio_' . $instance->get('plugin'))));
continue;
}
if (!$instance->allows_multiple_exports() && in_array($instance->get('plugin'), $existingexports)) {
// bail, already exporting something with this plugin and it doesn't support multiple exports
continue;
}
$count++;
$selectoutput .= "\n" . '<option value="' . $instance->get('id') . '">' . $instance->get('name') . '</option>' . "\n";
$options[$instance->get('id')] = $instance->get('name');
@ -786,7 +756,7 @@ function portfolio_report_insane($insane, $instances=false, $return=false) {
*/
function portfolio_fake_add_url($instanceid, $classname, $classfile, $callbackargs) {
global $CFG;
$url = $CFG->wwwroot . '/portfolio/add.php?instance=' . $instanceid . '&amp;callbackclass=' . $classname . '&amp;callbackfile=' . $classfile;
$url = $CFG->wwwroot . '/portfolio/add.php?instance=' . $instanceid . '&amp;callbackclass=' . $classname . '&amp;callbackfile=' . $classfile . '&sesskey=' . sesskey();
if (is_object($callbackargs)) {
$callbackargs = (array)$callbackargs;

View File

@ -36,8 +36,11 @@ require_once($CFG->libdir . '/portfoliolib.php');
// so plugins don't have to.
require_once($CFG->libdir . '/formslib.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
$dataid = optional_param('id', 0, PARAM_INT); // id of partially completed export (in session, everything else in portfolio_tempdata
$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)
@ -46,14 +49,23 @@ $callbackfile = optional_param('callbackfile', null, PARAM_PATH); //
$callbackclass = optional_param('callbackclass', null, PARAM_ALPHAEXT); // callback class eg forum_portfolio_caller - the class to handle the exporting content.
require_login(); // this is selectively called again with $course later when we know for sure which one we're in.
$PAGE->set_url('/portfolio/add.php', array('id' => $dataid));
$PAGE->set_url('/portfolio/add.php', array('id' => $dataid, 'sesskey' => sesskey()));
$exporter = null;
// try and find a partial export id in the session if it's not passed explicitly
if (empty($dataid)) {
if (isset($SESSION->portfolioexport)) {
$dataid = $SESSION->portfolioexport;
if ($postcontrol && $type && !$dataid) {
// we're returning from an external system that can't construct dynamic return urls
// this is a special "one export of this type only per session" case
if (portfolio_static_function($type, 'allows_multiple_exports')) {
throw new portfolio_exception('multiplesingleresume', 'portfolio');
}
if (!$dataid = $DB->get_field('portfolio_tempdata', 'id', array('type' => $type, 'userid' => $USER->id))) {
throw new portfolio_exception('invalidtempid', 'portfolio');
}
} else {
// we can't do this in the above case, because we're redirecting straight back from an external system
// this is not really ideal, but since we're in a "staged" wizard, the session key is checked in other stages.
require_sesskey(); // pretty much everything in this page is a write that could be hijacked, so just do this at the top here
}
// if we have a dataid, it means we're in the middle of an export,
@ -65,18 +77,34 @@ if (!empty($dataid)) {
// this can happen in some cases, a cancel request is sent when something is already broken
// so process it elegantly and move on.
if ($cancel) {
unset($SESSION->portfolioexport);
if ($logreturn) {
redirect($CFG->wwwroot . '/user/portfoliologs.php');
}
redirect($CFG->wwwroot);
} else {
portfolio_exporter::print_expired_export();
throw $e;
}
}
// we have to wake it up first before we can cancel it
// so temporary directories etc get cleaned up.
if ($cancel) {
$exporter->cancel_request();
if ($cancelsure) {
$exporter->cancel_request($logreturn);
} else {
$yesurl = $CFG->wwwroot . '/portfolio/add.php?id=' . $dataid . '&cancel=1&cancelsure=1&logreturn=' . $logreturn . '&sesskey=' . sesskey();
$nourl = $CFG->wwwroot . '/portfolio/add.php?id=' . $dataid . '&sesskey=' . sesskey();
if ($logreturn) {
$nourl = $CFG->wwwroot . '/user/portfoliologs.php';
}
$exporter->print_header('confirmcancel');
echo $OUTPUT->box_start();
echo $OUTPUT->confirm(get_string('confirmcancel', 'portfolio'), $yesurl, $nourl);
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
exit;
}
}
// verify we still belong to the correct user and session
// verify we still belong to the correct user and permissions are still ok
$exporter->verify_rewaken();
// if we don't have an instanceid in the exporter
// it means we've just posted from the 'choose portfolio instance' page
@ -142,9 +170,6 @@ if (!empty($dataid)) {
$callbackargs[substr($key, 3)] = $value;
}
}
if (!confirm_sesskey()) {
throw new portfolio_caller_exception('confirmsesskeybad', 'error');
}
// 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
@ -167,11 +192,7 @@ if (!empty($dataid)) {
// set the export-specific variables, and save.
$exporter->set('user', $USER);
$exporter->set('sesskey', sesskey());
$exporter->save();
// and finally, put it in the session for waking up again later.
$SESSION->portfolioexport = $exporter->get('id');
}
if (!$exporter->get('instance')) {
@ -179,7 +200,7 @@ if (!$exporter->get('instance')) {
// in this case the exporter object and the caller object have been set up above
// so just make a little form to select the portfolio plugin instance,
// which is the last thing to do before starting the export.
$mform = new portfolio_instance_select('', array('caller' => $exporter->get('caller')));
$mform = new portfolio_instance_select('', array('id' => $exporter->get('id'), 'caller' => $exporter->get('caller')));
if ($mform->is_cancelled()) {
$exporter->cancel_request();
} else if ($fromform = $mform->get_data()){

View File

@ -1,82 +0,0 @@
<?php
/**
* Moodle - Modular Object-Oriented Dynamic Learning Environment
* http://moodle.org
* Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package moodle
* @subpackage portfolio
* @author Penny Leach <penny@catalyst.net.nz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*
* This file is the handler that gets invoked when there's already an export happening.
*/
require_once(dirname(dirname(__FILE__)) . '/config.php');
if (empty($CFG->enableportfolios)) {
print_error('disabled', 'portfolio');
}
require_once($CFG->libdir . '/portfoliolib.php');
require_login();
$dataid = 0;
// look for the export id in the request, if it's not there, try the session
if (!$dataid = optional_param('id', '', PARAM_INT) ) {
if (isset($SESSION->portfolioexport)) {
$dataid = $SESSION->portfolioexport;
}
}
// all we're going to do is print a table with some information
// about the current export, with a yes/ no option to resume or cancel.
$table = new html_table();
$table->head = array(
get_string('displayarea', 'portfolio'), // the part of moodle exporting content
get_string('destination', 'portfolio'), // the portfolio plugin instance
get_string('displayinfo', 'portfolio'), // any extra data about what it is we're exporting from the caller
);
$table->data = array();
if ($dataid) {
try {
// try to reawaken it and get any information about it we can
$exporter = portfolio_exporter::rewaken_object($dataid);
$exporter->verify_rewaken();
$table->data[] = array(
$exporter->get('caller')->display_name(),
($exporter->get('instance') ? $exporter->get('instance')->get('name') : get_string('notyetselected', 'portfolio')),
$exporter->get('caller')->heading_summary(),
);
} catch (portfolio_exception $e) { } // maybe in this case we should just kill it and redirect to the new request anyway ?
}
$strheading = get_string('activeexport', 'portfolio');
$PAGE->set_title($strheading);
$PAGE->set_heading($strheading);
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string('alreadyexporting', 'portfolio'), $CFG->wwwroot . '/portfolio/add.php', $CFG->wwwroot . '/portfolio/add.php?cancel=1');
if (count($table->data) > 0) {
echo $OUTPUT->table($table);
}
echo $OUTPUT->footer();

View File

@ -63,8 +63,11 @@ echo $OUTPUT->header();
$currenttab = 'portfoliologs';
$showroles = 1;
$somethingprinted = false;
include('tabs.php');
echo $OUTPUT->box_start();
$queued = $DB->get_records('portfolio_tempdata', array('userid' => $USER->id), '', 'id, expirytime');
if (count($queued) > 0) {
$table = new html_table();
@ -73,22 +76,45 @@ if (count($queued) > 0) {
get_string('plugin', 'portfolio'),
get_string('displayinfo', 'portfolio'),
get_string('displayexpiry', 'portfolio'),
'',
);
$table->data = array();
$now = time();
foreach ($queued as $q){
$e = portfolio_exporter::rewaken_object($q->id);
$e->verify_rewaken(true);
$queued = $e->get('queued');
$base = $CFG->wwwroot . '/portfolio/add.php?id=' . $q->id . '&logreturn=1&sesskey=' . sesskey();
$iconstr = '';
$cancel = new moodle_action_icon();
$cancel->link->url = new moodle_url($base . '&cancel=1');
$cancel->image->src = $OUTPUT->old_icon_url('t/stop');
$cancel->linktext = get_string('cancel');
$iconstr = $OUTPUT->action_icon($cancel);
if (!$e->get('queued') && $e->get('expirytime') > $now) {
$continue = new moodle_action_icon();
$continue->link->url = new moodle_url($base);
$continue->image->src = $OUTPUT->old_icon_url('t/go');
$continue->linktext = get_string('continue');
$iconstr .= '&nbsp;' . $OUTPUT->action_icon($continue);
}
$table->data[] = array(
$e->get('caller')->display_name(),
$e->get('instance')->get('name'),
(($e->get('instance')) ? $e->get('instance')->get('name') : get_string('noinstanceyet', 'portfolio')),
$e->get('caller')->heading_summary(),
userdate($q->expirytime),
$iconstr,
);
unset($e); // this could potentially be quite big, so free it.
}
echo $OUTPUT->heading(get_string('queuesummary', 'portfolio'));
echo $OUTPUT->table($table);
$somethingprinted = true;
}
// paging - get total count separately
$logcount = $DB->count_records('portfolio_log', array('userid' => $USER->id));
if ($logcount > 0) {
$table = new html_table();
@ -120,9 +146,13 @@ if ($logcount > 0) {
echo $OUTPUT->paging_bar($pagingbar);
echo $OUTPUT->table($table);
echo $OUTPUT->paging_bar($pagingbar);
$somethingprinted = true;
}
if (!$somethingprinted) {
echo $OUTPUT->heading($strportfolios);
echo get_string('nologs', 'portfolio');
}
echo $OUTPUT->box_end();
echo $OUTPUT->footer();