diff --git a/lang/en/portfolio.php b/lang/en/portfolio.php index 8e6c83b4c2e..ccd52e95304 100644 --- a/lang/en/portfolio.php +++ b/lang/en/portfolio.php @@ -121,6 +121,7 @@ $string['invaliduserproperty'] = 'Could not find that user config property ({$a- $string['leap2a_emptyselection'] = 'Required value not selected'; $string['leap2a_entryalreadyexists'] = 'You tried to add a Leap2A entry with an id ({$a}) that already exists in this feed'; $string['leap2a_feedtitle'] = 'Leap2A export from Moodle for {$a}'; +$string['leap2a_filecontent'] = 'Tried to set the content of a leap2a entry to a file, rather than using the file sublcass'; $string['leap2a_invalidentryfield'] = 'You tried to set an entry field that didn\'t exist ({$a}) or you can\'t set directly'; $string['leap2a_invalidentryid'] = 'You tried to access an entry by an id that didn\'t exist ({$a})'; $string['leap2a_missingfield'] = 'Required Leap2A entry field {$a} missing'; diff --git a/lib/portfolio/formats.php b/lib/portfolio/formats.php index ef38ab8a024..17e7873b746 100644 --- a/lib/portfolio/formats.php +++ b/lib/portfolio/formats.php @@ -235,20 +235,27 @@ class portfolio_format_leap2a extends portfolio_format_rich { return 'files/'; } + public static function file_id_prefix() { + return 'storedfile'; + } + /** * return the link to a file * * @param stored_file $file * @param array $options can contain the same as normal, with the addition of: - * entry => whether the file is a LEAP2A entry or just a bundled file (default false) + * entry => whether the file is a LEAP2A entry or just a bundled file (default true) */ public static function file_output($file, $options=null) { $id = ''; if (!is_array($options)) { $options = array(); } + if (!array_key_exists('entry', $options)) { + $options['entry'] = true; + } if (!empty($options['entry'])) { - $path = 'portfolio:file' . $file->get_id; + $path = 'portfolio:' . self::file_id_prefix() . $file->get_id(); } else { $path = self::get_file_directory() . $file->get_filename(); } diff --git a/lib/portfolio/formats/leap2a/lib.php b/lib/portfolio/formats/leap2a/lib.php index 0641a460e88..f705b674ebc 100644 --- a/lib/portfolio/formats/leap2a/lib.php +++ b/lib/portfolio/formats/leap2a/lib.php @@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die(); * should be used like: * * $writer = portfolio_format_leap2a::leap2a_writer($USER); - * $entry = new portfolio_format_leap2a_entry('forumpost6', $title, 'leaptype', 'somecontent') + * $entry = new portfolio_format_leap2a_entry('forumpost6', $title, 'leap2', 'somecontent') * $entry->add_link('something', 'has_part')->add_link('somethingelse', 'has_part'); * .. etc * $writer->add_entry($entry); @@ -71,15 +71,16 @@ class portfolio_format_leap2a_writer { $this->feed = $this->dom->createElement('feed'); $this->feed->setAttribute('xmlns', 'http://www.w3.org/2005/Atom'); $this->feed->setAttribute('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); - $this->feed->setAttribute('xmlns:leap', 'http://wiki.cetis.ac.uk/2009-03/LEAP2A_predicates#'); - $this->feed->setAttribute('xmlns:leaptype', 'http://wiki.cetis.ac.uk/2009-03/LEAP2A_types#'); - $this->feed->setAttribute('xmlns:categories', 'http://wiki.cetis.ac.uk/2009-03/LEAP2A_categories/'); + $this->feed->setAttribute('xmlns:leap2', 'http://terms.leapspecs.org/'); + $this->feed->setAttribute('xmlns:categories', 'http://wiki.leapspecs.org/2A/categories'); $this->feed->setAttribute('xmlns:portfolio', $this->id); // this is just a ns for ids of elements for convenience $this->dom->appendChild($this->feed); $this->feed->appendChild($this->dom->createElement('id', $this->id)); $this->feed->appendChild($this->dom->createElement('title', get_string('leap2a_feedtitle', 'portfolio', fullname($this->user)))); + $this->feed->appendChild($this->dom->createElement('leap2:version', 'http://www.leapspecs.org/2010-07/2A/')); + $generator = $this->dom->createElement('generator', 'Moodle'); $generator->setAttribute('uri', $CFG->wwwroot); @@ -103,7 +104,9 @@ class portfolio_format_leap2a_writer { */ public function add_entry(portfolio_format_leap2a_entry $entry) { if (array_key_exists($entry->id, $this->entries)) { - throw new portfolio_format_leap2a_exception('leap2a_entryalreadyexists', 'portfolio', '', $entry->id); + if (!($entry instanceof portfolio_format_leap2a_file)) { + throw new portfolio_format_leap2a_exception('leap2a_entryalreadyexists', 'portfolio', '', $entry->id); + } } $this->entries[$entry->id] = $entry; return $entry; @@ -140,6 +143,21 @@ class portfolio_format_leap2a_writer { } } + /** + * helper function to link some stored_files into the feed and link them to a particular entry + * + * @param portfolio_format_leap2a_entry $entry the entry to link the files into + * @param array $files array of stored_files to link + */ + public function link_files($entry, $files) { + foreach ($files as $file) { + $fileentry = new portfolio_format_leap2a_file($file->get_filename(), $file); + $this->add_entry($fileentry); + $entry->add_link($fileentry, 'related'); + $fileentry->add_link($entry, 'related'); + } + } + /** * validate the feed and all entries */ @@ -196,18 +214,13 @@ class portfolio_format_leap2a_entry { public $author; /** summary - for split long content **/ public $summary; - /** main content of the entry. can be html,text,xhtml or a stored_file **/ + /** main content of the entry. can be html,text,or xhtml. for a stored_file, use portfolio_format_leap2a_file **/ public $content; /** updated date - unix timestamp */ public $updated; /** published date (ctime) - unix timestamp */ public $published; - /** used internally for file content **/ - private $contentsrc; - /** used internally for file content **/ - private $referencedfile; - /** the required fields for a leap2a entry */ private $requiredfields = array( 'id', 'title', 'type'); @@ -232,7 +245,7 @@ class portfolio_format_leap2a_entry { * This must be unique to the entire feed. * @param string $title title of the entry. This is pure atom. * @param string $type the leap type of this entry. - * @param mixed $content the content of the entry. string (xhtml/html/text) or stored_file + * @param mixed $content the content of the entry. string (xhtml/html/text) */ public function __construct($id, $title, $type, $content=null) { $this->id = $id; @@ -249,7 +262,7 @@ class portfolio_format_leap2a_entry { public function __set($field, $value) { // detect the case where content is being set to be a file directly if ($field == 'content' && $value instanceof stored_file) { - return $this->set_content_file($value); + throw new portfolio_format_leap2a_exception('leap2a_filecontent', 'portfolio'); } if (in_array($field, $this->requiredfields) || in_array($field, $this->optionalfields)) { return $this->{$field} = $value; @@ -257,23 +270,6 @@ class portfolio_format_leap2a_entry { throw new portfolio_format_leap2a_exception('leap2a_invalidentryfield', 'portfolio', '', $field); } - /** - * sets the content of this entry to have a source - * this will take care of namespacing the filepath - * to the final path in the resulting zip file. - * - * @param stored_file $file the file to link to - * @param boolean $overridetype (default true) will set the entry rdf type to resource, - * overriding what was previously set. - * will be ignored if type is empty already - */ - public function set_content_file(stored_file $file, $overridetype=true) { - $this->contentsrc = portfolio_format_leap2a::get_file_directory() . $file->get_filename(); - if (empty($overridetype) || empty($this->type)) { - $this->type = 'resource'; - } - $this->referencedfile = $file; - } /** * validate this entry. @@ -301,7 +297,7 @@ class portfolio_format_leap2a_entry { * http://wiki.cetis.ac.uk/2009-03/LEAP2A_relationships * * @param mixed $otherentry portfolio_format_leap2a_entry or its id - * @param string $reltype (no leap: ns required) + * @param string $reltype (no leap2: ns required) * * @return the current entry object. This is so that these calls can be chained * eg $entry->add_link('something6', 'has_part')->add_link('something7', 'has_part'); @@ -314,9 +310,9 @@ class portfolio_format_leap2a_entry { if ($otherentry == $this->id) { throw new portfolio_format_leap2a_exception('leap2a_selflink', 'portfolio', '', (object)array('rel' => $reltype, 'id' => $this->id)); } - // add on the leap: ns if required + // add on the leap2: ns if required if (!in_array($reltype, array('related', 'alternate', 'enclosure'))) { - $reltype = 'leap:' . $reltype; + $reltype = 'leap2:' . $reltype; } $this->links[$otherentry] = (object)array('rel' => $reltype, 'order' => $displayorder); @@ -324,26 +320,6 @@ class portfolio_format_leap2a_entry { return $this; } - /** - * add an attachment to the feed. - * adding the file to the files area has to be handled outside this class separately. - * - * @param stored_file $file the file to add - */ - public function add_attachment(stored_file $file) { - $this->attachments[$file->get_id()] = $file; - } - - /** - * helper function to add a bunch of files at the same time - * useful for passing $this->multifiles straight through from the portfolio_caller - */ - public function add_attachments(array $files) { - foreach ($files as $file) { - $this->add_attachment($file); - } - } - /** * add a category to this entry * http://wiki.cetis.ac.uk/2009-03/LEAP2A_categories @@ -394,13 +370,7 @@ class portfolio_format_leap2a_entry { $entry->appendChild($dom->createElement($field, $date)); } } - // deal with referenced files first since it's simple - if ($this->contentsrc) { - $content = $dom->createElement('content'); - $content->setAttribute('src', $this->contentsrc); - $content->setAttribute('type', $this->referencedfile->get_mimetype()); - $entry->appendChild($content); - } else if (empty($this->content)) { + if (empty($this->content)) { $entry->appendChild($dom->createElement('content')); } else { $content = $this->create_xhtmlish_element($dom, 'content', $this->content); @@ -413,7 +383,7 @@ class portfolio_format_leap2a_entry { } $type = $dom->createElement('rdf:type'); - $type->setAttribute('rdf:resource', 'leaptype:' . $this->type); + $type->setAttribute('rdf:resource', 'leap2:' . $this->type); $entry->appendChild($type); foreach ($this->links as $otherentry => $l) { @@ -421,17 +391,13 @@ class portfolio_format_leap2a_entry { $link->setAttribute('rel', $l->rel); $link->setAttribute('href', 'portfolio:' . $otherentry); if ($l->order) { - $link->setAttribute('leap:display_order', $l->order); + $link->setAttribute('leap2:display_order', $l->order); } $entry->appendChild($link); } - foreach ($this->attachments as $id => $file) { - $link = $dom->createElement('link'); - $link->setAttribute('rel', 'enclosure'); - $link->setAttribute('href', portfolio_format_leap2a::get_file_directory() . $file->get_filename()); - $link->setAttribute('length', $file->get_filesize()); - $entry->appendChild($link); - } + + $this->add_extra_links($dom, $entry); // hook for subclass + foreach ($this->categories as $category) { $cat = $dom->createElement('category'); $cat->setAttribute('term', $category->term); @@ -487,4 +453,44 @@ class portfolio_format_leap2a_entry { } return $topel; } + + /** + * hook function for subclasses to add extra links (like for files) + */ + protected function add_extra_links() {} } + + +/** + * subclass of entry, purely for dealing with files + */ +class portfolio_format_leap2a_file extends portfolio_format_leap2a_entry { + + protected $referencedfile; + + /** + * overridden constructor to set up the file. + * + */ + public function __construct($title, stored_file $file) { + $id = portfolio_format_leap2a::file_id_prefix() . $file->get_id(); + parent::__construct($id, $title, 'resource'); + $this->referencedfile = $file; + $this->published = $this->referencedfile->get_timecreated(); + $this->updated = $this->referencedfile->get_timemodified(); + $this->add_category('offline', 'resource_type'); + } + + /** + * implement the hook to add extra links to attach the file in an enclosure + */ + protected function add_extra_links($dom, $entry) { + $link = $dom->createElement('link'); + $link->setAttribute('rel', 'enclosure'); + $link->setAttribute('href', portfolio_format_leap2a::get_file_directory() . $this->referencedfile->get_filename()); + $link->setAttribute('length', $this->referencedfile->get_filesize()); + $link->setAttribute('type', $this->referencedfile->get_mimetype()); + $entry->appendChild($link); + } +} + diff --git a/mod/assignment/locallib.php b/mod/assignment/locallib.php index 687bcd4e3ba..d6701bb582e 100644 --- a/mod/assignment/locallib.php +++ b/mod/assignment/locallib.php @@ -98,15 +98,11 @@ class assignment_portfolio_caller extends portfolio_module_caller_base { $baseid = 'assignment' . $this->assignment->assignment->assignmenttype . $this->assignment->assignment->id . 'submission'; $entryids = array(); foreach ($files as $file) { - $id = $baseid . $file->get_id(); - $entry = new portfolio_format_leap2a_entry($id, $file->get_filename(), 'resource', $file); - $entry->add_category('offline', 'resource_type'); - $entry->published = $file->get_timecreated(); - $entry->updated = $file->get_timemodified(); + $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[] = $id; + $entryids[] = $entry->id; } if (count($files) > 1) { // if we have multiple files, they should be grouped together into a folder diff --git a/mod/assignment/type/online/assignment.class.php b/mod/assignment/type/online/assignment.class.php index c2881bcb5ef..d70781e114c 100644 --- a/mod/assignment/type/online/assignment.class.php +++ b/mod/assignment/type/online/assignment.class.php @@ -311,9 +311,9 @@ class assignment_online extends assignment_base { $entry->author = $user; $leapwriter->add_entry($entry); if ($files = $exporter->get('caller')->get('multifiles')) { + $leapwriter->link_files($entry, $files, 'assignmentonline' . $this->assignment->id . 'file'); foreach ($files as $f) { $exporter->copy_existing_file($f); - $entry->add_attachment($f); } } $exporter->write_new_file($leapwriter->to_xml(), $exporter->get('format')->manifest_name(), true); diff --git a/mod/data/locallib.php b/mod/data/locallib.php index 5198af699b0..807999ba0a0 100644 --- a/mod/data/locallib.php +++ b/mod/data/locallib.php @@ -203,9 +203,7 @@ class data_portfolio_caller extends portfolio_module_caller_base { $entry->author = $users[$record->userid]; } $ids[] = $entry->id; - foreach ($files as $file) { - $entry->add_attachment($file); - } + $leapwriter->link_files($entry, $files, 'dataentry' . $record->id . 'file'); $leapwriter->add_entry($entry); } } diff --git a/mod/forum/locallib.php b/mod/forum/locallib.php index ba07ed8589e..e7082b8b1a4 100644 --- a/mod/forum/locallib.php +++ b/mod/forum/locallib.php @@ -181,11 +181,7 @@ class forum_portfolio_caller extends portfolio_module_caller_base { if ($this->attachment) { // simplest case first - single file attachment $this->copy_files(array($this->singlefile), $this->attachment); if ($writingleap) { // if we're writing leap, make the manifest to go along with the file - $entry = new portfolio_format_leap2a_entry('forumattachment' . $this->singlefile->get_id(), - $this->singlefile->get_filename(), 'resource', $this->singlefile); - $entry->published = $this->singlefile->get_timecreated(); - $entry->updated = $this->singlefile->get_timemodified(); - $entry->add_category('offline', 'resource_type'); + $entry = new portfolio_format_leap2a_file($this->singlefile->get_filename(), $this->singlefile); $leapwriter->add_entry($entry); return $this->exporter->write_new_file($leapwriter->to_xml(), $this->exporter->get('format')->manifest_name(), true); } @@ -251,10 +247,7 @@ class forum_portfolio_caller extends portfolio_module_caller_base { $entry->updated = $post->modified; $entry->author = $post->author; if (is_array($this->keyedfiles) && array_key_exists($post->id, $this->keyedfiles) && is_array($this->keyedfiles[$post->id])) { - foreach ($this->keyedfiles[$post->id] as $file) { - // copying the file into the package area is handled elsewhere - $entry->add_attachment($file); - } + $leapwriter->link_files($entry, $this->keyedfiles[$post->id], 'forumpost' . $post->id . 'attachment'); } $entry->add_category('web', 'resource_type'); $leapwriter->add_entry($entry); diff --git a/mod/glossary/locallib.php b/mod/glossary/locallib.php index e8a662dee51..f464642079a 100644 --- a/mod/glossary/locallib.php +++ b/mod/glossary/locallib.php @@ -155,7 +155,7 @@ class glossary_full_portfolio_caller extends portfolio_module_caller_base { $entry->published = $e->timecreated; $entry->updated = $e->timemodified; if (!empty($this->keyedfiles[$e->id])) { - $entry->add_attachments($this->keyedfiles[$e->id]); + $writer->link_files($entry, $this->keyedfiles[$e->id], 'glossaryentry' . $e->id . 'file'); foreach ($this->keyedfiles[$e->id] as $file) { $this->exporter->copy_existing_file($file); } @@ -259,7 +259,7 @@ class glossary_entry_portfolio_caller extends portfolio_module_caller_base { $context = get_context_instance(CONTEXT_MODULE, $maincm->id); } } - $this->aliases = $DB->get_records('glossary_alias', array('entryid'=>$this->entryid)); + $this->aliases = $DB->get_record('glossary_alias', array('entryid'=>$this->entryid)); $fs = get_file_storage(); $this->multifiles = array_merge( $fs->get_area_files($context->id, 'mod_glossary', 'attachment', $this->entry->id, "timemodified", false), @@ -315,7 +315,7 @@ class glossary_entry_portfolio_caller extends portfolio_module_caller_base { $entry->published = $this->entry->timecreated; $entry->updated = $this->entry->timemodified; if ($this->multifiles) { - $entry->add_attachments($this->multifiles); + $writer->link_files($entry, $this->multifiles, 'glossaryentry' . $this->entry->id . 'file'); } if ($this->categories) { foreach ($this->categories as $cat) { @@ -374,9 +374,11 @@ class glossary_entry_portfolio_caller extends portfolio_module_caller_base { public static function entry_content($course, $cm, $glossary, $entry, $aliases, $format) { global $OUTPUT, $DB; $entry = clone $entry; + $context = get_context_instance(CONTEXT_MODULE, $cm->id); $options = new object(); $options->para = false; $options->trusted = $entry->definitiontrust; + $options->context = $context; $output = '
'; $key = (count($aliases) == 1) ? 'alias' : 'aliases'; $output .= get_string($key, 'glossary') . ': '; foreach ($aliases as $alias) { $output .= s($alias) . ','; } - $output .= substr($output, 0, -1); + $output = substr($output, 0, -1); $output .= ' |