]> git.mjollnir.org Git - moodle.git/commitdiff
Portfolio MDL-19356 removal of session reliance completely.
authorPenny Leach <penny@liip.ch>
Tue, 17 Nov 2009 14:01:25 +0000 (14:01 +0000)
committerPenny Leach <penny@liip.ch>
Tue, 17 Nov 2009 14:01:25 +0000 (14:01 +0000)
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

lang/en_utf8/portfolio.php
lib/portfolio/exceptions.php
lib/portfolio/exporter.php
lib/portfolio/forms.php
lib/portfolio/plugin.php
lib/portfoliolib.php
portfolio/add.php
portfolio/already.php [deleted file]
user/portfoliologs.php

index bff3bdc8b513582979ee0a6c061b58981ad841fc..ec958abb5aac18dba1ee5e015a71a2d594c51d91 100644 (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.';
index 3c249f0a6c29e6a6a99105f3b5b2b346536bd6fa..dee46e5020ca7ef85b0489b70573288ab613de1b 100644 (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);
     }
index 46ea79be635dbea465658deb6feee35439ca0dbf..6d0c8c29a6dbfc828f57ff5c3578acbc633b0150 100644 (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);
+    }
 }
index 6559eff60fd21b6ebefad25018a7a2c26ddfdd20..61ce6dfbab1a470c5c9175e112533f850ad5bf62 100644 (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'));
     }
 }
index e9cc4d0a79c8d600a28323520b1b775c0c0758f3..a8a91349bbb7294b9e73426303d7815d16acc183 100644 (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;
+    }
 }
 
 /**
index 5ed6b958140d78da7b456855762dbcd2729b5c17..7cd706f7f4e3a239d9782a7b9c99fd41872ebd67 100644 (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;
index 6834df733e79ece4bdf32afeec89e9e7a120fb0b..7cae4a23962f324d51b139cde0bcd7622c27a912 100644 (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()){
diff --git a/portfolio/already.php b/portfolio/already.php
deleted file mode 100644 (file)
index e7a3588..0000000
+++ /dev/null
@@ -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();
-
-
index 35aa89eb00df6b3d0cd1aaee7576f9e020bbb469..078b622efc02a4368c79623d8cda9ebeb3a78ea0 100644 (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();