Commit 04ea83c9 authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review

Merge "Bug 1837999: Extend the plans functionality"

parents 621553bf 6a10a44d
......@@ -11,6 +11,6 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config = new stdClass();
$config->version = 2018073000;
$config->release = '1.0.0';
......@@ -11,6 +11,6 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config = new stdClass();
$config->version = 2018073000;
$config->release = '1.0.0';
......@@ -11,6 +11,6 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config = new stdClass();
$config->version = 2018073000;
$config->release = '1.0.0';
......@@ -2,8 +2,8 @@
/**
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -11,7 +11,7 @@
define('INTERNAL', 1);
define('SECTION_PLUGINTYPE', 'core');
require(dirname(dirname(dirname(__FILE__))). '/init.php');
require(dirname(dirname(dirname(dirname(__FILE__)))). '/init.php');
$taskid = param_integer('taskid');
......
......@@ -3,7 +3,7 @@
*
* @package mahara
* @subpackage artefact-plans
* @author Catalyst IT Ltd
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -34,20 +34,21 @@ if ($blockid && !$artefactid) {
// If block sets limit use that instead
$limit = !empty($configdata['count']) ? $configdata['count'] : $limit;
$planid = param_integer('planid');
$tasks = ArtefactTypeTask::get_tasks($planid, $offset, $limit);
$planId = param_integer('planid');
$plan = new ArtefactTypePlan($planId);
$tasks = ArtefactTypeTask::get_tasks($plan, $offset, $limit);
$template = 'artefact:plans:taskrows.tpl';
$template = 'artefact:plans:view/plantasks.tpl';
$baseurl = $bi->get_view()->get_url();
$baseurl .= ((false === strpos($baseurl, '?')) ? '?' : '&') . 'block=' . $blockid . '&planid=' . $planid . '&editing=' . $editing;
$pagination = array(
'baseurl' => $baseurl,
'id' => 'block' . $blockid . '_plan' . $planid . '_pagination',
'datatable' => 'tasklist_' . $blockid . '_plan' . $planid,
'jsonscript' => 'artefact/plans/viewtasks.json.php',
);
$baseurl .= ((false === strpos($baseurl, '?')) ? '?' : '&') . 'block=' . $blockid . '&planid=' . $planId . '&editing=' . $editing;
$pagination = [
'baseurl' => $baseurl,
'id' => 'block' . $blockid . '_plan' . $planId . '_pagination',
'datatable' => 'tasklist_' . $blockid . '_plan' . $planId,
'jsonscript' => 'artefact/plans/block/tasks.json.php',
];
}
ArtefactTypeTask::render_tasks($tasks, $template, $options, $pagination, $editing);
json_reply(false, (object) array('message' => false, 'data' => $tasks));
json_reply(false, (object) ['message' => false, 'data' => $tasks]);
/**
*
* @package mahara
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
*/
function rewriteTaskTitles(blockid, planid) {
jQuery('tasklist_' + blockid + '_plan' + planid + ' a.task-title').each(function() {
jQuery(this).off();
jQuery(this).on('click', function(e) {
e.preventDefault();
var description = jQuery(this).parent().find('div.task-desc');
description.toggleClass('d-none');
});
});
jQuery('tasklist_' + blockid + '_plan' + planid + ' a.task-title').each(function() {
jQuery(this).off();
jQuery(this).on('click', function(e) {
e.preventDefault();
var description = jQuery(this).parent().find('div.task-desc');
description.toggleClass('d-none');
});
});
}
function TaskPager(blockid, planid) {
var self = this;
......@@ -33,7 +42,7 @@ function changeCheckBox(taskid, state) {
function saveCheckBoxChange(taskid) {
var params = {};
params.taskid = taskid;
sendjsonrequest(config.wwwroot + 'artefact/plans/checktask.json.php', params, 'POST', function(data) {
sendjsonrequest(config.wwwroot + 'artefact/plans/block/checktask.json.php', params, 'POST', function(data) {
if (data.data) {
changeCheckBox(data.data.artefact, data.data.state);
}
......
......@@ -2,8 +2,8 @@
/**
*
* @package mahara
* @subpackage blocktype-plans
* @author Catalyst IT Ltd
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -15,7 +15,7 @@ $string['title'] = 'Plans';
$string['description1'] = 'Display a plan (see Content -> Plans)';
$string['defaulttitledescription'] = 'If this is left empty, the title of the plan will be used.';
$string['newerplans'] = 'Newer plans';
$string['noplansselectone'] = 'No plans selected';
$string['noplansselectone1'] = 'No plans yet. Select one in the block configuration.';
$string['olderplans'] = 'Older plans';
$string['planstoshow'] = 'Plan to show';
$string['taskstodisplay'] = 'Tasks to display';
\ No newline at end of file
......@@ -25,7 +25,7 @@ class PluginBlocktypePlans extends MaharaCoreBlocktype {
return array('general' => 22000);
}
/**
/**
* Optional method. If exists, allows this class to decide the title for
* all blockinstances of this type
*/
......@@ -64,19 +64,19 @@ class PluginBlocktypePlans extends MaharaCoreBlocktype {
$plans = array();
$alltasks = array();
$template = 'artefact:plans:taskrows.tpl';
$template = 'artefact:plans:view/plantasks.tpl';
if (($versioning && isset($configdata['existing_artefacts']) && !empty($configdata['existing_artefacts'])) ||
(isset($configdata['artefactids']) && is_array($configdata['artefactids']) && count($configdata['artefactids']) > 0)) {
(isset($configdata['artefactids']) && is_array($configdata['artefactids']) && count($configdata['artefactids']) > 0)) {
if ($versioning) {
// recover the configdata from the version
$blockid = $instance->get('id');
$blocks = $versioning->blocks;
foreach ($blocks as $key => $value) {
if ($value->originalblockid == $blockid) {
$versionblock = $value;
break;
}
if ($value->originalblockid == $blockid) {
$versionblock = $value;
break;
}
}
$configdata = (array)$versionblock->configdata;
$savedplans = $configdata['existing_artefacts'];
......@@ -86,7 +86,8 @@ class PluginBlocktypePlans extends MaharaCoreBlocktype {
}
foreach ($savedplans as $planid => $plancontent) {
try {
$tasks = isset($plancontent->tasks) ? (array)$plancontent->tasks : ArtefactTypeTask::get_tasks($planid, 0, $limit);
$plan = artefact_instance_from_id($planid);
$tasks = isset($plancontent->tasks) ? (array)$plancontent->tasks : ArtefactTypeTask::get_tasks($plan, 0, $limit);
$blockid = $instance->get('id');
if ($exporter || $versioning) {
$pagination = false;
......@@ -98,7 +99,7 @@ class PluginBlocktypePlans extends MaharaCoreBlocktype {
'baseurl' => $baseurl,
'id' => 'block' . $blockid . '_plan' . $planid . '_pagination',
'datatable' => 'tasklist_' . $blockid . '_plan' . $planid,
'jsonscript' => 'artefact/plans/viewtasks.json.php',
'jsonscript' => 'artefact/plans/block/tasks.json.php',
);
}
$configdata['view'] = $instance->get('view');
......@@ -137,7 +138,7 @@ class PluginBlocktypePlans extends MaharaCoreBlocktype {
}
}
else {
$smarty->assign('noplans', get_string('noplansselectone', 'blocktype.plans/plans'));
$smarty->assign('noplans', get_string('noplansselectone1', 'blocktype.plans/plans'));
}
$smarty->assign('editing', $editing);
......
......@@ -3,7 +3,7 @@
*
* @package mahara
* @subpackage blocktype-plans
* @author Catalyst IT Ltd
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......
<?php
/**
*
* @package mahara
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
*/
define('INTERNAL', 1);
define('JSON', 1);
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
require_once(get_config('libroot') . 'view.php');
require_once(get_config('libroot') . 'collection.php');
$id = param_integer('id');
$collection = new \Collection($id);
$viewIds = $collection->get_viewids();
if (empty($viewIds)) {
json_reply(true, array(
'message' => get_string('noviewsincollection', 'collection'),
));
}
$firstViewId = $viewIds[0];
if (!can_view_view($firstViewId)) {
json_reply('local', get_string('accessdenied', 'error'));
}
$firstview = new View($firstViewId);
$collection = $firstview->get('collection');
$smarty = smarty_core();
$smarty->assign('viewid', $id);
$smarty->assign('collectiontitle', $collection->get('name'));
$smarty->assign('ownername', $firstview->formatted_owner());
$smarty->assign('collectiondescription', $collection->get('description'));
$smarty->assign('viewcontent', $firstview->build_rows(false, true));
$smarty->assign('tags', $firstview->get('tags'));
$shownav = $collection->get('navigation');
if ($shownav) {
if ($views = $collection->get('views')) {
if (count($views['views']) > 1) {
$smarty->assign('collection', array_chunk($views['views'], 5));
}
}
}
$html = $smarty->fetch('collection/viewcontent.tpl');
json_reply(false, array(
'message' => null,
'html' => $html,
));
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="artefact/plans/db" VERSION="20100525" COMMENT="XMLDB file for MyPlans Artefact Mahara tables"
<XMLDB PATH="artefact/plans/db" VERSION="20190717" COMMENT="XMLDB file for Plans artefact Mahara tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<!-- This table is supposed to have a 1-1 relation with every row in the
artefact table with artefacttype = 'task'. It contains additional data
that isn't in the artefact table. -->
that doesn't exist in the artefact table. -->
<TABLE NAME="artefact_plans_task">
<FIELDS>
<FIELD NAME="artefact" TYPE="int" LENGTH="10" SEQUENCE="true" NOTNULL="true" />
<FIELD NAME="startdate" TYPE="datetime" NOTNULL="false" />
<FIELD NAME="completiondate" TYPE="datetime" NOTNULL="false" />
<FIELD NAME="completed" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="reminder" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true"/>
<FIELD NAME="remindermailsent" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="taskview" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="outcome" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="outcometype" TYPE="char" LENGTH="20" NOTNULL="false" />
<FIELD NAME="template" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="roottemplatetask" TYPE="int" LENGTH="10" NOTNULL="false"/>
<FIELD NAME="mandatory" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="rootgrouptask" TYPE="int" LENGTH="10" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="artefact" />
<KEY NAME="artefactfk" TYPE="foreign" FIELDS="artefact" REFTABLE="artefact" REFFIELDS="id" />
</KEYS>
<INDEXES>
<INDEX NAME="rootgrouptaskix" UNIQUE="false" FIELDS="rootgrouptask"/>
<INDEX NAME="roottemplatetaskix" UNIQUE="false" FIELDS="roottemplatetask"/>
<INDEX NAME="taskviewix" UNIQUE="false" FIELDS="taskview"/>
<INDEX NAME="outcomeix" UNIQUE="false" FIELDS="outcome"/>
<INDEX NAME="outcometypeix" UNIQUE="false" FIELDS="outcometype"/>
<INDEX NAME="completedremindermailsentix" UNIQUE="false" FIELDS="completed,remindermailsent"/>
</INDEXES>
</TABLE>
<TABLE NAME="artefact_plans_plan">
<FIELDS>
<FIELD NAME="artefact" TYPE="int" LENGTH="10" SEQUENCE="true" NOTNULL="true" />
<FIELD NAME="template" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
<FIELD NAME="roottemplate" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="rootgroupplan" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="selectionplan" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="artefact" />
<KEY NAME="artefactfk" TYPE="foreign" FIELDS="artefact" REFTABLE="artefact" REFFIELDS="id" />
</KEYS>
<INDEXES>
<INDEX NAME="roottemplateix" UNIQUE="false" FIELDS="roottemplate"/>
<INDEX NAME="rootgroupplanix" UNIQUE="false" FIELDS="rootgroupplan"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
......@@ -3,7 +3,7 @@
*
* @package mahara
* @subpackage artefact-plans
* @author Catalyst IT Ltd
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -17,5 +17,87 @@ function xmldb_artefact_plans_upgrade($oldversion=0) {
set_field('artefact', 'container', 1, 'artefacttype', 'plan');
}
if ($oldversion < 2019071700) {
$table = new XMLDBTable('artefact_plans_plan');
$table->addFieldInfo('artefact', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
$table->addFieldInfo('template', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, null, null, 0);
$table->addFieldInfo('rootgroupplan', XMLDB_TYPE_INTEGER, 10);
$table->addFieldInfo('selectionplan', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, null, null, 0);
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, ['artefact']);
$table->addKeyInfo('artefactfk', XMLDB_KEY_FOREIGN, ['artefact'], 'artefact', ['id']);
//ToDo: Create unique Index using rootgroupplan and artefact
$table->addIndexInfo('rootgroupplanix', XMLDB_INDEX_NOTUNIQUE, ['rootgroupplan']);
create_table($table);
execute_sql('INSERT INTO {artefact_plans_plan} (artefact)
SELECT id FROM {artefact} WHERE artefacttype = ?', ['plan']);
$table = new XMLDBTable('artefact_plans_task');
$table->addFieldInfo('startdate', XMLDB_TYPE_DATETIME, null, null, null, null, null, null, null, 'artefact');
$table->addFieldInfo('reminder', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED);
$table->addFieldInfo('remindermailsent', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, null, null, 0);
$table->addFieldInfo('taskview', XMLDB_TYPE_INTEGER, 10);
$table->addFieldInfo('outcome', XMLDB_TYPE_INTEGER, 10);
$table->addFieldInfo('outcometype', XMLDB_TYPE_CHAR, 20);
$table->addFieldInfo('template', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, null, null, 0);
$table->addFieldInfo('mandatory', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, null, null, 0);
$table->addFieldInfo('rootgrouptask', XMLDB_TYPE_INTEGER, 10);
//Greyed out to ensure, that a usertask will not be deleted, when the root group task is.
//$table->addKeyInfo('rootgrouptaskfk', XMLDB_KEY_FOREIGN, ['rootgrouptask'], 'artefact', ['id']);
$table->addIndexInfo('rootgrouptaskix', XMLDB_INDEX_NOTUNIQUE, ['rootgrouptask']);
$table->addIndexInfo('taskviewix', XMLDB_INDEX_NOTUNIQUE, ['taskview']);
$table->addIndexInfo('outcomeix', XMLDB_INDEX_NOTUNIQUE, ['outcome']);
$table->addIndexInfo('outcometypeix', XMLDB_INDEX_NOTUNIQUE, ['outcometype']);
//Combined index to speed up cron_reminder_check
$table->addIndexInfo('completedremindermailsentix', XMLDB_INDEX_NOTUNIQUE, ['completed,remindermailsent']);
foreach ($table->getFields() as $field) {
add_field($table, $field);
}
foreach ($table->getKeys() as $key) {
add_key($table, $key);
}
foreach ($table->getIndexes() as $index) {
add_index($table, $index);
}
}
if ($oldversion < 2019091300) {
$table = new XMLDBTable('artefact_plans_plan');
$field = new XMLDBField('roottemplate');
$field->setAttributes(XMLDB_TYPE_INTEGER, 10, null, null, null, null, null, null, 'template');
add_field($table, $field);
$index = new XMLDBIndex('roottemplateix');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, ['roottemplate']);
add_index($table, $index);
}
if ($oldversion < 2019091600) {
$table = new XMLDBTable('artefact_plans_task');
$field = new XMLDBField('roottemplatetask');
$field->setAttributes(XMLDB_TYPE_INTEGER, 10, null, null, null, null, null, null, 'template');
add_field($table, $field);
// We have to drop and recreate this index to make the system determine consistent index names
$index = new XMLDBIndex('rootgrouptaskix');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, ['rootgrouptask']);
drop_index($table, $index);
add_index($table, $index);
$index = new XMLDBIndex('roottemplatetaskix');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, ['roottemplatetask']);
add_index($table, $index);
}
return true;
}
......@@ -2,8 +2,8 @@
/**
*
* @package mahara
* @subpackage artefact-plans-export-html
* @author Catalyst IT Ltd
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -44,13 +44,9 @@ class HtmlExportPlans extends HtmlExportArtefactPlugin {
}
$smarty->assign('plans', $plans);
if (count($plans)) {
$smarty->assign('stryouhaveplans', get_string('youhavenplan', 'artefact.plans', count($plans), count($plans)));
}
return array(
'title' => get_string('Plans', 'artefact.plans'),
'description' => $smarty->fetch('export:html/plans:summary.tpl'),
'description' => $smarty->fetch('artefact:plans:export/html/summary.tpl'),
);
}
......
......@@ -2,8 +2,8 @@
/**
*
* @package mahara
* @subpackage artefact-plans-export-leap
* @author Catalyst IT Ltd
* @subpackage artefact-plans
* @author Catalyst IT Ltd, Alexander Del Ponte
* @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.
*
......@@ -18,7 +18,7 @@ class LeapExportElementPlan extends LeapExportElement {
}
public function get_template_path() {
return 'export:leap/plans:plan.tpl';
return 'artefact:plans:export/leap/plan.tpl';
}
}
......
<?php
/**
*
* @package mahara
* @subpackage artefact-plans
* @author Alexander Del Ponte
* @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.
*
*/
use artefact\plans\tools\PlansTools;
define('INTERNAL', 1);
define('JSON', 1);
try {
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
require(dirname(dirname(__FILE__)) . '/tools/PlansTools.php');
safe_require('artefact', 'plans');
if (!PluginArtefactPlans::is_active()) {
throw new AccessDeniedException(get_string('plugindisableduser', 'mahara', get_string('Plans', 'artefact.plans')));
}
$planId = param_integer('planid');
$userPlanTemplate = new ArtefactTypePlan($planId);
$result = PlansTools::getArrayOfUserPlanTemplateForForm($userPlanTemplate);
}
catch (Exception $e) {
json_reply(true, $e->getMessage());
die;
}
json_reply(false, (object) $result);
<?php
/**
*
* @package mahara
* @subpackage artefact-plans
* @author Alexander Del Ponte
* @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.
*
*/
use artefact\plans\tools\PlansTools;
define('INTERNAL', 1);
define('JSON', 1);
try {
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
require(dirname(dirname(__FILE__)) . '/tools/PlansTools.php');
safe_require('artefact', 'plans');
if (!PluginArtefactPlans::is_active()) {
throw new AccessDeniedException(get_string('plugindisableduser', 'mahara', get_string('Plans', 'artefact.plans')));
}
$rootGroupTaskId = param_integer('taskid');
$chosen = param_boolean('chosen');
$rootGroupTask = new ArtefactTypeTask($rootGroupTaskId);
$rootGroupPlan = new ArtefactTypePlan((int)$rootGroupTask->get('parent'));
if (!$USER->can_view_artefact($rootGroupPlan)) {
throw new AccessDeniedException();
}
if ($USER->can_edit_artefact($rootGroupPlan)) {
throw new Exception(get_string('wrongroleforfunction', 'artefact.plans'));
}
if (!$rootGroupPlan->is_selection_plan()) {
throw new MaharaException(get_string('noselectiontask','artefact.plans'));
}
$userTask = PlansTools::findCorrespondingUserTaskByRootGroupTaskId($rootGroupTaskId);
// $chosen represents the selection state of the frontend. If it is not sync to the backend, send info.
if (empty($userTask) === $chosen) {
global $SESSION;
$SESSION->add_error_msg(get_string('selectionstatechangedpagereload','artefact.plans'));
json_reply(true, null, 1);
die;
}
$userPlan = PlansTools::findCorrespondingUserPlanByRootGroupPlanId($rootGroupPlan->get('id'));
if (!$userPlan) {
$userPlan = PlansTools::createUserPlanFromGroupPlan($rootGroupPlan);
}
if ($userTask) {
$portfolioElement = PlansTools::getPortfolioElementByTypeAndId($rootGroupTask->get('outcometype'), $rootGroupTask->get('outcome'));
$outcomeurl = PlansTools::createOutcomeUrlForPortfolioElement($portfolioElement);
if ($outcomeurl) {
$buttons = '';
$buttons .= '<a href="' . $outcomeurl . '" class="btn btn-secondary btn-sm btn-outcome" title="' . get_string('editassignedoutcome', 'artefact.plans') . '">
<span class="icon icon-file icon-lg" role="presentation" aria-hidden="true"></span>
</a>';