Commit f1b582d9 authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Merge changes from topic 'WR 287940'

* changes:
  Bug 1722861: Display institution tags in a table
  Bug 1722861: Restricting use of institution tags
  Bug 1775106: Creating page from tags
parents 5e78f440 10615213
......@@ -275,7 +275,7 @@ if ($tagsarray = get_records_sql_array("SELECT t.tag, t.prefix, t.ownerid
FROM (
SELECT ut.tag, NULL AS prefix, 0 AS ownerid
FROM {tag} ut
WHERE resourcetype = ? AND resourceid = ? AND ownertype <> 'instituion'
WHERE resourcetype = ? AND resourceid = ? AND ownertype != 'instituion'
AND NOT tag " . db_ilike() . " 'lastinstitution:%'
UNION
SELECT it.tag, it.ownerid AS prefix, i.id AS ownerid
......@@ -628,16 +628,22 @@ function edituser_site_submit(Pieform $form, $values) {
if (empty($tag)) {
continue;
}
if ($tagid = get_field('tag', 'resourceid', 'resourcetype', 'institution', 'tag', $tag)) {
$tag = 'tagid_' . $tagid;
$tag = check_if_institution_tag($tag);
if (preg_match("/^lastinstitution\:(.*)/", $tag, $matches)) {
$ownertype = 'institution';
$ownerid = $matches[1];
}
else {
$ownertype = 'user';
$ownerid = $user->id;
}
insert_record(
'tag',
(object) array(
'resourcetype' => 'usr',
'resourceid' => $user->id,
'ownertype' => 'user',
'ownerid' => $user->id,
'ownertype' => $ownertype,
'ownerid' => $ownerid,
'tag' => $tag,
'ctime' => db_format_timestamp(time()),
'editedby' => $USER->get('id'),
......
......@@ -472,33 +472,37 @@ EOF;
$tagselect = $values['tagselect'];
unset($values['tagselect']);
if (!empty($tagselect)) {
delete_records('blocktype_taggedposts_tags', 'block_instance', $instance->get('id'));
foreach ($tagselect as $tag) {
$value = PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE;
if (substr($tag, 0, 1) == '-') {
$value = PluginBlocktypeTaggedposts::TAGTYPE_EXCLUDE;
$tag = substr($tag, 1);
}
// If tag is institution tag, save it's correct form.
if (strpos($tag, ':')) {
$tagarray = explode(': ', $tag);
$sql = "SELECT t.id
FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid
WHERE t.tag = ? AND t.resourcetype = 'institution' AND i.displayname = ?";
$insttagid = get_field_sql($sql, array($tagarray[1], $tagarray[0]));
$tag = 'tagid_' . $insttagid;
}
$todb = new stdClass();
$todb->block_instance = $instance->get('id');
$todb->tag = htmlspecialchars_decode($tag);
$todb->tagtype = $value;
insert_record('blocktype_taggedposts_tags', $todb);
}
self::save_tag_selection($tagselect, $instance);
}
return $values;
}
public static function save_tag_selection($tagselect, BlockInstance $instance) {
delete_records('blocktype_taggedposts_tags', 'block_instance', $instance->get('id'));
foreach ($tagselect as $tag) {
$value = PluginBlocktypeTaggedposts::TAGTYPE_INCLUDE;
if (substr($tag, 0, 1) == '-') {
$value = PluginBlocktypeTaggedposts::TAGTYPE_EXCLUDE;
$tag = substr($tag, 1);
}
// If tag is institution tag, save it's correct form.
if (strpos($tag, ':')) {
$tagarray = explode(': ', $tag);
$sql = "SELECT t.id
FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid
WHERE t.tag = ? AND t.resourcetype = 'institution' AND i.displayname = ?";
$insttagid = get_field_sql($sql, array($tagarray[1], $tagarray[0]));
$tag = 'tagid_' . $insttagid;
}
$todb = new stdClass();
$todb->block_instance = $instance->get('id');
$todb->tag = htmlspecialchars_decode($tag);
$todb->tagtype = $value;
insert_record('blocktype_taggedposts_tags', $todb);
}
}
/**
* Returns a list of artefact IDs that are "in" this blockinstance.
*
......
......@@ -658,9 +658,7 @@ abstract class ArtefactType implements IArtefactType {
if (empty($tag)) {
continue;
}
if ($institutiontag = get_record('tag', 'tag', $tag, 'resourcetype', 'institution', 'ownertype', 'institution')) {
$tag = 'tagid_' . $institutiontag->id;
}
$tag = check_if_institution_tag($tag);
insert_record('tag',
(object) array(
'resourcetype' => 'artefact',
......
......@@ -736,6 +736,10 @@ class BlockInstance {
private function set_tags($tags) {
global $USER;
if (empty($this->view_obj)) {
$this->get_view();
}
if ($this->view_obj->get('group')) {
$ownertype = 'group';
$ownerid = $this->view_obj->get('group');
......@@ -753,9 +757,7 @@ class BlockInstance {
foreach ($this->tags as $tag) {
// truncate the tag before insert it into the database
$tag = substr($tag, 0, 128);
if ($institutiontag = get_record('tag', 'tag', $tag, 'resourcetype', 'institution', 'ownertype', 'institution')) {
$tag = 'tagid_' . $institutiontag->id;
}
$tag = check_if_institution_tag($tag);
insert_record('tag',
(object)array(
'resourcetype' => 'blocktype',
......
<!-- @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. -->
<h3>Create page via tags</h3>
<p>You can select some tags to populate the page with content containing those tags.</p>
<p>The resulting page will contain the content (artefacts and blocks) that you tagged. You can then re-arrange the blocks on the page.</p>
<p>For example, if you tag:<p>
<ul>
<li>One image and then select that tag here, it will be added as an image block to the page.</li>
<li>Three images with the same two tags and select these tags here, the images will be displayed in an image gallery.</li>
<li>One PDF and select that tag here, the PDF block will be added to the page.</li>
<li>An existing block on another page, e.g. the "Text" block, it will copy that block to this page.</li>
</ul>
<h4>Content mappings:</h4>
<table>
<tr>
<th>Type</th>
<th>Count</th>
<th>Block</th>
</tr>
<tr>
<td rowspan="2" valign="top">Image</td>
<td>1</td>
<td valign="top">Image</td>
</tr>
<tr>
<td valign="top">2+</td>
<td valign="top">Image gallery slideshow</td>
</tr>
<td rowspan="2" valign="top">PDF</td>
<td valign="top">1</td>
<td valign="top">PDF block</td>
</tr>
<tr>
<td valign="top">2+</td>
<td valign="top">Files to download</td>
</tr>
<td valign="top">Generic files</td>
<td valign="top">1+</td>
<td>Files to download</td>
</tr>
<tr>
<td rowspan="2" valign="top">Audio/video</td>
<td valign="top">1</td>
<td valign="top">Internal media</td>
</tr>
<tr>
<td valign="top">2+</td>
<td valign="top">Files to download</td>
</tr>
<tr>
<td valign="top">Folder</td>
<td valign="top">1+</td>
<td valign="top">Folder block per folder</td>
</tr>
<tr>
<td valign="top">Journal</td>
<td valign="top">1+</td>
<td valign="top">Journal block per journal</td>
</tr>
<tr>
<td valign="top">Journal entry</td>
<td valign="top">1+</td>
<td valign="top">Tagged journal entries</td>
</tr>
<tr>
<td valign="top">Notes</td>
<td valign="top">1+</td>
<td valign="top">Note block per note</td>
</tr>
<tr>
<td valign="top">Plan/tasks</td>
<td valign="top">1+</td>
<td valign="top">Plan, i.e. the entire plan(s) that contain the tagged tasks</td>
</tr>
</table>
<p><strong>Note</strong>: The selected tags are only used to add the initial blocks to the page. If you tag other content afterwards, you would need to add that to the page yourself. Also, when you remove a block, it will not be added back automatically.</p>
<p>If you select a different tag (or the same again) the next time, the new content will be added to the page.</p>
......@@ -223,6 +223,7 @@ $string['allowinstitutiontagsdescription'] = 'Administrators can define a set of
$string['cantlistinstitutiontags'] = 'You are not allowed to list institution tags.';
$string['createtag'] = 'Create tag';
$string['deleteinstitutiontag'] = 'Delete institution tag';
$string['deleteinstitutiontagspecific'] = 'Delete institution tag "%s"';
$string['editinstitutiontag'] = 'Edit institution tag';
$string['error:duplicatetag'] = 'Institutional tag already exists.';
$string['error:emptytag'] = 'Institutional tag cannot be empty.';
......@@ -235,7 +236,9 @@ $string['institutiontags'] = 'Institution tags';
$string['institutiontagsdescription'] = 'The institution tags are predefined by the institution and available for use by all institution members. You can create as many tags as you like.';
$string['institutiontagsaved'] = 'Institution tag saved.';
$string['notags'] = 'No tags for this institution.';
$string['timesused'] = 'Times used:';
$string['tag'] = 'Tag';
$string['timesused'] = 'Times used';
$string['usedtagscantbedeleted'] = 'Used tags can\'t be deleted';
// License metadata
$string['license'] = 'License';
......
......@@ -48,6 +48,8 @@ $string['unrecogniseddateformat'] = 'Unrecognised date format';
$string['allowcommentsonview1'] = 'Allow users to leave comments.';
$string['ownerformat'] = 'Name display format';
$string['ownerformatdescription'] = 'How do you want people who look at your page to see your name?';
$string['createtags'] = 'Create via tags';
$string['createtagsdesc'] = 'Search for or enter tags that you want to use for pulling existing content into your page. If you have a lot of content tagged, this may take a little bit. You can then re-arrange and delete blocks from your page.';
$string['anonymise'] = 'Anonymise';
$string['anonymisedescription'] = 'Hide your name as the author of the page from other users. Administrators will still be able to see your name if they so desire.';
$string['Locked'] = 'Locked';
......
......@@ -214,9 +214,7 @@ class Collection {
foreach ($tags as $tag) {
//truncate the tag before insert it into the database
$tag = substr($tag, 0, 128);
if ($institutiontag = get_record('tag', 'tag', $tag, 'resourcetype', 'institution', 'ownertype', 'institution')) {
$tag = 'tagid_' . $institutiontag->id;
}
$tag = check_if_institution_tag($tag);
insert_record('tag',
(object)array(
'resourcetype' => 'collection',
......
......@@ -41,11 +41,22 @@ function translate_tags_to_names(array $ids) {
global $USER;
// for an empty list, the element '' is transmitted
$ids = array_diff($ids, array(''));
$ids = array_map(function($a) {
if (strpos($a, ':')) {
$arr = explode(': ', $a);
return $arr[1];
$institutions = $USER->get('institutions');
if (!empty($institutions)) {
$institutions = array_keys($institutions);
// Fetch valid institution tags
$validinstitutiontags = get_column_sql("SELECT tag FROM {tag}
WHERE ownertype = 'institution' AND ownerid IN ('" . join("','", $institutions) . "')");
}
else {
$validinstitutiontags = array();
}
$ids = array_map(function($a) use ($validinstitutiontags) {
if (strpos($a, ': ')) {
if (in_array($a, $validinstitutiontags)) {
$arr = explode(': ', $a);
return trim($arr[1]);
}
}
return $a;
}, $ids);
......@@ -94,25 +105,14 @@ function get_all_tags_for_user($query = null, $limit = null, $offset = null) {
$usertags = "";
$userid = $USER->get('id');
$typecast = is_postgres() ? '::varchar' : '';
if ($USER->get('admin')) {
$usertags = "
UNION ALL
SELECT tag, COUNT(*) AS count, 'lastinstitution' AS prefix FROM {tag} t INNER JOIN {usr} u ON (t.resourcetype = 'usr' AND t.resourceid = u.id" . $typecast . ") GROUP BY 1";
}
else if ($admininstitutions = $USER->get('admininstitutions')) {
$insql = "'" . join("','", $admininstitutions) . "'";
$usertags = "
UNION ALL
SELECT tag, COUNT(*) AS count, 'lastinstitution' AS prefix FROM {tag} t INNER JOIN {usr} u ON (t.resourcetype = 'usr' AND t.resourceid = u.id" . $typecast . ") INNER JOIN {usr_institution} ui ON ui.usr=u.id WHERE ui.institution IN ($insql) GROUP BY 1";
}
$values = array($userid, $userid);
$querystr = '';
if ($query) {
$querystr = " WHERE tag LIKE '%' || ? || '%'";
$querystr = " WHERE tag " . db_ilike() . " '%' || ? || '%'";
$values[] = $query;
// Also do matching by institution name so we can list valid institution tags
// if we only know institution name
$querystr .= " OR prefix LIKE '%' || ? || '%'";
$querystr .= " OR prefix " . db_ilike() . " '%' || ? || '%'";
$values[] = $query;
}
$sql = "
......@@ -133,7 +133,7 @@ function get_all_tags_for_user($query = null, $limit = null, $offset = null) {
FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid AND i.tags = 1
JOIN {usr_institution} ui ON ui.institution = i.name AND ui.usr = ?
" . $usertags . "
WHERE t.resourcetype != 'usr'
) tags
" . $querystr . "
GROUP BY tag, prefix
......
......@@ -622,6 +622,8 @@ class Institution {
}
public function removeMember($user) {
global $USER;
if (is_numeric($user)) {
$user = get_record('usr', 'id', $user);
}
......@@ -695,6 +697,20 @@ class Institution {
)
);
// Need to change any user's "institution tag" tags for this institution
// into normal user tags
$typecast = is_postgres() ? '::varchar' : '';
if ($userinstitutiontags = get_records_sql_array("
SELECT t.id, t.tag, (SELECT t2.tag FROM {tag} t2 WHERE t2.id" . $typecast . " = SUBSTRING(t.tag, 7)) AS realtag
FROM {tag} t
WHERE ownertype = ? AND ownerid = ?
AND tag LIKE 'tagid_%'", array('user', $user->id))) {
foreach ($userinstitutiontags as $newtag) {
execute_sql("UPDATE {tag} SET tag = ? WHERE id = ?", array($newtag->realtag, $newtag->id));
}
}
// If the user's license default is set to "institution default", remove the pref
delete_records('usr_account_preference', 'usr', $user->id, 'field', 'licensedefault', 'value', LICENSE_INSTITUTION_DEFAULT);
......
......@@ -4542,7 +4542,7 @@ function build_portfolio_search_html(&$data) {
safe_require('artefact', $artefacttypes[$item->artefacttype]->plugin);
$links = call_static_method(generate_artefact_class_name($item->artefacttype), 'get_links', $item->id);
$item->url = $links['_default'];
$item->typestr = $item->artefacttype;
$item->typestr = isset($item->specialtype) ? $item->specialtype : $item->artefacttype;
if ($item->artefacttype == 'task') {
$item->typelabel = get_string('Task', 'artefact.plans');
}
......@@ -4701,6 +4701,31 @@ function generate_csv($data, $csvfields, $csvheaders = array()) {
return $csv;
}
/**
*
*/
function check_if_institution_tag($tag) {
global $USER;
$institutions = $USER->get('institutions');
if ($institutions && $institutiontags = get_records_sql_array("
SELECT id FROM {tag}
WHERE tag = ?
AND resourcetype = ?
AND ownertype = ?
AND ownerid IN ('" . join("','", array_keys($institutions)) . "')
UNION
SELECT t.id FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid
WHERE resourcetype = ?
AND ownertype = ?
AND ownerid IN ('" . join("','", array_keys($institutions)) . "')
AND CONCAT(i.displayname, ': ', t.tag) = ?",
array($tag, 'institution', 'institution', 'institution', 'institution', $tag))) {
$tag = 'tagid_' . $institutiontags[0]->id; // if same tag in multiple institutions just pick first
}
return $tag;
}
/**
* Check to make sure table is case sensitive (currently only for MySql)
* If it is not then reduce supplied array to a case insensitive version
......
......@@ -869,9 +869,7 @@ class View {
foreach ($this->get_tags() as $tag) {
//truncate the tag before insert it into the database
$tag = substr($tag, 0, 128);
if ($institutiontag = get_record('tag', 'tag', $tag, 'resourcetype', 'institution', 'ownertype', 'institution')) {
$tag = 'tagid_' . $institutiontag->id;
}
$tag = check_if_institution_tag($tag);
insert_record('tag',
(object)array(
'resourcetype' => 'view',
......@@ -2916,7 +2914,7 @@ class View {
/**
* returns the current max block position within a column
*/
private function get_current_max_order($row, $column) {
public function get_current_max_order($row, $column) {
return get_field('block_instance', 'max("order")', 'column', $column, 'view', $this->get('id'), 'row', $row);
}
......
......@@ -1044,11 +1044,13 @@ class PluginSearchInternal extends PluginSearch {
$split = explode(':', $tag);
if (count($split) == 2) {
$prefix = trim($split[0]);
$tag = trim($split[1]);
$tag = get_field_sql("SELECT CONCAT('tagid_', t.id)
FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid
WHERE i.displayname = ? AND t.tag = ?", array($prefix, $tag));
$itag = trim($split[1]);
if ($checktag = get_field_sql("SELECT CONCAT('tagid_', t.id)
FROM {tag} t
JOIN {institution} i ON i.name = t.ownerid
WHERE i.displayname = ? AND t.tag = ?", array($prefix, $itag))) {
$tag = $checktag;
}
}
$values = array($owner->id, $tag, $owner->id, $tag, $owner->id, $tag, $tag, $owner->id, $tag);
}
......@@ -1148,6 +1150,17 @@ class PluginSearchInternal extends PluginSearch {
}
$d->views = $record_views;
}
// Check if the file is a pdf
if ($d->artefacttype == 'file') {
if (get_field_sql("SELECT artefact
FROM {artefact_file_files}
WHERE artefact = ?
AND filetype IN (
SELECT mimetype FROM {artefact_file_mime_types}
WHERE description = ?)", array($d->id, 'pdf'))) {
$d->specialtype = 'pdf';
}
}
}
else if ($d->type == 'collection') {
$c = new Collection($d->id);
......@@ -1319,6 +1332,7 @@ class PluginSearchInternal extends PluginSearch {
$result->data = $data;
}
}
return $result;
}
......
......@@ -26,6 +26,7 @@
<strong>{str tag=tags}:</strong> {list_tags owner=$plan.owner tags=$plan.tags view=$plan.view}
</div>
{/if}
{if !$plan.description && !$plan.tags} &nbsp; {/if}
{if $plan.numtasks != 0}
{foreach from=$alltasks item=tasks}
......
......@@ -2,37 +2,37 @@
{if !$canedit}<p>{str tag=cantlistinstitutiontags}</p>{/if}
{if $tags && !$new}
<p class="lead view-description">{str tag=institutiontagsdescription}</p>
<div class="panel panel-default">
<div id="institutiontags" class="list-group">
<div id="institutiontags" class="list-group">
{foreach $tags tag}
<div class="list-group-item r0 ">
<div class="row">
<div class="col-md-9">
<h3 class="title list-group-item-heading" title="{$tag->tag}">
{$tag->tag}
</h3>
</div>
<div class="col-md-3">
<div class="inner-link btn-action-list">
<div class="btn-top-right btn-group btn-group-top">
{if $tag->count <= 0}
<a href="{$WWWROOT}admin/users/institutiontags.php?delete={$tag->id}&institution={$institution}" title="{str tag=deleteinstitutiontag}" class="btn btn-default btn-xs">
<span class="icon icon-trash icon-lg text-danger" role="presentation" aria-hidden="true"></span>
<span class="sr-only">{str tag=deleteinstitutiontag}</span>
</a>
{else}
{str tag=timesused} {$tag->count}
{/if}
</div>
</div>
</div>
<div class="panel panel-default view-container">
<div class="table-responsive">
<table class="fullwidth table table-striped">
<thead>
<tr>
<th>{str tag="tag"}</th>
<th>{str tag="timesused"}</th>
<th><span class="accessible-hidden sr-only">{str tag=edit}</span></th>
</tr>
</thead>
<tbody>
{foreach from=$tags item=tag}
<tr>
<td>{$tag->tag}</td>
<td>{$tag->count}</td>
<td class="center">
<div class="pull-right">
{if $tag->count <= 0}
<a href="{$WWWROOT}admin/users/institutiontags.php?delete={$tag->id}&institution={$institution}" title="{str tag=deleteinstitutiontag}" class="btn btn-default btn-xs">
<span class="icon icon-trash icon-lg text-danger" role="presentation" aria-hidden="true"></span>
<span class="sr-only">{str tag=deleteinstitutiontagspecific arg1=$tag->tag}</span>
</a>
{else}
{str tag=usedtagscantbedeleted}
{/if}
</div>
</div>
{/foreach}
</div>
</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
{$pagination|safe}
{if $pagination_js}
......@@ -40,6 +40,7 @@
{$pagination_js|safe}
</script>
{/if}
</div>
{else}
{if $new}
{$form|safe}
......
......@@ -233,6 +233,25 @@ function get_basic_elements() {
$ownerformatoptions[FORMAT_NAME_STUDENTID] = sprintf($formatstring, get_string('studentid'), $studentid);
}
$createtagsoptions = array();
$typecast = is_postgres() ? '::varchar' : '';
if ($selecttags = get_records_sql_array("
SELECT (
CASE
WHEN t.tag LIKE 'tagid_%' THEN CONCAT(i.displayname, ': ', t2.tag)
ELSE t.tag
END) AS tag, t.resourcetype, t.id
FROM {tag} t
LEFT JOIN {tag} t2 ON t2.id" . $typecast . " = SUBSTRING(t.tag, 7)
LEFT JOIN {institution} i ON i.name = t2.ownerid
WHERE t.ownertype = ? AND t.ownerid = ?
AND t.resourcetype IN ('artefact', 'blocktype')
ORDER BY tag ASC", array('user', $USER->id))) {
foreach ($selecttags as $k => $tag) {
$createtagsoptions[$tag->tag] = $tag->tag;
}
}
$elements = array(
'title' => array(
'type' => 'text',
......@@ -266,6 +285,20 @@ function get_basic_elements() {
'help' => true,
)
);
if (!($group || $institution) && $createtagsoptions) {
$elements['createtags'] = array(
'type' => 'select',
'title' => get_string('createtags', 'view'),
'description' => get_string('createtagsdesc', 'view'),
'options' => $createtagsoptions,
'isSelect2' => true,
'class' => 'js-select2',
'multiple' => true,
'defaultvalue' => null,
'width' => '280px',
'help' => true,
);
}
if ($group) {
$grouproles = $USER->get('grouproles');
if ($grouproles[$group] == 'admin') {
......@@ -636,8 +669,39 @@ function set_view_layout(Pieform $form, $values){
$view->set('layout', $newlayout); //layout
}
function create_block($bt, $configdata, $view, $column, $blocktags = null) {
if ($bt == 'taggedposts') {
$tagselect = $configdata['tagselect'];
unset($configdata['tagselect']);
}