Commit 669ebe8b authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review
Browse files

Make blocktype:taggedposts work with view_artefacts

Bug 1401210. The get_artefacts() method is used by the Blogpost
artefact to find all the blocks that use a particular blogpost,
for storing in the view_artefacts table.

I needed to add a table, blocktype_taggedposts_tags, to store
the tags in a manner that was easier to query than a serialized
blockconfig.

Change-Id: Ieef58715e404689d95848e32ccd4132ea3fbcdc5
parent 247c10a2
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20060926" COMMENT="XMLDB file for core Mahara tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="blocktype_taggedposts_tags">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" SEQUENCE="true" NOTNULL="true" />
<FIELD NAME="block_instance" TYPE="int" LENGTH="10" NOTNULL="true" />
<FIELD NAME="tag" TYPE="char" LENGTH="128" NOTNULL="true" />
<FIELD NAME="tagtype" TYPE="int" LENGTH="10" NOTNULL="true" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
</KEYS>
<INDEXES>
<INDEX NAME="tagtagtypeix" UNIQUE="false" FIELDS="tag,tagtype"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
......@@ -2,7 +2,7 @@
/**
*
* @package mahara
* @subpackage artefact-blog
* @subpackage blocktype-taggedposts
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
......@@ -13,17 +13,32 @@ defined('INTERNAL') || die();
function xmldb_blocktype_taggedposts_upgrade($oldversion=0) {
if ($oldversion < 2014121700) {
// if we have existing taggedposts blocks we will need to to update them
if ($taggedblockids = get_column('block_instance', 'id', 'blocktype', 'taggedposts')) {
require_once(get_config('docroot') . 'blocktype/lib.php');
foreach ($taggedblockids as $blockid) {
$bi = new BlockInstance($blockid);
$configdata = $bi->get('configdata');
if (isset($configdata['tagselect']) && !is_array($configdata['tagselect'])) {
$configdata['tagselect'] = array($configdata['tagselect'] => 1);
$bi->set('configdata', $configdata);
$bi->commit();
if ($oldversion < 2015011500) {
$table = new XMLDBTable('blocktype_taggedposts_tags');
$table->addFieldInfo('id', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
$table->addFieldInfo('block_instance', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL);
$table->addFieldInfo('tag', XMLDB_TYPE_CHAR, 128, null, XMLDB_NOTNULL);
$table->addFieldInfo('tagtype', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL);
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->addIndexInfo('tagtagtypeix', XMLDB_INDEX_NOTUNIQUE, array('tag', 'tagtype'));
if (!table_exists($table)) {
create_table($table);
$rs = get_recordset('block_instance', 'blocktype', 'taggedposts', 'id', 'id, configdata');
while ($bi = $rs->FetchRow()) {
// Each block will have only one tag (because we combined this upgrade block
// with the upgrade block for the "multiple tags" enhancement.
$configdata = unserialize($bi['configdata']);
if (!empty($configdata['tagselect'])) {
$todb = new stdClass();
$todb->block_instance = $bi['id'];
$todb->tag = $configdata['tagselect'];
$todb->tagtype = PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE;
insert_record('blocktype_taggedposts_tags', $todb);
}
}
}
......
......@@ -13,6 +13,9 @@ defined('INTERNAL') || die();
class PluginBlocktypeTaggedposts extends SystemBlocktype {
const TAGTYPE_INCLUDE = 1;
const TAGTYPE_EXCLUDE = 0;
public static function get_title() {
return get_string('title', 'blocktype.blog/taggedposts');
}
......@@ -35,29 +38,69 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
);
}
public static function render_instance(BlockInstance $instance, $editing=false) {
/**
* Given a list of tags, finds blocks by the current user that contain those tags
* (Used to determine which ones to check for the view_artefact table)
* @param array $tags
* @return array
*/
public static function find_matching_blocks(array $tags) {
global $USER;
$taggedblockids = (array)get_column_sql(
'SELECT bi.id as block
FROM
{blocktype_taggedposts_tags} btt
INNER JOIN {block_instance} bi
ON btt.block_instance = bi.id
INNER JOIN {view} v
ON bi.view = v.id
WHERE
v.owner = ?
AND btt.tagtype = ?
AND btt.tag IN (' . implode(',', db_array_to_ph($tags)) . ')
',
array_merge(
array(
$USER->id,
PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE
),
$tags
)
);
if ($taggedblockids) {
return $taggedblockids;
}
else {
return array();
}
}
/**
* Returns the blog posts that will be displayed by this block.
*
* @param BlockInstance $instance
* @param array $tagsin Optional reference variable for finding out the "include" tags used by this block
* @param array $tagsout Optional reference variable for finding out the "extclude" tags used by this block
* @return array of blogpost records
*/
public static function get_blog_posts_in_block(BlockInstance $instance, &$tagsinreturn = null, &$tagsoutreturn = null) {
$configdata = $instance->get('configdata');
$view = $instance->get('view');
$limit = isset($configdata['count']) ? (int) $configdata['count'] : 10;
$full = isset($configdata['full']) ? $configdata['full'] : false;
$results = array();
$smarty = smarty_core();
$smarty->assign('view', $view);
$viewownerdisplay = null;
// Display all posts, from all blogs, owned by this user
$configdata['tagselect'] = (!empty($configdata['tagselect'])) ? $configdata['tagselect'] : array();
if (!empty($configdata['tagselect'])) {
$tagselect = $configdata['tagselect'];
$tagsin = $tagsout = array();
foreach ($tagselect as $key => $value) {
if (!empty($value)) {
$tagsin[] = $key;
$tagsin = $tagsout = array();
$tagrecords = get_records_array('blocktype_taggedposts_tags', 'block_instance', $instance->get('id'), 'tagtype desc, tag', 'tag, tagtype');
if ($tagrecords) {
$view = $instance->get('view');
$limit = isset($configdata['count']) ? (int) $configdata['count'] : 10;
foreach ($tagrecords as $tag) {
if ($tag->tagtype == PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE) {
$tagsin[] = $tag->tag;
}
else {
$tagsout[] = $key;
$tagsout[] = $tag->tag;
}
}
$tagsout = array_filter($tagsout);
......@@ -107,6 +150,37 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
$results = array_slice($results, 0, $limit);
}
}
else {
$results = array();
}
}
if ($tagsinreturn !== null) {
$tagsinreturn = $tagsin;
}
if ($tagsoutreturn !== null) {
$tagsoutreturn = $tagsout;
}
return $results;
}
public static function render_instance(BlockInstance $instance, $editing=false) {
global $USER;
$configdata = $instance->get('configdata');
$view = $instance->get('view');
$full = isset($configdata['full']) ? $configdata['full'] : false;
$results = array();
$smarty = smarty_core();
$smarty->assign('view', $view);
$viewownerdisplay = null;
// Display all posts, from all blogs, owned by this user
$tagsin = $tagsout = array();
$results = self::get_blog_posts_in_block($instance, $tagsin, $tagsout);
if ($tagsin || $tagsout) {
$smarty->assign('blockid', $instance->get('id'));
$smarty->assign('editing', $editing);
if ($editing) {
......@@ -121,8 +195,8 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
// if posts are not found with the selected tag, notify the user
if (!$results) {
$smarty->assign('badtag', implode(', ', array_keys($tagselect,1)));
$smarty->assign('badnotag', implode(', ', array_keys($tagselect,0)));
$smarty->assign('badtag', implode(', ', $tagsin));
$smarty->assign('badnotag', implode(', ', $tagsout));
return $smarty->fetch('blocktype:taggedposts:taggedposts.tpl');
}
......@@ -139,7 +213,6 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
safe_require('artefact', 'comment');
foreach ($results as $result) {
$dataobject["artefact"] = $result->parent;
ensure_record_exists('view_artefact', $dataobject, $dataobject);
$result->postedbyon = get_string('postedbyon', 'artefact.blog', display_default_name($result->owner), format_date(strtotime($result->ctime)));
$result->displaydate= format_date(strtotime($result->ctime));
......@@ -176,7 +249,7 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
$smarty->assign('tagsin', $tagsin);
$smarty->assign('tagsout', $tagsout);
}
else if (!self::get_tags()) {
else if (!self::get_chooseable_tags()) {
// error if block configuration fails
$smarty->assign('configerror', get_string('notagsavailableerror', 'blocktype.blog/taggedposts'));
return $smarty->fetch('blocktype:taggedposts:taggedposts.tpl');
......@@ -212,16 +285,28 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
return $smarty->fetch('blocktype:taggedposts:taggedposts.tpl');
}
private static function get_tags() {
private static function get_selected_tags() {
}
/**
* Get the tags the user can choose from
* (i.e. tags they use on their blogpost artefacts)
* @return array
*/
private static function get_chooseable_tags() {
global $USER;
return get_records_sql_array("
SELECT at.tag
FROM {artefact_tag} at
JOIN {artefact} a
ON a.id = at.artefact
WHERE a.owner = ?
AND a.artefacttype = 'blogpost'
FROM
{artefact_tag} at
JOIN {artefact} a
ON a.id = at.artefact
WHERE
a.owner = ?
AND a.artefacttype = 'blogpost'
GROUP BY at.tag
ORDER BY at.tag ASC
", array($USER->id));
......@@ -235,18 +320,19 @@ class PluginBlocktypeTaggedposts extends SystemBlocktype {
global $USER;
$configdata = $instance->get('configdata');
$tags = self::get_tags();
$tags = self::get_chooseable_tags();
$elements = array();
$tagselect = array();
if (!empty($tags)) {
if (!empty($configdata['tagselect'])) {
foreach ($configdata['tagselect'] as $tag => $option) {
if ($option == '1') {
$tagselect[] = $tag;
$tagselect = array();
$tagrecords = get_records_array('blocktype_taggedposts_tags', 'block_instance', $instance->get('id'), 'tagtype desc, tag', 'tag, tagtype');
if ($tagrecords) {
foreach ($tagrecords as $tag) {
if ($tag->tagtype == PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE) {
$tagselect[] = $tag->tag;
}
else {
$tagselect[] = '-' . $tag;
$tagselect[] = '-' . $tag->tag;
}
}
}
......@@ -323,22 +409,55 @@ EOF;
}
}
public static function instance_config_save($values) {
public static function instance_config_save($values, BlockInstance $instance) {
$tagselect = $values['tagselect'];
unset($values['tagselect']);
if (!empty($tagselect)) {
delete_records('blocktype_taggedposts_tags', 'block_instance', $instance->get('id'));
foreach ($tagselect as $tag) {
$value = 1;
$value = PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE;
if (substr($tag, 0, 1) == '-') {
$value = 0;
$value = PluginBlocktypeTaggedposts::TAGTYPE_EXCLUDE;
$tag = substr($tag, 1);
}
$values['tagselect'][$tag] = $value;
$todb = new stdClass();
$todb->block_instance = $instance->get('id');
$todb->tag = $tag;
$todb->tagtype = $value;
insert_record('blocktype_taggedposts_tags', $todb);
}
}
return $values;
}
/**
* 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) {
$artefacts = array();
$blogposts = self::get_blog_posts_in_block($instance);
foreach ($blogposts as $blogpost) {
$artefacts[] = $blogpost->id;
$artefacts[] = $blogpost->parent;
$blogpostobj = $instance->get_artefact_instance($blogpost->id);
$artefacts = array_merge($artefacts, $blogpostobj->get_referenced_artefacts_from_postbody());
}
$artefacts = array_unique($artefacts);
return $artefacts;
}
public static function default_copy_type() {
return 'nocopy';
}
......
......@@ -12,5 +12,5 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2014121700;
$config->release = '1.0.3';
$config->version = 2015011500;
$config->release = '1.1.0';
......@@ -536,6 +536,8 @@ class ArtefactTypeBlogPost extends ArtefactType {
* PluginBlocktypeBlogPost::get_artefacts for more information}
*/
protected function postcommit_hook($new) {
require_once(get_config('docroot') . 'blocktype/lib.php');
require_once(get_config('docroot') . 'artefact/blog/blocktype/taggedposts/lib.php');
$data = (object)array(
'blogpost' => $this->get('id'),
'published' => ($this->get('published') ? 1 : 0)
......@@ -553,19 +555,26 @@ class ArtefactTypeBlogPost extends ArtefactType {
// 2) All blog blocktypes with this posts's blog in it
// 3) All recentposts blocktypes with this post's blog in it
// 4) All taggedposts blocktypes with this post's tags
$blockinstanceids = (array)get_column_sql('SELECT block
$blocks = (array)get_column_sql('SELECT block
FROM {view_artefact}
WHERE artefact = ?
OR artefact = ?', array($this->get('id'), $this->get('parent')));
if (!$blockinstanceids) {
$blockinstanceids = array();
if (!$blocks) {
$blocks = array();
}
// Get all "tagged blog entries" blocks that may contain this block
// (we'll just check for a single matching tag here, and let each block
// instance further down decide whether or not it matches
$tags = $this->get('tags');
if ($tags) {
$blocks = array_merge($blocks, PluginBlocktypeTaggedposts::find_matching_blocks($tags));
}
// Now rebuild the list of which artefacts these blocks contain
// in the view_artefacts table. (This is used for watchlist notifications)
if ($blockinstanceids) {
require_once(get_config('docroot') . 'blocktype/lib.php');
foreach ($blockinstanceids as $id) {
if ($blocks) {
foreach ($blocks as $id) {
$instance = new BlockInstance($id);
$instance->rebuild_artefact_list();
}
......
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