Commit 77527e58 authored by Son Nguyen's avatar Son Nguyen Committed by Gerrit Code Review

Enable embedded images in view description. Bug 1045138

- Add new resourcetype 'description' for the view
description
- Display embedded images in view description
- Update embedded image urls when copy and export/import view

Change-Id: I8088be317ddb1659de2d091a2940bea6665e4af0
Signed-off-by: default avatarSon Nguyen <son.nguyen@catalyst.net.nz>
parent 8fb9c3f2
......@@ -39,7 +39,13 @@ if ($viewid && $fileid) {
$ancestors = $file->get_item_ancestors();
$artefactok = false;
if (artefact_in_view($file, $viewid)) {
// Check if the artefact is embedded in the page description
$resourceid = param_integer('description', null);
if ($resourceid && $file instanceof ArtefactTypeImage) {
$artefactok = EmbeddedImage::can_see_embedded_image($fileid, 'description', $resourceid);
}
if (!$artefactok && artefact_in_view($file, $viewid)) {
$artefactok = true;
}
// Check to see if the artefact has a parent that is allowed to be in this view.
......
......@@ -119,31 +119,10 @@ class PluginBlocktypeText extends SystemBlocktype {
* See more PluginBlocktype::import_rewrite_blockinstance_extra_config_leap()
*/
public static function import_rewrite_blockinstance_extra_config_leap(array $artefactids, array $configdata) {
// Find all possible embedded image artefact ids in the import configdata
$ids = array();
if (isset($configdata['text'])
&& preg_match_all(
'#<img([^>]+)src="' . get_config('wwwroot')
. 'artefact/file/download.php\?file=([0-9]+)&embedded=1([^"]+)"#',
$configdata['text'],
$ids)
) {
$ids = $ids[2];
$regexp = array();
$replacetext = array();
foreach ($ids as $id) {
if (!empty($artefactids["portfolio:artefact$id"])) {
// Change the old image id to the new one
$regexp[] = '#<img([^>]+)src="' . get_config('wwwroot')
. 'artefact/file/download.php\?file='
. $id . '&embedded=1([^"]+)"#';
$replacetext[] = '<img$1src="' . get_config('wwwroot')
. 'artefact/file/download.php?file='
. $artefactids["portfolio:artefact$id"][0] . '&embedded=1"';
}
}
$configdata['text'] = preg_replace($regexp, $replacetext, $configdata['text']);
}
// Rewrite embedded image urls in the configdata['text']
require_once('embeddedimage.php');
$configdata['text'] = EmbeddedImage::rewrite_embedded_image_urls_from_import($configdata['text'], $artefactids);
return $configdata;
}
......@@ -324,8 +303,16 @@ class PluginBlocktypeText extends SystemBlocktype {
$replacetext = array();
foreach ($artefactcopies as $copyobj) {
// Change the old image id to the new one
$regexp[] = '#<img([^>]+)src="' . get_config('wwwroot') . 'artefact/file/download.php\?file=' . $copyobj->oldid . '&embedded=1([^"]+)"#';
$replacetext[] = '<img$1src="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $copyobj->newid . '&embedded=1"';
$regexp[] = '#<img([^>]+)src=("|\\")'
. preg_quote(
get_config('wwwroot')
. 'artefact/file/download.php?file=' . $copyobj->oldid
)
. '(&|&amp;)embedded=1([^"]*)"#';
$replacetext[] = '<img$1src="'
. get_config('wwwroot')
. 'artefact/file/download.php?file=' . $copyobj->newid
. '&embedded=1"';
}
$configdata['text'] = preg_replace($regexp, $replacetext, $configdata['text']);
return $configdata;
......
......@@ -398,10 +398,11 @@ abstract class PluginExport extends Plugin implements IPluginExport {
}
/**
* Artefact plugins can specify additional artefacts required for view export
* Returns embedded artefacts in view description and
* additional artefacts required for view export from artefact plugins
*/
protected function get_view_extra_artefacts() {
$extra = array();
$extra = View::get_embedded_artefacts(array_keys($this->views));
$plugins = plugins_installed('artefact');
foreach ($plugins as &$plugin) {
safe_require('artefact', $plugin->name);
......
......@@ -999,6 +999,17 @@ class PluginImportLeap extends PluginImport {
$viewdata = unserialize($entry_request->entrycontent);
$view = View::import_from_config($this->rewrite_blockinstance_config($viewdata), $this->get('usr'), 'leap');
// Rewrite embedded image urls in the view description
// These links have been generated by export_leap_rewrite_links()
require_once('embeddedimage.php');
$newdescription = EmbeddedImage::rewrite_embedded_image_urls_from_import(
$view->get('description'),
$this->artefactids,
'description',
$view->get('id')
);
$view->set('description', $newdescription);
if (isset($viewdata->ctime)) {
$view->set('ctime', $viewdata->ctime);
}
......
......@@ -180,4 +180,94 @@ class EmbeddedImage {
}
}
}
/**
* Rewrites all possible embedded image urls when import a html string
*
* @param string $text the html string
* @param array $artefactids artefact ID mapping, see more PluginImportLeap::$artefactids
* @param string $resourcetype
* @param string $resourceid
* @return mixed
*/
public function rewrite_embedded_image_urls_from_import($text, array $artefactids, $resourcetype=null, $resourceid=null) {
$resourcestr = (!empty($resourcetype) && !empty($resourceid)) ?
"&$resourcetype=$resourceid"
: '';
// Find all possible embedded image artefact ids
// We support 2 formats of embedded image urls
// 1. <img ... src=".../artefact/file/download.php?file=...">
// generated by TinyMCE embedded image plugin
// 2. <img ... rel="leap2:has_part" href="(portfolio:artefact[\d]+)"...>
// generated by export_leap_rewrite_links()
if (!empty($text) && strpos($text, '<img') !== false) {
$ids = array();
$regexp = array();
$replacetext = array();
$matches = array();
if (preg_match_all(
'#<img([^>]+)src=("|\\")'
. preg_quote(
get_config('wwwroot')
. 'artefact/file/download.php?file='
)
. '([\d]+)'
. '(&|&amp;)embedded=1([^"]*)"#',
$text,
$matches)
) {
foreach ($matches[3] as $id) {
if (!empty($artefactids["portfolio:artefact$id"])) {
// Replace the old image id by the new one
$regexp[] = '#<img([^>]+)src=("|\\")'
. preg_quote(
get_config('wwwroot')
. 'artefact/file/download.php?file=' . $id
)
. '(&|&amp;)embedded=1#';
$replacetext[] = '<img$1src="' . get_config('wwwroot')
. 'artefact/file/download.php?file='
. $artefactids["portfolio:artefact$id"][0] . '&embedded=1'
. $resourcestr;
$ids[] = $id;
}
}
}
$matches = array();
if (preg_match_all(
'#<(img[^>]+)rel="leap2:has_part"'
. ' href="portfolio:artefact([\d]+)"([^>]*)>#',
$text,
$matches)
) {
foreach ($matches[2] as $id) {
if (!empty($artefactids["portfolio:artefact$id"])) {
// Replace the old entry id to the new one
$regexp[] = '#<img([^>]+)rel="leap2:has_part"'
. ' href="portfolio:artefact' . $id . '"#';
$replacetext[] = '<img$1src="' . get_config('wwwroot')
. 'artefact/file/download.php?file='
. $artefactids["portfolio:artefact$id"][0] . '&embedded=1'
. $resourcestr
. '"';
$ids[] = $id;
}
}
}
if (!empty($ids)) {
$text = preg_replace($regexp, $replacetext, $text);
// Update the table 'artefact_file_embedded'
if (!empty($resourcetype) && !empty($resourceid)) {
foreach ($ids as $id) {
insert_record('artefact_file_embedded', (object) array(
'fileid' => $artefactids["portfolio:artefact$id"][0],
'resourcetype' => $resourcetype,
'resourceid' => $resourceid
));
}
}
}
}
return $text;
}
}
......@@ -2938,7 +2938,6 @@ class View {
* what fields are available.
*/
public function export_config($format='') {
$data = $this->get_row_datastructure();
$config = array(
'title' => $this->get('title'),
'description' => $this->get('description'),
......@@ -2949,6 +2948,8 @@ class View {
'ownerformat' => $this->get('ownerformat'),
);
// Export view content
$data = $this->get_row_datastructure();
foreach ($data as $rowkey => $row) {
foreach ($row as $colkey => $column) {
$config['rows'][$rowkey]['columns'][$colkey] = array();
......@@ -2971,6 +2972,24 @@ class View {
return $config;
}
/**
* Returns embedded image artefact IDs in the description of given views
*
* @param array $viewids
* @return array artefact IDs
*/
public static function get_embedded_artefacts(array $viewids) {
if (!$aids = get_column_sql("
SELECT fileid
FROM {artefact_file_embedded}
WHERE resourcetype = ?
AND resourceid IN (" . join(',', array_map('intval', $viewids)) . ')'
, array('description'))) {
return array();
}
return $aids;
}
/**
* Given a data structure like the one created by {@link export_config},
* creates and returns a View object representing the config.
......@@ -5069,16 +5088,16 @@ class View {
public function copy_contents($template) {
$artefactcopies = array(); // Correspondence between original artefact ids and id of the copy
$this->set('numcolumns', $template->get('numcolumns'));
$this->set('numrows', $template->get('numrows'));
$this->set('layout', $template->get('layout'));
$this->set('description', $template->get('description'));
$this->set('description', $this->copy_description($template, $artefactcopies));
$this->set('tags', $template->get('tags'));
$this->set('columnsperrow', $template->get('columnsperrow'));
$blocks = get_records_array('block_instance', 'view', $template->get('id'));
$numcopied = array('blocks' => 0, 'artefacts' => 0);
$numcopied = array('blocks' => 0);
if ($blocks) {
$artefactcopies = array(); // Correspondence between original artefact ids and id of the copy
foreach ($blocks as $b) {
safe_require('blocktype', $b->blocktype);
$oldblock = new BlockInstance($b->id, $b);
......@@ -5086,17 +5105,17 @@ class View {
$numcopied['blocks']++;
}
}
// Go back and fix up artefact references in the new artefacts so
// they also point to new artefacts.
if ($artefactcopies) {
foreach ($artefactcopies as $oldid => $copyinfo) {
$a = artefact_instance_from_id($copyinfo->newid);
$a->update_artefact_references($this, $template, $artefactcopies, $oldid);
$a->commit();
}
}
// Go back and fix up artefact references in the new artefacts so
// they also point to new artefacts.
if ($artefactcopies) {
foreach ($artefactcopies as $oldid => $copyinfo) {
$a = artefact_instance_from_id($copyinfo->newid);
$a->update_artefact_references($this, $template, $artefactcopies, $oldid);
$a->commit();
}
$numcopied['artefacts'] = count($artefactcopies);
}
$numcopied['artefacts'] = count($artefactcopies);
return $numcopied;
}
......@@ -5118,6 +5137,63 @@ class View {
return $title . $ext;
}
/**
* Copy the description of the view template
* and its embedded image artefacts
*
* @param View $template the view template
* @param array &$artefactcopies the artefact mapping
* @return string updated description
*/
private function copy_description(View $template, array &$artefactcopies) {
$new_description = $template->get('description');
if (!empty($new_description)
&& strpos($new_description, 'artefact/file/download.php?file=') !== false) {
// Get all possible embedded artefacts
$artefactids = array_unique(artefact_get_references_in_html($new_description));
// Copy these image artefacts
foreach ($artefactids as $aid) {
try {
$a = artefact_instance_from_id($aid);
}
catch (Exception $e) {
continue;
}
if ($a instanceof ArtefactTypeImage) {
$artefactcopies[$aid] = (object) array(
'oldid' => $aid,
'oldparent' => $a->get('parent')
);
$artefactcopies[$aid]->newid = $a->copy_for_new_owner(
$this->get('owner'),
$this->get('group'),
$this->get('institution')
);
}
}
// Update the image urls in the description
if (!empty($artefactcopies)) {
$regexp = array();
$replacetext = array();
foreach ($artefactcopies as $oldaid => $newobj) {
// Change the old image id to the new one
$regexp[] = '#<img([^>]+)src=("|\\")'
. preg_quote(
get_config('wwwroot')
. 'artefact/file/download.php?file=' . $oldaid
)
. '(&|&amp;)embedded=1([^"]*)"#';
$replacetext[] = '<img$1src="'
. get_config('wwwroot')
. 'artefact/file/download.php?file=' . $newobj->newid
. '&embedded=1"';
}
$new_description = preg_replace($regexp, $replacetext, $new_description);
}
}
return $new_description;
}
/**
* Get a simplified name for this view for use in a url, which must be unique for a
* a given owner.
......
......@@ -16,6 +16,7 @@ define('SECTION_PLUGINNAME', 'view');
define('SECTION_PAGE', 'edit');
require(dirname(dirname(__FILE__)) . '/init.php');
require_once(get_config('docroot') . 'blocktype/lib.php');
require_once(get_config('libroot') . 'view.php');
require_once(get_config('libroot') . 'group.php');
......@@ -204,7 +205,11 @@ function editview_submit(Pieform $form, $values) {
global $new, $view, $SESSION, $urlallowed;
$view->set('title', $values['title']);
$view->set('description', $values['description']);
if (trim($values['description']) !== '') {
// Add or update embedded images in the view description
require_once('embeddedimage.php');
$view->set('description', EmbeddedImage::prepare_embedded_images($values['description'], 'description', $view->get('id')));
}
$view->set('tags', $values['tags']);
if (isset($values['locked'])) {
$view->set('locked', (int)$values['locked']);
......
......@@ -23,6 +23,7 @@ require_once(get_config('libroot') . 'objectionable.php');
require_once('institution.php');
require_once('group.php');
safe_require('artefact', 'comment');
safe_require('artefact', 'file');
// access key for roaming teachers
$mnettoken = $SESSION->get('mnetuser') ? param_alphanum('mt', null) : null;
......@@ -430,7 +431,7 @@ if ($mnetviewlist = $SESSION->get('mnetviewaccess')) {
}
}
$smarty->assign('viewdescription', $view->get('description'));
$smarty->assign('viewdescription', ArtefactTypeFolder::append_view_url($view->get('description'), $view->get('id')));
$smarty->assign('viewcontent', $viewcontent);
$smarty->assign('releaseform', $releaseform);
if (isset($addfeedbackform)) {
......
......@@ -13,6 +13,7 @@ define('INTERNAL', 1);
define('JSON', 1);
require(dirname(dirname(__FILE__)) . '/init.php');
require_once(get_config('libroot') . 'view.php');
safe_require('artefact', 'file');
$id = param_integer('id');
if (!can_view_view($id)) {
......@@ -23,7 +24,7 @@ $view = new View($id);
$smarty = smarty_core();
$smarty->assign('viewtitle', $view->get('title'));
$smarty->assign('ownername', $view->formatted_owner());
$smarty->assign('viewdescription', $view->get('description'));
$smarty->assign('viewdescription', ArtefactTypeFolder::append_view_url($view->get('description'), $view->get('id')));
$smarty->assign('viewcontent', $view->build_rows());
$smarty->assign('tags', $view->get('tags'));
$html = $smarty->fetch('view/viewcontent.tpl');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment