// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
/**
* @package mod-data
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
*/
/**
- * @package mod-data
- * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * class to handle exporting the full database
*/
+class data_full_portfolio_caller extends portfolio_module_caller_base {
-class data_portfolio_caller extends portfolio_module_caller_base {
-
- /** @var int */
- protected $recordid;
- /** @var string */
- protected $exporttype;
- /** @var string */
+ /** field delimiter - used for csv */
protected $delimiter_name;
- /** @var object */
+ /** data object - represents row in database */
private $data;
- /**#@+ @var array */
+
+ /** selected fields to export */
private $selectedfields;
+
+ /** array of field objects for each field */
private $fields;
+
+ /** array of field types for each field - same keys as {@link $fields} */
private $fieldtypes;
+
+ /** all the loaded data to export */
private $exportdata;
+
+ /**
+ * callback arguments that are expected from the portfolio api
+ *
+ * @return array keyed on field name, value boolean required or not
+ */
+ public static function expected_callbackargs() {
+ return array(
+ 'id' => true,
+ 'delimiter_name' => false, // @todo true?
+ //'exporttype' => false, // @todo revisit this
+ );
+ }
+
+ /**
+ * @param array $callbackargs
+ */
+ public function __construct($callbackargs) {
+ parent::__construct($callbackargs);
+ if (empty($this->exporttype)) {
+ $this->exporttype = 'csv';
+ }
+ $this->selectedfields = array();
+ foreach ($callbackargs as $key => $value) {
+ if (strpos($key, 'field_') === 0) {
+ $this->selectedfields[] = substr($key, 6);
+ }
+ }
+ }
+
+ /**
+ * load up all the data required for this export
+ */
+ public function load_data() {
+ global $DB;
+ if (!$this->cm = get_coursemodule_from_id('data', $this->id)) {
+ throw new portfolio_caller_exception('invalidid', 'data');
+ }
+ $this->data = $DB->get_record('data', array('id' => $this->cm->instance));
+ $fieldrecords = $DB->get_records('data_fields', array('dataid'=>$this->cm->instance), 'id');
+ // populate objets for this databases fields
+ $this->fields = array();
+ foreach ($fieldrecords as $fieldrecord) {
+ $tmp = data_get_field($fieldrecord, $this->data);
+ $this->fields[] = $tmp;
+ $this->fieldtypes[] = $tmp->type;
+ }
+ $this->exportdata = data_get_exportdata($this->cm->instance, $this->fields, $this->selectedfields);
+ }
+
+ /**
+ * @todo penny later when we suport exporting to more than just csv, we may
+ * need to ask the user here if we have not already passed it
+ *
+ * @return bool
+ */
+ public function has_export_config() {
+ return false;
+ }
+
+ /**
+ * how long we expect this export to take
+ * @return one of PORTFOLIO_TIME_XX constant
+ */
+ public function expected_time() {
+ return portfolio_expected_time_db(count($this->exportdata));
+ }
+
+ /**
+ * calculate the sha1 of this export
+ *
+ * @return string
+ */
+ public function get_sha1() {
+ $str = '';
+ foreach ($this->exportdata as $data) {
+ if (is_array($data) || is_object($data)) {
+ $testkey = array_pop(array_keys($data));
+ if (is_array($data[$testkey]) || is_object($data[$testkey])) {
+ foreach ($data as $d) {
+ $str .= implode(',', (array)$d);
+ }
+ } else {
+ $str .= implode(',', (array)$data);
+ }
+ } else {
+ $str .= $data;
+ }
+ }
+ return sha1($str . ',' . $this->exporttype);
+ }
+
+ /**
+ * prepare the package for exporting off to the portfolio plugin
+ */
+ public function prepare_package() {
+ global $DB;
+ $count = count($this->exportdata);
+ $content = '';
+ $filename = '';
+ switch ($this->exporttype) {
+ case 'csv':
+ $content = data_export_csv($this->exportdata, $this->delimiter_name, $this->cm->name, $count, true);
+ $filename = clean_filename($this->cm->name . '.csv');
+ break;
+ case 'xls':
+ // todo why?
+ throw new portfolio_caller_exception('notimplemented', 'portfolio', '', 'xls');
+ $content = data_export_xls($this->exportdata, $this->cm->name, $count, true);
+ break;
+ case 'ods':
+ // todo why
+ throw new portfolio_caller_exception('notimplemented', 'portfolio', '', 'ods');
+ $content = data_export_ods($this->exportdata, $this->cm->name, $count, true);
+ break;
+ default:
+ throw new portfolio_caller_exception('notimplemented', 'portfolio', '', $this->exporttype);
+ break;
+ }
+ return $this->exporter->write_new_file(
+ $content,
+ $filename,
+ ($this->exporter->get('format') instanceof PORTFOLIO_FORMAT_RICH) // if we have associate files, this is a 'manifest'
+ );
+ // todo attachments?!
+ }
+
+ /**
+ * make sure the user can still export this database
+ * @return bool
+ */
+ public function check_permissions() {
+ return has_capability('mod/data:exportallentries', get_context_instance(CONTEXT_MODULE, $this->cm->id));
+ }
+
+ /**
+ * display name for showing in navigation
+ * @return string
+ */
+ public static function display_name() {
+ return get_string('modulename', 'data');
+ }
+
+ /**
+ * perform any necessary __wakeup duties - load up the data field class definitions
+ * @return void
+ */
+ public function __wakeup() {
+ global $CFG;
+ if (empty($CFG)) {
+ return; // too early yet
+ }
+ foreach ($this->fieldtypes as $key => $field) {
+ require_once($CFG->dirroot . '/mod/data/field/' . $field .'/field.class.php');
+ $this->fields[$key] = unserialize(serialize($this->fields[$key]));
+ }
+ }
+
+ public static function base_supported_formats() {
+ return array(PORTFOLIO_FORMAT_SPREADSHEET);
+ }
+}
+
+
+
+/**
+ * class to handle the exporting of a single entry
+ */
+class data_entry_portfolio_caller extends portfolio_module_caller_base {
+
+ /** id of entry to export */
+ protected $recordid;
+
+ /** the mdl_data record for this entry */
+ private $data;
+
+ /** selected fields to export */
+ private $selectedfields;
+
+ /** array of field objects for each field */
+ private $fields;
+
+ /** array of field types for each field - same keys as {@link $fields} */
+ private $fieldtypes;
+
+ /** type of export - single or singlefile */
+ private $exportype;
+
/**#@-*/
/**#@+ @var object */
private $singlerecord;
return array(
'id' => true,
'recordid' => false,
- 'delimiter_name' => false,
- 'exporttype' => false,
);
}
/**
*/
public function __construct($callbackargs) {
parent::__construct($callbackargs);
- if (empty($this->exporttype)) {
- $this->exporttype = 'csv';
- }
$this->selectedfields = array();
foreach ($callbackargs as $key => $value) {
if (strpos($key, 'field_') === 0) {
$this->fieldtypes[] = $tmp->type;
}
- if ($this->recordid) {
- //user has selected to export one single entry rather than the whole thing
- // which is completely different
- $this->singlerecord = $DB->get_record('data_records', array('id' => $this->recordid));
- $this->singlerecord->content = $DB->get_records('data_content', array('recordid' => $this->singlerecord->id));
- $this->exporttype = 'single';
-
- list($formats, $files) = self::formats($this->fields, $this->singlerecord);
- if (count($files) == 1 && count($this->fields) == 1) {
- $this->singlefile = $files[0];
- $this->exporttype = 'singlefile';
- } else if (count($files) > 0) {
- $this->multifiles = $files;
- }
+ $this->singlerecord = $DB->get_record('data_records', array('id' => $this->recordid));
+ $this->singlerecord->content = $DB->get_records('data_content', array('recordid' => $this->singlerecord->id));
+ $this->exporttype = 'single';
+
+ if ($singlefile = self::is_single_file_export($this->fields, $this->singlerecord)) {
+ $this->singlefile = $singlefile;
+ $this->exporttype = 'singlefile';
} else {
- // all records as csv or whatever
- $this->exportdata = data_get_exportdata($this->cm->instance, $this->fields, $this->selectedfields);
+ $this->multifiles = self::get_all_files($this->fields, $this->singlerecord);
}
}
/**
- * @todo penny later when we suport exporting to more than just csv, we may
- * need to ask the user here if we have not already passed it
- *
* @return bool
*/
public function has_export_config() {
* @return mixed
*/
public function expected_time() {
- if ($this->exporttype == 'single') {
- return PORTFOLIO_TIME_LOW;
+ if ($this->multifiles || $this->singlefile) {
+ return $this->expected_time_file();
}
- return portfolio_expected_time_db(count($this->exportdata));
+ return PORTFOLIO_TIME_LOW;
}
/**
+ * sha1 of this export
* @return string
*/
public function get_sha1() {
if ($this->exporttype == 'singlefile') {
return $this->singlefile->get_contenthash();
}
- $loopdata = $this->exportdata;
- if ($this->exporttype == 'single') {
- $loopdata = $this->singlerecord;
- }
$str = '';
- foreach ($loopdata as $data) {
+ foreach ($this->singlerecord as $data) {
if (is_array($data) || is_object($data)) {
$testkey = array_pop(array_keys($data));
if (is_array($data[$testkey]) || is_object($data[$testkey])) {
}
return sha1($str . ',' . $this->exporttype);
}
+
/**
- * @global object
+ * do whatever necessary to get the package ready to be picked up by the portfolio plugin
*/
public function prepare_package() {
global $DB;
- $count = count($this->exportdata);
$content = '';
$filename = '';
switch ($this->exporttype) {
$content = $this->exportsingle();
$filename = clean_filename($this->cm->name . '-entry.html');
break;
- case 'csv':
- $content = data_export_csv($this->exportdata, $this->delimiter_name, $this->cm->name, $count, true);
- $filename = clean_filename($this->cm->name . '.csv');
- break;
- case 'xls':
- throw new portfolio_caller_exception('notimplemented', 'portfolio', '', 'xls');
- $content = data_export_xls($this->exportdata, $this->cm->name, $count, true);
- break;
- case 'ods':
- throw new portfolio_caller_exception('notimplemented', 'portfolio', '', 'ods');
- $content = data_export_ods($this->exportdata, $this->cm->name, $count, true);
- break;
default:
throw new portfolio_caller_exception('notimplemented', 'portfolio', '', $this->exporttype);
break;
}
/**
- * @return bool
+ * make sure that the user can still export this entry
+ *
+ * @return boolean
*/
public function check_permissions() {
- return has_capability('mod/data:exportallentries', get_context_instance(CONTEXT_MODULE, $this->cm->id));
+ $c = get_context_instance(CONTEXT_MODULE, $this->cm->id);
+ return (has_capability('mod/data:exportentry', $c)
+ || ($this->singlerecord->userid == $this->exporter->get('user')->id && has_capability('mod/data:exportownentry', $c)));
}
/**
+ * nice display name for navigation
* @return string
*/
public static function display_name() {
/**
* @global object
- * @return bool|void
+ * @return void
*/
public function __wakeup() {
global $CFG;
if (empty($CFG)) {
- return true; // too early yet
+ return; // too early yet
}
foreach ($this->fieldtypes as $key => $field) {
require_once($CFG->dirroot . '/mod/data/field/' . $field .'/field.class.php');
}
/**
- * @param array $fields
- * @param object $record
- * @uses PORTFOLIO_FORMAT_PLAINHTML
- * @uses PORTFOLIO_FORMAT_RICHHTML
- * @return array
+ * helper function to retrieve the files used in this export
+ *
+ * @param array $fields the fields belonging to this data entry
+ * @param object $record the entry record
+ *
+ * @return array of $file records
*/
- public static function formats($fields, $record) {
- $formats = array(PORTFOLIO_FORMAT_PLAINHTML);
- $includedfiles = array();
- foreach ($fields as $singlefield) {
- if (is_callable(array($singlefield, 'get_file'))) {
- $includedfiles[] = $singlefield->get_file($record->id);
+ public static function get_all_files($fields, $record) {
+ static $files = array();
+ if (!array_key_exists($record->id, $files)) {
+ $files[$record->id] = array();
+ foreach ($fields as $singlefield) {
+ if (is_callable(array($singlefield, 'get_file'))) {
+ $files[$record->id][] = $singlefield->get_file($record->id);
+ }
}
}
- if (count($includedfiles) == 1 && count($fields) == 1) {
- $formats= array(portfolio_format_from_mimetype($includedfiles[0]->get_mimetype()));
- } else if (count($includedfiles) > 0) {
- $formats = array(PORTFOLIO_FORMAT_RICHHTML);
+ return $files[$record->id];
+ }
+
+ /**
+ * tiny helper function to figure out if this is a single file export
+ *
+ * @param array $fields the fields belonging to this data entry
+ * @param object $record the entry record
+ *
+ * @return mixed stored_file or false
+ */
+ public static function is_single_file_export($fields, $record) {
+ $files = self::get_all_files($fields, $record);
+ //print_object($files);
+ // print_object($fields);
+ debugging("files count was " . count($files) . " and fields count was " . count($fields));
+ if (count($files) == 1 && count($fields) == 1) {
+ return array_shift($files);
}
- return array($formats, $includedfiles);
+ return false;
}
public static function base_supported_formats() {
- return array(PORTFOLIO_FORMAT_SPREADSHEET, PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_PLAINHTML);
+ return array(PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_PLAINHTML);
}
}