This allows us to always have a unique id for a portfolio export which can be used as itemid for files api.
Also it makes the session smaller :)
$string['instancenotsaved'] = 'Failed to save portfolio';
$string['instancenotdelete'] = 'Failed to delete portfolio';
$string['instancesaved'] = 'Portfolio saved successfully';
+$string['invalidtempid'] = 'Invalid temporary id';
$string['invalidformat'] = 'Something is exporting an invalid format, $a';
$string['invalidinstance'] = 'Could not find that portfolio instance';
$string['manageportfolios'] = 'Manage portfolios';
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20080805" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20080806" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<KEY NAME="portfoliofk" TYPE="foreign" FIELDS="portfolio" REFTABLE="portfolio_instance" REFFIELDS="id" COMMENT="fk to portfolio_instance" PREVIOUS="userfk"/>
</KEYS>
</TABLE>
- <TABLE NAME="portfolio_tempdata" COMMENT="stores temporary data for portfolio exports" PREVIOUS="portfolio_log" NEXT="message_providers">
+ <TABLE NAME="portfolio_tempdata" COMMENT="stores temporary data for portfolio exports. the id of this table is used for the itemid for the temporary files area. cron can clean up stale records (and associated file data) after expirytime." PREVIOUS="portfolio_log" NEXT="message_providers">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="data"/>
- <FIELD NAME="data" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="dumping ground for portfolio callers to store their data in." PREVIOUS="id"/>
+ <FIELD NAME="data" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="dumping ground for portfolio callers to store their data in." PREVIOUS="id" NEXT="expirytime"/>
+ <FIELD NAME="expirytime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="time this record will expire (used for cron cleanups) - the start of export + 24 hours" PREVIOUS="data"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</SENTENCES>
</STATEMENT>
</STATEMENTS>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
upgrade_main_savepoint($result, 2008080500);
}
+ if ($result && $oldversion < 2008080600) {
+
+ $DB->delete_records('portfolio_tempdata'); // there shouldnt' be any, and it will cause problems with this upgrade.
+ /// Define field expirytime to be added to portfolio_tempdata
+ $table = new xmldb_table('portfolio_tempdata');
+ $field = new xmldb_field('expirytime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null, 'data');
+
+ /// Conditionally launch add field expirytime
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ /// Main savepoint reached
+ upgrade_main_savepoint($result, 2008080600);
+ }
return $result;
}
return;
}
- if (!empty($SESSION->portfoliointernal)) {
+ if (defined('PORTFOLIO_INTERNAL')) {
// something somewhere has detected a risk of this being called during inside the preparation
// eg forum_print_attachments
return;
}
+ if (isset($SESSION->portfolioexport)) {
+ print_error('alreadyexporting', 'portfolio');
+ }
+
if (empty($callbackfile)) {
$backtrace = debug_backtrace();
if (!array_key_exists(0, $backtrace) || !array_key_exists('file', $backtrace[0]) || !is_readable($backtrace[0]['file'])) {
$callersupports = call_user_func(array($callbackclass, 'supported_formats'));
- if (isset($SESSION->portfolio)) {
- return portfolio_exporter::raise_error('alreadyexporting', 'portfolio');
- }
-
$output = '<form method="post" action="' . $CFG->wwwroot . '/portfolio/add.php" id="portfolio-add-button">' . "\n";
foreach ($callbackargs as $key => $value) {
if (!empty($value) && !is_string($value) && !is_numeric($value)) {
*/
protected $user;
+
/**
- * id if any of tempdata
+ *
*/
- private $tempdataid;
+ private $stage;
/**
* if this caller wants any additional config items
}
- protected function set_export_data($data) {
- global $DB;
- if ($this->tempdataid) {
- $DB->set_field('portfolio_tempdata', 'data', serialize($data), array('id' => $this->tempdataid));
- }
- $this->tempdataid = $DB->insert_record('portfolio_tempdata', (object)array('data' => serialize($data)));
- }
-
- protected function get_export_data() {
- global $DB;
- if ($this->tempdataid) {
- if ($data = $DB->get_field('portfolio_tempdata', 'data', array('id' => $this->tempdataid))) {
- return unserialize($data);
- }
- }
- return false;
- }
/**
* Similar to the other allowed_config functions
public $instancefile;
public $callerfile;
+ /**
+ * id of this export - matches record in portfolio_tempdata
+ */
+ private $id;
+
/**
* construct a new exporter for use
*
* @return boolean whether or not to process the next stage. this is important as the function is called recursively.
*/
public function process_stage($stage, $alreadystolen=false) {
- global $SESSION;
if (!$alreadystolen && $url = $this->instance->steal_control($stage)) {
- $SESSION->portfolio->stagepresteal = $stage;
+ $this->set('stage', $stage);
+ $this->save();
+ //$SESSION->portfolio->stagepresteal = $stage;
redirect($url);
break;
}
$stage++;
return $this->process_stage($stage);
}
+ $this->save();
return false;
}
*/
public function process_stage_config() {
- global $SESSION;
+ //global $SESSION;
$pluginobj = $callerobj = null;
if ($this->instance->has_export_config()) {
);
$mform = new portfolio_export_form('', $customdata);
if ($mform->is_cancelled()){
+ $this->cancel_request();
+ /*
unset($SESSION->portfolio);
redirect($this->caller->get_return_url());
exit;
+ */
} else if ($fromform = $mform->get_data()){
if (!confirm_sesskey()) {
return $this->raise_error('confirmsesskeybad', '', $caller->get_return_url());
global $SESSION;
$wait = $this->instance->get_export_config('wait');
if (empty($wait)) {
- events_trigger('portfolio_send', $this);
- unset($SESSION->portfolio);
+ events_trigger('portfolio_send', $this->id);
+ unset($SESSION->portfolioexport);
return $this->process_stage_finished(true);
}
return true;
* @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() {
- global $CFG, $DB;
+ global $CFG, $DB, $SESSION;
// @todo this is unpleasant. fix it.
require_once($CFG->dirroot . '/backup/lib.php');
delete_dir_contents($this->tempdir);
// @todo maybe add a hook in the plugin(s)
- if ($this->caller->get('tempdataid')) {
- $DB->delete_records('portfolio_tempdata', array('id' => $this->caller->get('tempdataid')));
- }
-
+ $DB->delete_records('portfolio_tempdata', array('id' => $this->id));
+ unset($SESSION->portfolioexport);
return true;
}
* @return boolean whether or not to process the next stage. this is important as the control function is called recursively.
*/
public function process_stage_finished($queued=false) {
- global $SESSION;
+ //global $SESSION;
$returnurl = $this->caller->get_return_url();
$continueurl = $this->instance->get_continue_url();
$extras = $this->instance->get_extra_finish_options();
}
}
print_footer();
- unset($SESSION->portfolio);
+ //unset($SESSION->portfolio);
return false;
}
debugging(get_string($string, $module));
return false;
}
- global $SESSION;
- unset($SESSION->portfolio);
+ if (isset($this)) {
+ $this->process_stage_cleanup();
+ }
+ //global $SESSION;
+ //unset($SESSION->portfolio);
print_error($string, $module, $continue);
}
+
+ public function cancel_request() {
+ if (!isset($this)) {
+ return;
+ }
+ $this->process_stage_cleanup();
+ redirect($this->caller->get_return_url());
+ exit;
+ }
+
+ /**
+ * writes out the contents of this object and all its data to the portfolio_tempdata table and sets the 'id' field.
+ */
+ public function save() {
+ global $DB;
+ if (empty($this->id)) {
+ $r = (object)array(
+ 'data' => base64_encode(serialize($this)),
+ 'expirytime' => time() + (60*60*24),
+ );
+ $this->id = $DB->insert_record('portfolio_tempdata', $r);
+ } else {
+ $DB->set_field('portfolio_tempdata', 'data', base64_encode(serialize($this)), array('id' => $this->id));
+ }
+ }
+
+ public static function rewaken_object($id) {
+ global $DB, $CFG;
+ if (!$data = $DB->get_record('portfolio_tempdata', array('id' => $id))) {
+ portfolio_exporer::raise_error('invalidtempid', 'portfolio');
+ }
+ $exporter = unserialize(base64_decode($data->data));
+ if ($exporter->instancefile) {
+ require_once($CFG->dirroot . '/' . $exporter->instancefile);
+ }
+ require_once($CFG->dirroot . '/' . $exporter->callerfile);
+ $exporter = unserialize(serialize($exporter));
+ return $exporter;
+ }
}
class portfolio_instance_select extends moodleform {
*/
function portfolio_handle_event($eventdata) {
global $CFG;
- require_once($CFG->dirroot . '/' . $eventdata->instancefile);
- require_once($CFG->dirroot . '/' . $eventdata->callerfile);
- $exporter = unserialize(serialize($eventdata));
+ $exporter = portfolio_exporter::rewaken_object($eventdata);
$exporter->process_stage_package();
$exporter->process_stage_send();
$exporter->process_stage_cleanup();
private $fields;
private $fieldtypes;
private $delimiter;
+ private $exportdata;
public function __construct($callbackargs) {
global $DB;
$this->fields[] = $tmp;
$this->fieldtypes[] = $tmp->type;
}
- $this->set_export_data(data_get_exportdata($this->cm->instance, $this->fields, $this->selectedfields));
+ $this->exportdata = data_get_exportdata($this->cm->instance, $this->fields, $this->selectedfields);
}
public function expected_time() {
public function get_sha1() {
$str = '';
- foreach ($this->get_export_data() as $data) {
+ foreach ($this->exportdata as $data) {
$str .= implode(',', $data);
}
return sha1($str . ',' . $this->exporttype);
public function prepare_package($tempdir) {
global $DB;
- $exportdata = $this->get_export_data();
- $count = count($exportdata);
+ $count = count($this->exportdata);
switch ($this->exporttype) {
case 'csv':
- $return = data_export_csv($exportdata, $this->delimiter, $this->cm->name, $count, $tempdir);
+ $return = data_export_csv($this->exportdata, $this->delimiter, $this->cm->name, $count, $tempdir);
break;
case 'xls':
- $return = data_export_xls($exportdata, $this->cm->name, $count, $tempdir);
+ $return = data_export_xls($this->exportdata, $this->cm->name, $count, $tempdir);
break;
case 'ods':
- $return = data_export_ods($exportdata, $this->cm->name, $count, $tempdir);
+ $return = data_export_ods($this->exportdata, $this->cm->name, $count, $tempdir);
break;
}
return $return;
class glossary_csv_portfolio_caller extends portfolio_module_caller_base {
private $glossary;
+ private $exportdata;
public function __construct($callbackargs) {
global $DB;
ON c.id = ec.categoryid
WHERE ec.entryid ' . $where, $params);
- $this->set_export_data(array('entries' => $entries, 'aliases' => $aliases, 'categoryentries' => $categoryentries));
+ $this->exportdata = array('entries' => $entries, 'aliases' => $aliases, 'categoryentries' => $categoryentries);
}
public function expected_time() {
}
public function get_sha1() {
- return sha1(serialize($this->get_export_data()));
+ return sha1(serialize($this->exportdata));
}
public function prepare_package($tempdir) {
- $data = $this->get_export_data();
- $entries = $data['entries'];
+ $entries = $this->exportdata['entries'];
$aliases = array();
$categories = array();
- if (is_array($data['aliases'])) {
- foreach ($data['aliases'] as $alias) {
+ if (is_array($this->exportdata['aliases'])) {
+ foreach ($this->exportdata['aliases'] as $alias) {
if (!array_key_exists($alias->entryid, $aliases)) {
$aliases[$alias->entryid] = array();
}
$aliases[$alias->entryid][] = $alias->alias;
}
}
- if (is_array($data['categoryentries'])) {
- foreach ($data['categoryentries'] as $cat) {
+ if (is_array($this->exportdata['categoryentries'])) {
+ foreach ($this->exportdata['categoryentries'] as $cat) {
if (!array_key_exists($cat->entryid, $categories)) {
$categories[$cat->entryid] = array();
}
|| !$this->entry = $DB->get_record('glossary_entries', array('id' => $callbackargs['entryid']))) {
portfolio_exporter::raise_error('noentry', 'glossary');
}
+ /*
$aliases = $DB->get_records('glossary_alias', array('entryid' => $this->entry->id));
$categories = $DB->get_records_sql('SELECT ec.entryid, c.name
FROM {glossary_entries_categories} ec
JOIN {glossary_categories} c
ON c.id = ec.categoryid
WHERE ec.entryid = ?', array($this->entry->id));
- $this->set_export_data(array('entry' => $this->entry, 'aliases' => $aliases, 'categories' => $categories));
+ */
}
public function expected_time() {
}
public function prepare_package($tempdir) {
- global $SESSION;
- $data = $this->get_export_data();
- $data['entry']->approved = true; // in case we don't have $USER which this function checks
- $SESSION->portfoliointernal = true;
+ $this->entry->approved = true; // in case we don't have $USER which this function checks
+ define('PORTFOLIO_INTERNAL', true);
ob_start();
- glossary_print_entry($this->get('course'), $this->cm, $this->glossary, $data['entry'], null, null, false);
+ glossary_print_entry($this->get('course'), $this->cm, $this->glossary, $this->entry, null, null, false);
$content = ob_get_clean();
- $SESSION->portfoliointernal = false;
// @todo - convert to files api.
$status = ($handle = fopen($tempdir . '/' . clean_filename($this->entry->concept) . '.html', 'w'));
$status = $status && fwrite($handle, $content);
}
public function get_sha1() {
- $data = $this->get_export_data();
- return sha1(serialize($data['entry']) . serialize($data['aliases']) . serialize($data['categories']));
+ return sha1(serialize($this->entry));
}
}
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/formslib.php');
$exporter = null;
-if (isset($SESSION->portfolio) && isset($SESSION->portfolio->exporter)) {
- $exporter = unserialize(serialize($SESSION->portfolio->exporter));
- if ($exporter->instancefile) {
- require_once($CFG->dirroot . '/' . $exporter->instancefile);
+$dataid = 0;
+
+if (!$dataid = optional_param('id') ) {
+ if (isset($SESSION->portfolioexport)) {
+ $dataid = $SESSION->portfolioexport;
}
- require_once($CFG->dirroot . '/' . $exporter->callerfile);
- $exporter = unserialize(serialize($SESSION->portfolio->exporter));
- $SESSION->portfolio->exporter =& $exporter;
+}
+if ($dataid) {
+ $exporter = portfolio_exporter::rewaken_object($dataid);
if ($cancel = optional_param('cancel', 0, PARAM_RAW)) {
+ $exporter->cancel_request();
+ /*
$returnurl = $exporter->get('caller')->get_return_url();
unset($SESSION->portfolio);
redirect($returnurl);
+ */
}
if (!$exporter->get('instance')) {
if ($instance = optional_param('instance', '', PARAM_INT)) {
// for build navigation
if (!$course = $caller->get('course')) {
- echo 1;
$course = optional_param('course', 0, PARAM_INT);
}
if (!empty($course) && is_numeric($course)) {
- echo 2;
$course = $DB->get_record('course', array('id' => $course), 'id,shortname,fullname');
// this is yuk but used in build_navigation
}
$exporter = new portfolio_exporter($instance, $caller, $callbackfile, $navigation);
$exporter->set('user', $USER);
- $SESSION->portfolio = new StdClass;
- $SESSION->portfolio->exporter =& $exporter;
+ $exporter->save();
+ $SESSION->portfolioexport = $exporter->get('id');
}
// for places returning control to pass (rather than PORTFOLIO_STAGE_PACKAGE
// which is unstable if they can't get to the constant (eg external system)
if ($postcontrol = optional_param('postcontrol', 0, PARAM_INT)) {
- $stage = $SESSION->portfolio->stagepresteal;
+ $stage = $exporter->get('stage');
$exporter->instance()->post_control($stage, array_merge($_GET, $_POST));
$alreadystolen = true;
}
// for the next block to catch
$mform = new portfolio_instance_select('', array('caller' => $exporter->get('caller')));
if ($mform->is_cancelled()) {
+ $exporter->cancel_request();
+ /*
$returnurl = $caller->get_return_url();
unset($SESSION->portfolio);
redirect($returnurl);
exit;
+ */
} else if ($fromform = $mform->get_data()){
- redirect($CFG->wwwroot . '/portfolio/add.php?instance=' . $fromform->instance);
+ redirect($CFG->wwwroot . '/portfolio/add.php?instance=' . $fromform->instance . '&id=' . $exporter->get('id'));
exit;
}
else {
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
- $version = 2008080500; // YYYYMMDD = date of the last version bump
+ $version = 2008080600; // YYYYMMDD = date of the last version bump
// XX = daily increments
$release = '2.0 dev (Build: 20080806)'; // Human-friendly version name