Commit 5a83c883 authored by Richard Mansfield's avatar Richard Mansfield
Browse files

Import/export changes from Penny, Nigel collected from importexport branch

parent 5777b4aa
......@@ -39,6 +39,27 @@ define('SECTION_PLUGINNAME', $pluginname);
define('SECTION_PAGE', 'pluginconfig');
safe_require($plugintype, $pluginname);
if ($sesskey = param_alphanum('sesskey', '')) {
if ($sesskey != $USER->get('sesskey')) {
throw new UserException('Invalid sesskey');
}
}
$enable = param_integer('enable', 0);
$disable = param_integer('disable', 0);
if ($disable && !call_static_method(generate_class_name($plugintype, $pluginname), 'can_be_disabled')) {
throw new UserException("Plugin $plugintype $pluginname cannot be disabled");
}
if ($enable || $disable) {
if ($plugintype == 'blocktype') {
$pluginname = blocktype_namespaced_to_single($pluginname);
}
set_field($plugintype . '_installed', 'active', $enable, 'name', $pluginname);
$SESSION->add_ok_msg(get_string('plugin' . (($enable) ? 'enabled' : 'disabled')));
redirect('/admin/extensions/plugins.php');
}
if ($plugintype == 'artefact') {
$type = param_alpha('type');
$classname = generate_artefact_class_name($type);
......
......@@ -48,13 +48,17 @@ foreach (plugin_types() as $plugin) {
}
foreach (array_keys($plugins) as $plugin) {
if (table_exists(new XMLDBTable($plugin . '_installed'))) {
if ($installed = get_records_array($plugin . '_installed')) {
if ($installed = plugins_installed($plugin, true)) {
foreach ($installed as $i) {
$key = $i->name;
if ($plugin == 'blocktype') {
$key = blocktype_single_to_namespaced($i->name, $i->artefactplugin);
}
$plugins[$plugin]['installed'][$key] = array();
safe_require($plugin, $key);
$plugins[$plugin]['installed'][$key] = array(
'active' => $i->active,
'disableable' => call_static_method(generate_class_name($plugin, $key), 'can_be_disabled'),
);
if ($plugin == 'artefact') {
$plugins[$plugin]['installed'][$key]['types'] = array();
safe_require('artefact', $key);
......
......@@ -272,7 +272,7 @@ function user_authorise($token, $useragent) {
function send_content_intent($username) {
global $REMOTEWWWROOT;
require_once('import.php');
require_once(get_config('docroot') . 'import/lib.php');
list ($user, $authinstance) = find_remote_user($username, $REMOTEWWWROOT);
if (!$user) {
......@@ -289,16 +289,7 @@ function send_content_intent($username) {
throw $e;
}
// generate a token, insert it into the queue table
$queue = new StdClass;
$queue->token = generate_token();
$queue->host = $REMOTEWWWROOT;
$queue->usr = $user->id;
$queue->queue = (int)!(Importer::import_immediately_allowed());
$queue->ready = 0;
$queue->expirytime = db_format_timestamp(time()+(60*60*24));
insert_record('import_queue', $queue);
$queue = PluginImport::create_new_queue($user->id, null, $REMOTEWWWROOT, 0);
return array(
'sendtype' => (($queue->queue) ? 'queue' : 'immediate'),
......@@ -308,7 +299,7 @@ function send_content_intent($username) {
function send_content_ready($token, $username, $format, $importdata, $fetchnow=false) {
global $REMOTEWWWROOT;
require_once('import.php');
require_once(get_config('docroot') . 'import/lib.php');
list ($user, $authinstance) = find_remote_user($username, $REMOTEWWWROOT);
if (!$user) {
......@@ -327,7 +318,7 @@ function send_content_ready($token, $username, $format, $importdata, $fetchnow=f
$queue->format = $format;
$class = null;
try {
$class = Importer::class_from_format($format);
$class = PluginImport::class_from_format($format);
} catch (Exception $e) {
throw new ImportException('Invalid format $format');
}
......@@ -352,11 +343,12 @@ function send_content_ready($token, $username, $format, $importdata, $fetchnow=f
update_record('import_queue', $queue);
$result = new StdClass;
if ($fetchnow && Importer::import_immediately_allowed()) {
if ($fetchnow && PluginImport::import_immediately_allowed()) {
// either immediately spawn a curl request to go fetch the file
$importer = Importer::create_importer($queue->id, $queue);
$importer = PluginImport::create_importer($queue->id, $queue);
$importer->prepare();
$importer->process();
$importer->cleanup();
delete_records('import_queue', 'id', $queue->id);
$result->status = true;
$result->type = 'complete';
......
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
*
* 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 3 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 mahara
* @subpackage artefact-blog-export-html
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
*
*/
defined('INTERNAL') || die();
class HtmlExportBlog extends HtmlExportArtefactPlugin {
private $blogcount;
public function dump_export_data() {
if ($blogs = get_column('artefact', 'id', 'owner', $this->exporter->get('user')->get('id'), 'artefacttype', 'blog')) {
foreach ($blogs as $blogid) {
$blog = artefact_instance_from_id($blogid);
// Create directory for storing the blog
$dirname = preg_replace('#[^a-zA-Z0-9_-]+#', '-', $blog->get('title'));
if (!check_dir_exists($this->fileroot . $dirname)) {
throw new SystemException("Couldn't create blog directory {$this->fileroot}{$dirname}");
}
$smarty = $this->exporter->get_smarty('../../../');
$smarty->assign('title', $blog->get('title'));
$rendered = $blog->render_self(array());
$smarty->assign('rendered_blog', $rendered['html']);
$content = $smarty->fetch('export:html/blog:index.tpl');
if (false === file_put_contents($this->fileroot . $dirname . '/index.html', $content)) {
throw new SystemException("Unable to create index.html for blog $blogid");
}
}
}
$this->blogcount = count($blogs);
}
public function get_summary() {
return array(
'title' => 'Blogs',
'description' => "<p>You have {$this->blogcount} blogs</p>",
);
}
public function get_summary_weight() {
return 10;
}
}
?>
{include file="export:html:header.tpl"}
<h2>Blog: {$title|escape}</h2>
{$rendered_blog}
{include file="export:html:footer.tpl"}
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
*
* 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 3 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 mahara
* @subpackage artefact-blog-export-leap
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
*
*/
defined('INTERNAL') || die();
class LeapExportElementBlogpost extends LeapExportElement {
public function add_links() {
parent::add_links();
// add on attachments
if (!$attachments = $this->artefact->get_attached_files()) {
return;
}
foreach ($attachments as &$attachment) {
$f = artefact_instance_from_id($attachment->id);
$this->add_artefact_link($f, 'has_attachment');
}
}
public function replace_content_placeholders($content) {
$content = parent::replace_content_placeholders($content, 'ARTEFACT(DL|VIEW)LINK');
return $content;
}
public function assign_smarty_vars() {
parent::assign_smarty_vars();
$this->smarty->assign('contenttype', 'xhtml');
}
public function get_content() {
//$rendered = $this->artefact->render_base(array('icons' => false));
//$rendered = $rendered['html'];
//return $this->replace_content_placeholders(clean_html($rendered));
// Probably need replace content placeholders!
return clean_html($this->artefact->get('description'));
}
public function get_categories() {
if (!$this->artefact->get('published')) {
return array(
array(
'scheme' => 'readiness',
'term' => 'Unready',
)
);
}
return array();
}
}
class LeapExportElementBlog extends LeapExportElement {
public function get_leap_type() {
return 'selection';
}
public function get_categories() {
return array(
array(
'scheme' => 'selection_type',
'term' => 'Blog',
)
);
}
public function assign_smarty_vars() {
parent::assign_smarty_vars();
$this->smarty->assign('contenttype', 'xhtml');
}
public function get_content() {
return clean_html($this->artefact->get('description'));
}
}
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
*
* 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 3 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 mahara
* @subpackage artefact-blog-import-leap
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
*
*/
defined('INTERNAL') || die();
/**
* Implements LEAP2A import of blog related entries into Mahara
*
* For more information about LEAP blog importing, see:
* http://wiki.mahara.org/Developer_Area/Import%2f%2fExport/LEAP_Import/Blog_Artefact_Plugin
*
* TODO:
* - Get entries that feel they're part of the blog, not just entries the blog feels are part of it
* - Import raw ATOM feed entries as blog posts
* - Provide a default strategy for importing anything into a 'miscellaneous' blog
* - Handle importing things that don't have inline entry content into a blogpost
*/
class LeapImportBlog extends LeapImportArtefactPlugin {
/**
* Import an entry as a blog, with associated blog posts and attachments
*/
const STRATEGY_IMPORT_AS_BLOG = 1;
/**
* Import entry as an simple blog post into a catch-all blog
*/
const STRATEGY_IMPORT_AS_ENTRY = 2;
public static function get_import_strategies_for_entry(SimpleXMLElement $entry, PluginImport $importer) {
$strategies = array();
// TODO: when the xpath has an error in it, count(error) == 1 also.. so should check return type
$correctrdftype = count($entry->xpath('rdf:type['
. $importer->curie_xpath('@rdf:resource', PluginImportLeap::NS_LEAPTYPE, 'selection') . ']')) == 1;
$correctcategoryscheme = count($entry->xpath('a:category[('
. $importer->curie_xpath('@scheme', PluginImportLeap::NS_CATEGORIES, 'selection_type#') . ') and @term="Blog"]')) == 1;
if ($correctrdftype && $correctcategoryscheme) {
$otherrequiredentries = array();
// Get entries that this blog feels are a part of it
foreach ($entry->link as $link) {
if ($importer->curie_equals($link['rel'], PluginImportLeap::NS_LEAP, 'has_part') && isset($link['href'])) {
$otherrequiredentries[] = (string)$link['href'];
}
}
// TODO: Get entries that feel they should be a part of this blog.
// We can compare the lists and perhaps warn if they're different
// $otherentries = $importer->xml->xpath('//a:feed/a:entry/a:link[@rel="leap:is_part_of" and @href="' . $entryid . '"]/../a:id');
$otherrequiredentries = array_unique($otherrequiredentries);
$strategies[] = array(
'strategy' => self::STRATEGY_IMPORT_AS_BLOG,
'score' => 100,
'other_required_entries' => $otherrequiredentries,
);
}
else {
// The blog can import any entry as a literal blog post
$strategies[] = array(
'strategy' => self::STRATEGY_IMPORT_AS_ENTRY,
'score' => 10,
'other_required_entries' => array(),
);
}
return $strategies;
}
public static function import_using_strategy(SimpleXMLElement $entry, PluginImport $importer, $strategy, array $otherentries) {
$artefactmapping = array();
switch ($strategy) {
case self::STRATEGY_IMPORT_AS_BLOG:
// First, the blog
$blog = new ArtefactTypeBlog();
$blog->set('title', (string)$entry->title);
$blog->set('description', PluginImportLeap::get_entry_content($entry, $importer));
$blog->set('owner', $importer->get('usr'));
if ($published = strtotime((string)$entry->published)) {
$blog->set('ctime', $published);
}
if ($updated = strtotime((string)$entry->updated)) {
$blog->set('mtime', $updated);
}
$blog->set('tags', PluginImportLeap::get_entry_tags($entry));
$blog->commit();
$artefactmapping[(string)$entry->id] = array($blog->get('id'));
// Then, the blog posts
foreach ($otherentries as $entryid) {
$blogentry = $importer->get_entry_by_id($entryid);
if (!$blogentry) {
// TODO: what to do here? Also - should this be checked here or earlier?
$importer->trace("WARNING: Blog $entry->id claims to have part $entryid which doesn't exist");
continue;
}
$artefactmapping[$entryid] = self::create_blogpost($blogentry, $importer, $blog->get('id'));
}
break;
case self::STRATEGY_IMPORT_AS_ENTRY:
$blogid = self::ensure_catchall_blog($importer);
$artefactmapping[(string)$entry->id] = self::create_blogpost($entry, $importer, $blogid);
break;
default:
throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
}
return $artefactmapping;
}
/**
* Attaches files to blog posts
*
* We look at the leap relationships to add attachments. Currently this
* looks explicitly for the has_attachment relationship.
*
* If importing an entry resulted in importing a new file (caused by the
* entry having out-of-line content), we attach that file to the entry.
*/
public static function setup_relationships(SimpleXMLElement $entry, PluginImport $importer, $strategy, array $otherentries) {
switch ($strategy) {
case self::STRATEGY_IMPORT_AS_BLOG:
foreach ($otherentries as $entryid) {
$blogpostentry = $importer->get_entry_by_id($entryid);
// Get all attachments this blogpost things are attached to it
// TODO: get all entries that think they're attached to the blogpost.
// I think we can only look for files, Mahara doesn't understand
// attaching something that isn't a file to a blogpost
foreach ($blogpostentry->link as $blogpostlink) {
$blogpost = null;
if ($importer->curie_equals($blogpostlink['rel'], PluginImportLeap::NS_LEAP, 'has_attachment') && isset($blogpostlink['href'])) {
if (!$blogpost) {
$artefactids = $importer->get_artefactids_imported_by_entryid((string)$blogpostentry->id);
$blogpost = new ArtefactTypeBlogPost($artefactids[0]);
}
$importer->trace("Attaching file $blogpostlink[href] to blog post $blogpostentry->id", PluginImportLeap::LOG_LEVEL_VERBOSE);
$artefactids = $importer->get_artefactids_imported_by_entryid((string)$blogpostlink['href']);
$blogpost->attach_file($artefactids[0]);
}
if ($blogpost) {
$blogpost->commit();
}
}
self::setup_outoflinecontent_relationship($blogpostentry, $importer);
}
break;
case self::STRATEGY_IMPORT_AS_ENTRY:
self::setup_outoflinecontent_relationship($blogpostentry, $importer);
break;
default:
throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
}
}
/**
* Creates a catch-all blog if one doesn't exist already
*
* @param PluginImportLeap $importer The importer
* @return int The artefact ID of the catch-all blog
*/
private static function ensure_catchall_blog(PluginImportLeap $importer) {
static $blogid = null;
if (is_null($blogid)) {
$time = time(); // TODO maybe the importer will get a time field to record time of import
$blog = new ArtefactTypeBlog();
// TODO: i18n
$title = $importer->get('xml')->xpath('//a:feed/a:title');
$blog->set('title', 'Data imported from ' . (string)$title[0]);
$blog->set('description', 'Entries imported from a LEAP export, that were not abel to be imported elsewhere');
$blog->set('owner', $importer->get('usr'));
$blog->set('ctime', $time);
$blog->set('mtime', $time);
$blog->commit();
$blogid = $blog->get('id');
}
return $blogid;
}
/**
* Creates a blogpost from the given entry
*
* @param SimpleXMLElement $entry The entry to create the blogpost from
* @param PluginImportLeap $importer The importer
* @param int $blogid The blog in which to put the post
* @return array A list of artefact IDs created, to be used with the artefact mapping.
* There will either be one (the blogpost ID), or two. If there is two, the
* second one will be the ID of the file created to hold the out-of-line
* content associated with the blogpost
*/
private static function create_blogpost(SimpleXMLElement $entry, PluginImportLeap $importer, $blogid) {
$createdartefacts = array();
$blogpost = new ArtefactTypeBlogPost();
$blogpost->set('title', (string)$entry->title);
// If the entry has out of line content, we import that separately as a
// file and set the content to refer to it
if (isset($entry->content['src']) && isset($entry->content['type'])) {
$file = LeapImportFile::create_file($entry, $importer);
$createdartefacts[] = $file->get('id');
$content = '<a href="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $fileid . '"'
. ' title="' . hsc($file->get('title')) . '">';
if (is_image_mime_type($file->get('filetype'))) {
$content .= '<img src="' . get_config('wwwroot')
. 'artefact/file/download.php?file=' . $file->get('id') . '&amp;maxwidth=500&amp;maxheight=500"'
. ' alt="' . hsc($file->get('title')) . '">';
}
$content .= '</a>';
$blogpost->set('description', $content);
}
else {
$blogpost->set('description', PluginImportLeap::get_entry_content($entry, $importer));
}
if ($published = strtotime((string)$entry->published)) {
$blogpost->set('ctime', $published);
}
if ($updated = strtotime((string)$entry->updated)) {
$blogpost->set('mtime', $updated);
}
$draftpost = count($entry->xpath('a:category[('
. $importer->curie_xpath('@scheme', PluginImportLeap::NS_CATEGORIES, 'readiness#')
. ') and @term="Unready"]')) == 1;
$blogpost->set('published', $draftpost ? 0 : 1);
$blogpost->set('owner', $importer->get('usr'));
$blogpost->set('parent', $blogid);
$blogpost->set('tags', PluginImportLeap::get_entry_tags($entry));
$blogpost->commit();
array_unshift($createdartefacts, $blogpost->get('id'));
return $createdartefacts;
}
/**
* Checks to see if a blogpost had out-of-line content, and if it did,
* attaches the generated file to it
*
* @param SimpleXMLElement $entry The entry to check
* @param PluginImportLeap $importer The importer
*/
private static function setup_outoflinecontent_relationship(SimpleXMLElement $entry, PluginImportLeap $importer) {
$artefactids = $importer->get_artefactids_imported_by_entryid((string)$entry->id);
if (count($artefactids) == 2) {
// In this case, a file was created as a result of
// importing a blog entry with out-of-line content. We
// attach the file to this post.
$blogpost = new ArtefactTypeBlogPost($artefactids[0]);
$blogpost->attach_file($artefactids[1]);
$blogpost->commit();
}
}
}
?>
......@@ -447,8 +447,8 @@ class ArtefactTypeBlogPost extends ArtefactType {
foreach ($attachments as &$attachment) {
$f = artefact_instance_from_id($attachment->id);
$attachment->size = $f->describe_size();
$attachment->iconpath = $f->get_icon(array('id' => $attachment->id, 'viewid' => $options['viewid']));
$attachment->viewpath = get_config('wwwroot') . 'view/artefact.php?artefact=' . $attachment->id . '&view=' . $options['viewid'];
$attachment->iconpath = $f->get_icon(array('id' => $attachment->id, 'viewid' => isset($options['viewid']) ? $options['viewid'] : 0));
$attachment->viewpath = get_config('wwwroot') . 'view/artefact.php?artefact=' . $attachment->id . '&view=' . (isset($options['viewid']) ? $options['viewid'] : 0);
$attachment->downloadpath = get_config('wwwroot') . 'artefact/file/download.php?file=' . $attachment->id;
if (isset($options['viewid'])) {
$attachment->downloadpath .= '&id=' . $options['viewid'];
......
......@@ -10,7 +10,7 @@
<tr><th colspan="2">{str tag=attachedfiles section=artefact.blog}</th></tr>
{foreach from=$attachments item=item}
<tr class="r{cycle values=1,0}">
<td style="width: 22px;"><img src="{$item->iconpath|escape}" alt=""></td>
{if $icons}<td style="width: 22px;"><img src="{$item->iconpath|escape}" alt=""></td>{/if}
<td><a href="{$item->viewpath|escape}">{$item->title|escape}</a> ({$item->size|escape}) - <strong><a href="{$item->downloadpath|escape}">{str tag=Download section=artefact.file}</a></strong>
<br><strong>{$item->description|escape}</strong></td>