Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/portfolio/formats/leap2a/lib.php
Go to the documentation of this file.
00001 <?php
00029 defined('MOODLE_INTERNAL') || die();
00030 
00044 class portfolio_format_leap2a_writer {
00045 
00047     private $dom;
00049     private $feed;
00051     private $user;
00053     private $id;
00055     private $entries = array();
00056 
00063     public function __construct(stdclass $user) { // todo something else - exporter, format, etc
00064         global $CFG;
00065         $this->user = $user;
00066         $this->exporttime = time();
00067         $this->id = $CFG->wwwroot . '/portfolio/export/leap2a/' . $this->user->id . '/' . $this->exporttime;
00068 
00069         $this->dom = new DomDocument('1.0', 'utf-8');
00070 
00071         $this->feed = $this->dom->createElement('feed');
00072         $this->feed->setAttribute('xmlns', 'http://www.w3.org/2005/Atom');
00073         $this->feed->setAttribute('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
00074         $this->feed->setAttribute('xmlns:leap2', 'http://terms.leapspecs.org/');
00075         $this->feed->setAttribute('xmlns:categories', 'http://wiki.leapspecs.org/2A/categories');
00076         $this->feed->setAttribute('xmlns:portfolio', $this->id); // this is just a ns for ids of elements for convenience
00077 
00078         $this->dom->appendChild($this->feed);
00079 
00080         $this->feed->appendChild($this->dom->createElement('id', $this->id));
00081         $this->feed->appendChild($this->dom->createElement('title', get_string('leap2a_feedtitle', 'portfolio', fullname($this->user))));
00082         $this->feed->appendChild($this->dom->createElement('leap2:version', 'http://www.leapspecs.org/2010-07/2A/'));
00083 
00084 
00085         $generator = $this->dom->createElement('generator', 'Moodle');
00086         $generator->setAttribute('uri', $CFG->wwwroot);
00087         $generator->setAttribute('version', $CFG->version);
00088 
00089         $this->feed->appendChild($generator);
00090 
00091         $author = $this->dom->createElement('author');
00092         $author->appendChild($this->dom->createElement('name', fullname($this->user)));
00093         $author->appendChild($this->dom->createElement('email', $this->user->email));
00094         $author->appendChild($this->dom->CreateElement('uri', $CFG->wwwroot . '/user/view.php?id=' . $this->user->id));
00095 
00096         $this->feed->appendChild($author);
00097         // header done, we can start appending entry elements now
00098     }
00099 
00105     public function add_entry(portfolio_format_leap2a_entry $entry) {
00106         if (array_key_exists($entry->id, $this->entries)) {
00107             if (!($entry instanceof portfolio_format_leap2a_file)) {
00108                 throw new portfolio_format_leap2a_exception('leap2a_entryalreadyexists', 'portfolio', '', $entry->id);
00109             }
00110         }
00111         $this->entries[$entry->id] =  $entry;
00112         return $entry;
00113     }
00114 
00122     public function make_selection($selectionentry, $ids, $selectiontype) {
00123         $selectionid = null;
00124         if ($selectionentry instanceof portfolio_format_leap2a_entry) {
00125             $selectionid = $selectionentry->id;
00126         } else if (is_string($selectionentry)) {
00127             $selectionid = $selectionentry;
00128         }
00129         if (!array_key_exists($selectionid, $this->entries)) {
00130             throw new portfolio_format_leap2a_exception('leap2a_invalidentryid', 'portfolio', '', $selectionid);
00131         }
00132         foreach ($ids as $entryid) {
00133             if (!array_key_exists($entryid, $this->entries)) {
00134                 throw new portfolio_format_leap2a_exception('leap2a_invalidentryid', 'portfolio', '', $entryid);
00135             }
00136             $this->entries[$selectionid]->add_link($entryid, 'has_part');
00137             $this->entries[$entryid]->add_link($selectionid, 'is_part_of');
00138         }
00139         $this->entries[$selectionid]->add_category($selectiontype, 'selection_type');
00140         if ($this->entries[$selectionid]->type != 'selection') {
00141             debugging(get_string('leap2a_overwritingselection', 'portfolio', $this->entries[$selectionid]->type));
00142             $this->entries[$selectionid]->type = 'selection';
00143         }
00144     }
00145 
00152     public function link_files($entry, $files) {
00153         foreach ($files as $file) {
00154             $fileentry = new portfolio_format_leap2a_file($file->get_filename(), $file);
00155             $this->add_entry($fileentry);
00156             $entry->add_link($fileentry, 'related');
00157             $fileentry->add_link($entry, 'related');
00158         }
00159     }
00160 
00164     private function validate() {
00165         foreach ($this->entries as $entry) {
00166             // first call the entry's own validation method
00167             // which will throw an exception if there's anything wrong
00168             $entry->validate();
00169             // now make sure that all links are in place
00170             foreach ($entry->links as $linkedid => $rel) {
00171                 // the linked to entry exists
00172                 if (!array_key_exists($linkedid, $this->entries)) {
00173                     $a = (object)array('rel' => $rel->type, 'to' => $linkedid, 'from' => $entry->id);
00174                     throw new portfolio_format_leap2a_exception('leap2a_nonexistantlink', 'portfolio', '', $a);
00175                 }
00176                 // and contains a link back to us
00177                 if (!array_key_exists($entry->id, $this->entries[$linkedid]->links)) {
00178 
00179                 }
00180                 // we could later check that the reltypes were properly inverse, but nevermind for now.
00181             }
00182         }
00183     }
00184 
00191     public function to_xml() {
00192         $this->validate();
00193         foreach ($this->entries as $entry) {
00194             $entry->id = 'portfolio:' . $entry->id;
00195             $this->feed->appendChild($entry->to_dom($this->dom, $this->user));
00196         }
00197         return $this->dom->saveXML();
00198     }
00199 }
00200 
00205 class portfolio_format_leap2a_entry {
00206 
00208     public $id;
00210     public $title;
00212     public $type;
00214     public $author;
00216     public $summary;
00218     public $content;
00220     public $updated;
00222     public $published;
00223 
00225     private $requiredfields = array( 'id', 'title', 'type');
00226 
00228     private $optionalfields = array('author', 'updated', 'published', 'content', 'summary');
00229 
00231     public $links       = array();
00232 
00234     public $attachments = array();
00235 
00237     private $categories = array();
00238 
00250     public function __construct($id, $title, $type, $content=null) {
00251         $this->id    = $id;
00252         $this->title = $title;
00253         $this->type  = $type;
00254         $this->content = $this->__set('content', $content);
00255 
00256     }
00257 
00262     public function __set($field, $value) {
00263         // detect the case where content is being set to be a file directly
00264         if ($field == 'content' && $value instanceof stored_file) {
00265             throw new portfolio_format_leap2a_exception('leap2a_filecontent', 'portfolio');
00266         }
00267         if (in_array($field, $this->requiredfields) || in_array($field, $this->optionalfields)) {
00268             return $this->{$field} = $value;
00269         }
00270         throw new portfolio_format_leap2a_exception('leap2a_invalidentryfield', 'portfolio', '', $field);
00271     }
00272 
00273 
00279     public function validate() {
00280         foreach ($this->requiredfields as $key) {
00281             if (empty($this->{$key})) {
00282                 throw new portfolio_format_leap2a_exception('leap2a_missingfield', 'portfolio', '', $key);
00283             }
00284         }
00285         if ($this->type == 'selection') {
00286             if (count($this->links) == 0) {
00287                 throw new portfolio_format_leap2a_exception('leap2a_emptyselection', 'portfolio');
00288             }
00289             //TODO make sure we have a category with a scheme 'selection_type'
00290         }
00291     }
00292 
00306     public function add_link($otherentry, $reltype, $displayorder=null) {
00307         if ($otherentry instanceof portfolio_format_leap2a_entry) {
00308             $otherentry = $otherentry->id;
00309         }
00310         if ($otherentry == $this->id) {
00311             throw new portfolio_format_leap2a_exception('leap2a_selflink', 'portfolio', '', (object)array('rel' => $reltype, 'id' => $this->id));
00312         }
00313         // add on the leap2: ns if required
00314         if (!in_array($reltype, array('related', 'alternate', 'enclosure'))) {
00315             $reltype = 'leap2:' . $reltype;
00316         }
00317 
00318         $this->links[$otherentry] = (object)array('rel' => $reltype, 'order' => $displayorder);
00319 
00320         return $this;
00321     }
00322 
00334     public function add_category($term, $scheme=null, $label=null) {
00335         // "normalise" terms and set their label if they have spaces
00336         // see http://wiki.cetis.ac.uk/2009-03/LEAP2A_categories#Plain_tags for more information
00337         if (empty($scheme) && strpos($term, ' ') !== false) {
00338             $label = $term;
00339             $term = str_replace(' ', '-', $term);
00340         }
00341         $this->categories[] = (object)array(
00342             'term'   => $term,
00343             'scheme' => $scheme,
00344             'label'  => $label,
00345         );
00346     }
00347 
00357     public function to_dom(DomDocument $dom, $feedauthor) {
00358         $entry = $dom->createElement('entry');
00359         $entry->appendChild($dom->createElement('id', $this->id));
00360         $entry->appendChild($dom->createElement('title', $this->title));
00361         if ($this->author && $this->author->id != $feedauthor->id) {
00362             $author = $dom->createElement('author');
00363             $author->appendChild($dom->createElement('name', fullname($this->author)));
00364             $entry->appendChild($author);
00365         }
00366         // selectively add uncomplicated optional elements
00367         foreach (array('updated', 'published') as $field) {
00368             if ($this->{$field}) {
00369                 $date = date(DATE_ATOM, $this->{$field});
00370                 $entry->appendChild($dom->createElement($field, $date));
00371             }
00372         }
00373         if (empty($this->content)) {
00374             $entry->appendChild($dom->createElement('content'));
00375         } else {
00376             $content = $this->create_xhtmlish_element($dom, 'content', $this->content);
00377             $entry->appendChild($content);
00378         }
00379 
00380         if (!empty($this->summary)) {
00381             $summary = $this->create_xhtmlish_element($dom, 'summary', $this->summary);
00382             $entry->appendChild($summary);
00383         }
00384 
00385         $type = $dom->createElement('rdf:type');
00386         $type->setAttribute('rdf:resource', 'leap2:' . $this->type);
00387         $entry->appendChild($type);
00388 
00389         foreach ($this->links as $otherentry => $l) {
00390             $link = $dom->createElement('link');
00391             $link->setAttribute('rel',  $l->rel);
00392             $link->setAttribute('href', 'portfolio:' . $otherentry);
00393             if ($l->order) {
00394                 $link->setAttribute('leap2:display_order', $l->order);
00395             }
00396             $entry->appendChild($link);
00397         }
00398 
00399         $this->add_extra_links($dom, $entry); // hook for subclass
00400 
00401         foreach ($this->categories as $category) {
00402             $cat = $dom->createElement('category');
00403             $cat->setAttribute('term', $category->term);
00404             if ($category->scheme) {
00405                 $cat->setAttribute('scheme', 'categories:' .$category->scheme . '#');
00406             }
00407             if ($category->label && $category->label != $category->term) {
00408                 $cat->setAttribute('label', $category->label);
00409             }
00410             $entry->appendChild($cat);
00411         }
00412         return $entry;
00413     }
00414 
00427     private function create_xhtmlish_element(DomDocument $dom, $tagname, $content) {
00428         $topel = $dom->createElement($tagname);
00429         $maybexml = true;
00430         if (strpos($content, '<') === false && strpos($content, '>') === false) {
00431             $maybexml = false;
00432         }
00433         // try to load content as xml
00434         $tmp = new DomDocument();
00435         if ($maybexml && @$tmp->loadXML('<div>' . $content . '</div>')) {
00436             $topel->setAttribute('type', 'xhtml');
00437             $content = $dom->importNode($tmp->documentElement, true);
00438             $content->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
00439             $topel->appendChild($content);
00440         // if that fails, it could still be html
00441         } else if ($maybexml && @$tmp->loadHTML($content)) {
00442             $topel->setAttribute('type', 'html');
00443             $topel->nodeValue = $content;
00444             // TODO figure out how to convert this to xml
00445             // TODO because we end up with <html><body> </body></html> wrapped around it
00446             // which is annoying
00447         // either we already know it's text from the first check
00448         // or nothing else has worked anyway
00449         } else {
00450             $topel->nodeValue = $content;
00451             $topel->setAttribute('type', 'text');
00452             return $topel;
00453         }
00454         return $topel;
00455     }
00456 
00460     protected function add_extra_links() {}
00461 }
00462 
00463 
00467 class portfolio_format_leap2a_file extends portfolio_format_leap2a_entry {
00468 
00469     protected $referencedfile;
00470 
00475     public function __construct($title, stored_file $file) {
00476         $id = portfolio_format_leap2a::file_id_prefix() . $file->get_id();
00477         parent::__construct($id, $title, 'resource');
00478         $this->referencedfile = $file;
00479         $this->published = $this->referencedfile->get_timecreated();
00480         $this->updated = $this->referencedfile->get_timemodified();
00481         $this->add_category('offline', 'resource_type');
00482     }
00483 
00487     protected function add_extra_links($dom, $entry) {
00488         $link = $dom->createElement('link');
00489         $link->setAttribute('rel',  'enclosure');
00490         $link->setAttribute('href', portfolio_format_leap2a::get_file_directory() . $this->referencedfile->get_filename());
00491         $link->setAttribute('length', $this->referencedfile->get_filesize());
00492         $link->setAttribute('type', $this->referencedfile->get_mimetype());
00493         $entry->appendChild($link);
00494     }
00495 }
00496 
 All Data Structures Namespaces Files Functions Variables Enumerations