Commit 054e89d1 authored by Nigel McNie's avatar Nigel McNie
Browse files

Allow blog, blogpost and textbox blocktypes having links or manually created...

Allow blog, blogpost and textbox blocktypes having links or manually created <img> tags to artefacts to have those artefacts counted as being within the blocktype, and thus within the view.

This is so if people manually link to or source artefacts within textual content, those artefacts will be downloadable when the view is shown to others.

Not backporting to 1.0 although the problem will most certainly exist there - the patch is just too big to trust on a stable release.
parent 71c0b06d
......@@ -90,6 +90,42 @@ class PluginBlocktypeBlog extends PluginBlocktype {
);
}
/**
* Returns a list of artefact IDs that are in this blockinstance.
*
* {@internal{Because links to artefacts within blogposts don't count
* as making those artefacts 'children' of the blog post, we have to add
* them directly to the blog.}}
*
* @return array List of artefact IDs that are 'in' this blog - all
* blogposts in it plus all links to other artefacts that are
* part of the blogpost text. Note that proper artefact
* children, such as blog post attachments, aren't included -
* the artefact parent cache is used for them
* @see PluginBlocktypeBlogPost::get_artefacts()
*/
public static function get_artefacts(BlockInstance $instance) {
$configdata = $instance->get('configdata');
$artefacts = array();
if (isset($configdata['artefactid'])) {
$artefacts[] = $configdata['artefactid'];
// Artefacts that are linked to directly in blog post text aren't
// strictly children of blog posts, which means that
// artefact_in_view won't understand that they are "within the
// blog". We have to help it here directly by working out what
// artefacts are linked to in all of this blog's blog posts.
$blog = $instance->get_artefact_instance($configdata['artefactid']);
if ($blogposts = $blog->get_children_instances()) {
foreach ($blogposts as $blogpost) {
$artefacts = array_merge($artefacts, $blogpost->get_referenced_artefacts_from_postbody());
}
$artefacts = array_unique($artefacts);
}
}
return $artefacts;
}
public static function artefactchooser_element($default=null) {
return array(
'name' => 'artefactid',
......
......@@ -75,6 +75,36 @@ class PluginBlocktypeBlogpost extends PluginBlocktype {
return $result;
}
/**
* Returns a list of artefact IDs that are in this blockinstance.
*
* Normally this would just include the blogpost ID itself (children such
* as attachments don't need to be included here, they're handled by the
* artefact parent cache). But people might just link to artefacts without
* using the attachment facility. There's nothing wrong with them doing
* that, so if they do we should scrape the post looking for such links and
* include those artefacts as being part of this blockinstance.
*
* @return array List of artefact IDs that are 'in' this blogpost - all
* the blogpost ID plus links to other artefacts that are
* part of the blogpost text. Note that proper artefact
* children, such as blog post attachments, aren't included -
* the artefact parent cache is used for them
* @see PluginBlocktypeBlog::get_artefacts()
*/
public static function get_artefacts(BlockInstance $instance) {
$configdata = $instance->get('configdata');
$artefacts = array();
if (isset($configdata['artefactid'])) {
$artefacts[] = $configdata['artefactid'];
// Add all artefacts found in the blogpost text
$blogpost = $instance->get_artefact_instance($configdata['artefactid']);
$artefacts = array_unique(array_merge($artefacts, $blogpost->get_referenced_artefacts_from_postbody()));
}
return $artefacts;
}
public static function has_instance_config() {
return true;
}
......
......@@ -376,14 +376,20 @@ class ArtefactTypeBlogPost extends ArtefactType {
}
/**
* This function extends ArtefactType::commit() by adding additional data
* This method extends ArtefactType::commit() by adding additional data
* into the artefact_blog_blogpost table.
*
* This method also works out what blockinstances this blogpost is in, and
* informs them that they should re-check what artefacts they have in them.
* The post content may now link to different artefacts. See {@link
* PluginBlocktypeBlogPost::get_artefacts for more information}
*/
public function commit() {
if (empty($this->dirty)) {
return;
}
db_begin();
$new = empty($this->id);
parent::commit();
......@@ -402,6 +408,26 @@ class ArtefactTypeBlogPost extends ArtefactType {
update_record('artefact_blog_blogpost', $data, 'blogpost');
}
// We want to get all blockinstances that contain this blog post. That is currently:
// 1) All blogpost blocktypes with this post in it
// 2) All blog blocktypes with this posts's blog in it
//
// With these, we tell them to rebuild what artefacts they have in them,
// since the post content could have changed and now have links to
// different artefacts in it
$blockinstanceids = (array)get_column_sql('SELECT block
FROM {view_artefact}
WHERE artefact = ?
OR artefact = ?', array($this->get('id'), $this->get('parent')));
if ($blockinstanceids) {
require_once(get_config('docroot') . 'blocktype/lib.php');
foreach ($blockinstanceids as $id) {
$instance = new BlockInstance($id);
$instance->rebuild_artefact_list();
}
}
db_commit();
$this->dirty = false;
}
......@@ -844,6 +870,14 @@ class ArtefactTypeBlogPost extends ArtefactType {
return $blogid;
}
/**
* Looks through the blog post text for links to download artefacts, and
* returns the IDs of those artefacts.
*/
public function get_referenced_artefacts_from_postbody() {
return artefact_get_references_in_html($this->get('description'));
}
}
......
......@@ -1005,4 +1005,26 @@ function artefact_owner_sql($userid=null, $groupid=null, $institution=null) {
return null;
}
/**
* Given a string of html, look for references to artefacts in it and return a
* list of artefact IDs found
*
* @return array List of artefact IDs found
*/
function artefact_get_references_in_html($html) {
$matches = array();
// Look for links to artefacts
preg_match_all('#<a[^>]+href="[^>]+artefact/file/download\.php\?file=(\d+)#', $html, $matches);
$artefacts = $matches[1];
// Look for images sourcing artefacts
preg_match_all('#<img[^>]+src="[^>]+artefact/file/download\.php\?file=(\d+)#', $html, $matches);
$artefacts = array_unique(array_merge($artefacts, $matches[1]));
// TODO: might have to look for object tags etc. later
return $artefacts;
}
?>
......@@ -111,10 +111,14 @@ abstract class PluginBlocktype extends Plugin {
public static function instance_config_validate(Pieform $form, $values) { }
/**
* most Blocktype plugins will attach to artefacts.
* They should implement this function to keep a list of which ones
* note that it should just handle top level artefacts.
* the cache rebuilder will figure out the children.
* Most blocktype plugins will attach to artefacts.
* They should implement this function to keep a list of which ones. The
* result of this method is used to populate the view_artefact table, and
* thus decide whether an artefact is in a view for the purposes of access.
* See {@link artefact_in_view} for more information about this.
*
* Note that it should just handle top level artefacts.
* The cache rebuilder will figure out the children.
*
* @return array ids of artefacts in this block instance
*/
......@@ -248,7 +252,7 @@ abstract class PluginBlocktype extends Plugin {
abstract class SystemBlockType extends PluginBlockType {
public final static function get_artefacts(BlockInstance $instance) {
public static function get_artefacts(BlockInstance $instance) {
return array();
}
......@@ -679,6 +683,7 @@ class BlockInstance {
*/
public function get_view() {
if (empty($this->view_obj)) {
require_once('view.php');
$this->view_obj = new View($this->get('view'));
}
return $this->view_obj;
......
......@@ -52,6 +52,22 @@ class PluginBlocktypeTextbox extends SystemBlocktype {
return $text;
}
/**
* Returns a list of artefact IDs that are in this blockinstance.
*
* People may embed artefacts as images etc. They show up as links to the
* download script, which isn't much to go on, but should be enough for us
* to detect that the artefacts are therefore 'in' this blocktype.
*/
public static function get_artefacts(BlockInstance $instance) {
$artefacts = array();
$configdata = $instance->get('configdata');
if (isset($configdata['text'])) {
$artefacts = artefact_get_references_in_html($configdata['text']);
}
return $artefacts;
}
public static function has_instance_config() {
return true;
}
......
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