Commit ecbd694c authored by Son Nguyen's avatar Son Nguyen Committed by Aaron Wells
Browse files

Enable interactive user self import via Leap2a Bug #1185209



Change-Id: Iaa122f9ab71ccf337532f49b3c1f656267047de2
Signed-off-by: default avatarSon Nguyen <sonn@catalyst.net.nz>
Signed-off-by: Aaron Wells's avatarAaron Wells <aaronw@catalyst.net.nz>
parent 5d9b633b
This diff is collapsed.
......@@ -156,3 +156,8 @@ $string['hiddenblogsnotification'] = 'Additional journal(s) have been made for y
$string['shortcutaddpost'] = 'Add a new entry to';
$string['shortcutgo'] = 'Go';
$string['shortcutnewentry'] = 'New entry';
$string['duplicatedblog'] = 'Duplicated journal';
$string['existingblogs'] = 'Existing journals';
$string['duplicatedpost'] = 'Duplicated journal entry';
$string['existingposts'] = 'Existing journal entries';
<h3 class="title">{$artefacttitle|safe}</h3>
<div class="detail">{$description|str_shorten_html:80:true|strip_tags|safe}</div>
{if count($entryblogs)}
<div class="section fullwidth">
<h2>{str tag=blog section=artefact.blog}</h2>
</div>
{foreach from=$entryblogs item=blog}
<div class="{cycle name=rows values='r0,r1'} listrow">
<div id="entryblog" class="indent1">
<div class="importcolumn importcolumn1">
<h3 class="title"><a class="blogtitle" href="" id="{$blog.id}">{$blog.title|str_shorten_text:80:true}</a></h3>
<div id="{$blog.id}_desc" class="detail hidden">{$blog.description|clean_html|safe}</div>
{if $blog.tags}
<div class="tags">
<label>{str tag=tags}:</label> {list_tags owner=0 tags=$blog.tags}
</div>
{/if}
<div class="posts">
<label>{str tag=blogpost section=artefact.blog}:</label> <a class="showposts" href="" id="{$blog.id}">{str tag=nposts section=artefact.blog arg1=count($blog.entryposts)}</a>
</div>
</div>
<div class="importcolumn importcolumn2">
{if $blog.duplicateditem}
<div class="duplicatedblog">
<label>{str tag=duplicatedblog section=artefact.blog}:</label> <a class="showduplicatedblog" href="" id="{$blog.duplicateditem.id}">{$blog.duplicateditem.title|str_shorten_text:80:true}</a>
<div id="{$blog.duplicateditem.id}_duplicatedblog" class="detail hidden">{$blog.duplicateditem.html|clean_html|safe}</div>
</div>
{/if}
{if $blog.existingitems}
<div class="existingblogs">
<label>{str tag=existingblogs section=artefact.blog}:</label>
{foreach from=$blog.existingitems item=existingitem}
<a class="showexistingblog" href="" id="{$existingitem.id}">{$existingitem.title|str_shorten_text:80:true}</a><br>
<div id="{$existingitem.id}_existingblog" class="detail hidden">{$existingitem.html|clean_html|safe}</div>
{/foreach}
</div>
{/if}
</div>
<div class="importcolumn importcolumn3">
{foreach from=$displaydecisions key=opt item=displayopt}
{if !$blog.disabled[$opt]}
<input class="blogdecision" id="{$blog.id}" type="radio" name="decision_{$blog.id}" value="{$opt}"{if $blog.decision == $opt} checked="checked"{/if}>
{$displayopt}<br>
{/if}
{/foreach}
</div>
<div class="cb"></div>
</div>
<div id="{$blog.id}_posts" class="indent2 hidden">
{foreach from=$blog.entryposts item=post}
<div id="posttitle_{$post.id}" class="{cycle name=rows values='r0,r1'} listrow {if $post.published}published{else}draft{/if}">
<div class="importcolumn importcolumn1">
<h4 class="title"><a class="posttitle" href="" id="{$post.id}">{$post.title|str_shorten_text:80:true}</a></h4>
<div id="{$post.id}_desc" class="detail hidden">
{$post.description|clean_html|safe}
</div>
<span id="poststatus{$post.id}" class="poststatus">
{if $post.published}
{str tag=published section=artefact.blog}
{else}
{str tag=draft section=artefact.blog}
{/if}
</span>
{if $post.files}
<div id="postfiles_{$post.id}">
<table class="attachments fullwidth">
<tbody>
<tr><th colspan=3>{str tag=attachedfiles section=artefact.blog}</th></tr>
{foreach from=$post.files item=file}
<tr class="{cycle values='r1,r0'}">
<td class="icon-container"><img src="{$file->icon}" alt=""></td>
<td><a href="{$WWWROOT}artefact/file/download.php?file={$file->attachment}">{$file->title}</a></td>
<td>{$file->description}</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
{/if}
<div id="postdetails_{$post.id}" class="postdetails">
{str tag=postedon section=artefact.blog} {$post.ctime}
</div>
</div>
<div class="importcolumn importcolumn2">
{if $post.duplicateditem}
<div class="duplicatedpost">
<label>{str tag=duplicatedpost section=artefact.blog}:</label> <a class="showduplicatedpost" href="" id="{$post.duplicateditem.id}">{$post.duplicateditem.title|str_shorten_text:80:true}</a>
<div id="{$post.duplicateditem.id}_duplicatedpost" class="detail hidden">{$post.duplicateditem.html|clean_html|safe}</div>
</div>
{/if}
{if $post.existingitems}
<div class="existingposts">
<label>{str tag=existingposts section=artefact.blog}:</label>
{foreach from=$post.existingitems item=existingitem}
<a class="showexistingpost" href="" id="{$existingitem.id}">{$existingitem.title|str_shorten_text:80:true}</a><br>
<div id="{$existingitem.id}_existingpost" class="detail hidden">{$existingitem.html|clean_html|safe}</div>
{/foreach}
</div>
{/if}
</div>
<div class="importcolumn importcolumn3">
{foreach from=$displaydecisions key=opt item=displayopt}
{if !$post.disabled[$opt]}
<input class="postdecision" type="radio" name="decision_{$post.id}" value="{$opt}"{if $post.decision == $opt} checked="checked"{/if}>
{$displayopt}<br>
{/if}
{/foreach}
</div>
<div class="cb"></div>
</div>
{/foreach}
</div>
<div class="cb"></div>
</div>
{/foreach}
<script type="text/javascript">
jQuery(function() {
jQuery("a.blogtitle").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_desc").toggleClass("hidden");
});
jQuery("a.posttitle").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_desc").toggleClass("hidden");
});
jQuery("a.showduplicatedblog").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_duplicatedblog").toggleClass("hidden");
});
jQuery("a.showexistingblog").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_existingblog").toggleClass("hidden");
});
jQuery("a.showduplicatedpost").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_duplicatedpost").toggleClass("hidden");
});
jQuery("a.showexistingpost").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_existingpost").toggleClass("hidden");
});
jQuery("a.showposts").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_posts").toggleClass("hidden");
});
jQuery("input.blogdecision").change(function(e) {
e.preventDefault();
if (this.value == '1') {
// The import decision for the blog is IGNORE
// Set decision for its blogposts to be IGNORE as well
jQuery("#" + this.id + "_posts input.postdecision[value=1]").prop('checked', true);
}
});
});
</script>
{/if}
......@@ -107,64 +107,121 @@ class LeapImportComment extends LeapImportArtefactPlugin {
return $strategies;
}
public static function import_using_strategy(SimpleXMLElement $entry, PluginImportLeap $importer, $strategy, array $otherentries) {
if ($strategy != self::STRATEGY_IMPORT_AS_COMMENT) {
throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
/**
* Import from entry requests for Mahara comments
*
* @param PluginImportLeap $importer
* @return updated DB
* @throw ImportException
*/
public static function import_from_requests(PluginImportLeap $importer) {
if ($entry_requests = get_records_select_array('import_entry_requests', 'importid = ? AND entrytype = ?', array($importer->get('importertransport')->get('importid'), 'comment'))) {
foreach ($entry_requests as $entry_request) {
self::create_artefact_from_request($importer, $entry_request);
}
}
$artefactmapping = array();
$artefactmapping[(string)$entry->id] = self::create_comment($entry, $importer);
return $artefactmapping;
}
/**
* Creates a comment from the given entry
* Logic to figure out how to process an entry into a comment
* Used by import_using_strategy() and add_import_entry_request_using_strategy().
*
* @param SimpleXMLElement $entry The entry to create the comment from
* @param PluginImportLeap $importer The importer
* @return array A list of artefact IDs created, to be used with the artefact mapping.
* @param SimpleXMLElement $entry
* @param PluginImportLeap $importer
* @param unknown_type $strategy
* @param array $otherentries
* @return array An array of config stuff to either create the comment, or store an import request.
* @throws ImportException
*/
private static function create_comment(SimpleXMLElement $entry, PluginImportLeap $importer) {
$createdartefacts = array();
private static function get_entry_data_using_strategy(SimpleXMLElement $entry, PluginImportLeap $importer, $strategy, array $otherentries) {
if ($strategy != self::STRATEGY_IMPORT_AS_COMMENT) {
throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
}
$comment = new ArtefactTypeComment();
$comment->set('title', (string)$entry->title);
$description = PluginImportLeap::get_entry_content($entry, $importer);
$type = isset($entry->content['type']) ? (string)$entry->content['type'] : 'text';
if ($type == 'text') {
$description = format_whitespace($description);
}
$comment->set('description', $description);
if ($published = strtotime((string)$entry->published)) {
$comment->set('ctime', $published);
if (isset($entry->author->name) && strlen($entry->author->name)) {
$authorname = (string)$entry->author->name;
}
if ($updated = strtotime((string)$entry->updated)) {
$comment->set('mtime', $updated);
else {
$author = $importer->get('usr');
}
$private = PluginImportLeap::is_correct_category_scheme($entry, $importer, 'audience', 'Private');
$comment->set('private', (int) $private);
$comment->set('owner', $importer->get('usr'));
return array(
'owner' => $importer->get('usr'),
'type' => 'comment',
'content' => array(
'title' => (string)$entry->title,
'description' => $description,
'ctime' => (string)$entry->published,
'mtime' => (string)$entry->updated,
'private' => (int)PluginImportLeap::is_correct_category_scheme($entry, $importer, 'audience', 'Private'),
'authorname' => isset($authorname) ? $authorname : null,
'author' => isset($author) ? $author : null,
'tags' => PluginImportLeap::get_entry_tags($entry),
),
);
}
if (isset($entry->author->name) && strlen($entry->author->name)) {
$comment->set('authorname', $entry->author->name);
public static function add_import_entry_request_using_strategy(SimpleXMLElement $entry, PluginImportLeap $importer, $strategy, array $otherentries) {
$config = self::get_entry_data_using_strategy($entry, $importer, $strategy, $otherentries);
return PluginImportLeap::add_import_entry_request(
$importer->get('importertransport')->get('importid'),
(string)$entry->id,
self::STRATEGY_IMPORT_AS_COMMENT,
'comment',
$config
);
}
public static function import_using_strategy(SimpleXMLElement $entry, PluginImportLeap $importer, $strategy, array $otherentries) {
$config = self::get_entry_data_using_strategy($entry, $importer, $strategy, $otherentries);
$content = $config['content'];
$comment = new ArtefactTypeComment();
$comment->set('title', $content['title']);
$comment->set('description', $content['title']);
if ($content['ctime']) {
$comment->set('ctime', $content['ctime']);
}
if ($content['mtime']) {
$comment->set('mtime', $content['mtime']);
}
$comment->set('private', $content['private']);
$comment->set('owner', $config['owner']);
if ($content['authorname']) {
$comment->set('authorname', $content['authorname']);
}
else {
$comment->set('author', $importer->get('usr'));
$comment->set('author', $content['author']);
}
if (empty(self::$tempview)) {
self::create_temporary_view($importer->get('usr'));
self::create_temporary_view($config['owner']);
}
$comment->set('onview', self::$tempview);
$comment->set('tags', PluginImportLeap::get_entry_tags($entry));
$comment->set('tags', $content['tags']);
$comment->commit();
array_unshift($createdartefacts, $comment->get('id'));
return $createdartefacts;
$artefactmapping = array();
$artefactmapping[(string)$entry->id] = array($comment->get('id'));
return $artefactmapping;
}
/**
* Add an import entry request as a comment from the given entry
*
* @param SimpleXMLElement $entry The entry to create the comment from
* @param PluginImportLeap $importer The importer
*/
private static function add_import_entry_request_comment(SimpleXMLElement $entry, PluginImportLeap $importer) {
}
......@@ -188,10 +245,23 @@ class LeapImportComment extends LeapImportArtefactPlugin {
return new ArtefactTypeComment($artefactids[0]);
}
/**
* Relate comments to the artefacts they comment on
* Attach comments to comments
*
*/
public static function setup_relationships_from_requests(PluginImportLeap $importer) {
if ($entry_requests = get_records_select_array('import_entry_requests', 'importid = ? AND entrytype = ?', array($importer->get('importertransport')->get('importid'), 'comment'))) {
foreach ($entry_requests as $entry_request) {
$entry = $importer->get_entry_by_id($entry_request->entryid);
self::setup_relationships($entry, $importer);
}
}
}
/**
* Relate comments to the artefacts they comment on
* Attach files to comments
* Attach comments to comments
*/
public static function setup_relationships(SimpleXMLElement $entry, PluginImportLeap $importer) {
$comment = null;
......@@ -221,6 +291,35 @@ class LeapImportComment extends LeapImportArtefactPlugin {
return $newartefacts;
}
/**
* Fix comments to point to the right view. Probably more
* appropriate in setup_relationships. To do that we would have
* to change that call to happen after views are created.
*/
public static function setup_view_relationships_from_request(PluginImportLeap $importer) {
if ($entry_requests = get_records_select_array('import_entry_requests', 'importid = ? AND entrytype = ?', array($importer->get('importertransport')->get('importid'), 'comment'))) {
foreach ($entry_requests as $entry_request) {
$commentids = unserialize($entry_request->artefactmapping);
$comment = new ArtefactTypeComment($commentids[0]);
if ($comment->get('onartefact')) {
continue;
}
$entry = $importer->get_entry_by_id($entry_request->entryid);
$referentid = self::get_referent_entryid($entry, $importer);
if ($viewid = $importer->get_viewid_imported_by_entryid($referentid)) {
$comment->set('onview', $viewid);
$comment->commit();
}
else {
// Nothing to link this comment to, so leave it in the temporary view.
self::$savetempview = true;
}
}
}
}
/**
* Fix comments to point to the right view. Probably more
* appropriate in setup_relationships. To do that we would have
......@@ -243,4 +342,31 @@ class LeapImportComment extends LeapImportArtefactPlugin {
self::$savetempview = true;
}
}
/**
* Render import entry requests for Mahara comments
* @param PluginImportLeap $importer
* @return HTML code for displaying comments and choosing how to import them
*/
public static function render_import_entry_requests(PluginImportLeap $importer) {
$importid = $importer->get('importertransport')->get('importid');
// Get import entry requests for Mahara comments
$entrycomments = array();
if ($iercomments = get_records_select_array('import_entry_requests', 'importid = ? AND entrytype = ?', array($importid, 'comment'))) {
foreach ($iercomments as $iercomment) {
$comment = unserialize($iercomment->entrycontent);
$comment['id'] = $iercomment->id;
$comment['decision'] = $iercomment->decision;
$comment['disabled'][PluginImport::DECISION_IGNORE] = false;
$comment['disabled'][PluginImport::DECISION_ADDNEW] = false;
$comment['disabled'][PluginImport::DECISION_APPEND] = true;
$comment['disabled'][PluginImport::DECISION_REPLACE] = true;
$entrycomments[] = $comment;
}
}
$smarty = smarty_core();
$smarty->assign_by_ref('displaydecisions', $importer->get('displaydecisions'));
$smarty->assign_by_ref('entrycomments', $entrycomments);
return $smarty->fetch('artefact:comment:import/comments.tpl');
}
}
{if count($entrycomments)}
<div class="section fullwidth">
<h2>{str tag=Comment section=artefact.comment}</h2>
</div>
{foreach from=$entrycomments item=comment}
<div class="{cycle name=rows values='r0,r1'} listrow">
<div id="entrycomment" class="indent1 fullwidth">
<div class="importcolumn importcolumn1">
<div id="{$comment.id}_desc" class="detail">{$comment.description|clean_html|safe}</div>
</div>
<div class="importcolumn importcolumn2">
</div>
<div class="importcolumn importcolumn3">
{foreach from=$displaydecisions key=opt item=displayopt}
{if !$comment.disabled[$opt]}
<input class="commentdecision" id="{$comment.id}" type="radio" name="decision_{$comment.id}" value="{$opt}"{if $comment.decision == $opt} checked="checked"{/if}>
{$displayopt}<br>
{/if}
{/foreach}
</div>
<div class="cb"></div>
</div>
</div>
{/foreach}
<script type="text/javascript">
jQuery(function() {
jQuery("a.commenttitle").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_desc").toggleClass("hidden");
});
});
</script>
{/if}
This diff is collapsed.
......@@ -796,6 +796,17 @@ abstract class ArtefactTypeFileBase extends ArtefactType {
);
}
/**
* returns duplicated file/folder artefacts
*
* @param array $values
*/
public static function get_duplicated_artefacts(array $values) {
return array();
}
public static function get_existing_artefacts(array $values) {
return array();
}
}
......
{if count($entryfiles)}
<div class="section fullwidth">
<h2>{str tag=file section=artefact.file}</h2>
</div>
{foreach from=$entryfiles item=file}
<div class="{cycle name=rows values='r0,r1'} listrow">
<div id="entryfile" class="indent1 fullwidth">
<div class="importcolumn importcolumn1">
<h3 class="title"><a class="filetitle" href="" id="{$file.id}">{$file.title|str_shorten_text:80:true}</a></h3>
<div id="{$file.id}_desc" class="detail hidden">{$file.description|clean_html|safe}</div>
{if $file.filesize}
<div class="filesize">
{$file.filesize|display_size}
</div>
{/if}
{if $file.tags}
<div class="tags">
<label>{str tag=tags}:</label> {list_tags owner=0 tags=$file.tags}
</div>
{/if}
</div>
<div class="importcolumn importcolumn2">
</div>
<div class="importcolumn importcolumn3">
{foreach from=$displaydecisions key=opt item=displayopt}
{if !$file.disabled[$opt]}
<input class="filedecision" id="{$file.id}" type="radio" name="decision_{$file.id}" value="{$opt}"{if $file.decision == $opt} checked="checked"{/if}>
{$displayopt}<br>
{/if}
{/foreach}
</div>
<div class="cb"></div>
</div>
</div>
{/foreach}
<script type="text/javascript">
jQuery(function() {
jQuery("a.filetitle").click(function(e) {
e.preventDefault();
jQuery("#" + this.id + "_desc").toggleClass("hidden");
});
});
</script>
{/if}
......@@ -142,3 +142,5 @@ $string['confirmdeletenote'] = 'This note is used in %d blocks and %d pages. If
$string['notedeleted'] = 'Note deleted';
$string['noteupdated'] = 'Note updated';
$string['html'] = 'Note';
$string['duplicatedprofilefieldvalue'] = 'Duplicated value';
$string['existingprofilefieldvalues'] = 'Existing values';
......@@ -542,6 +542,13 @@ class ArtefactTypeProfileField extends ArtefactTypeProfile {
public function render_self($options) {
return array('html' => hsc($this->title), 'javascript' => null);
}
/**
* Render the import entry request for profile fields
*/
public static function render_import_entry_request($entry_content) {
return clean_html($entry_content['title']);
}
}
class ArtefactTypeCachedProfileField extends ArtefactTypeProfileField {
......@@ -687,6 +694,13 @@ class ArtefactTypeCountry extends ArtefactTypeProfileField {
$countries = getoptions_country();
return array('html' => $countries[$this->title], 'javascript' => null);
}
/**
* Render the import entry request for country fields
*/
public static function render_import_entry_request($entry_content) {
$countries = getoptions_country();
return (isset($countries[$entry_content['title']]) ? $countries[$entry_content['title']] : '');
}
}
class ArtefactTypeHomenumber extends ArtefactTypeProfileField {}
class ArtefactTypeBusinessnumber extends ArtefactTypeProfileField {}
......
<div class="section fullwidth">
<h2>{str tag=profile section=artefact.internal}</h2>
</div>
{foreach from=$profilegroups item=profilegroup}
{if count($profilegroup.fields)}
<fieldset id="{$profilegroup.id}_fs" class="indent1 collapsible collapsed">
<legend><a id="{$profilegroup.id}" class="profilegroup" href="">{$profilegroup.legend}</a></legend>
{foreach from=$profilegroup.fields key=fieldname item=fieldvalues}
{if count($fieldvalues)}
<div id="profilefield" class="indent2">
<h4 class="profilefield">{str tag=$fieldname section=artefact.internal}</h3>
{foreach from=$fieldvalues item=fieldvalue}
<div id="profilefield_{$fieldvalue.id}" class="{cycle name=rows values='r0,r1'} listrow">
<div class="importcolumn importcolumn1">
<div id="{$fieldvalue.id}_desc" class="detail">
{$fieldvalue.html|clean_html|safe}
</div>
</div>