Portfolio: Allow advanced selection of who can view the comments - refs BT#18201

pull/4600/head
Angel Fernando Quiroz Campos 3 years ago
parent 84135b4045
commit 90d9d4696c
  1. 201
      main/inc/lib/PortfolioController.php
  2. 4
      main/install/configuration.dist.php
  3. 11
      main/portfolio/index.php
  4. 4
      main/template/default/portfolio/items.html.twig
  5. 2
      main/template/default/portfolio/view.html.twig
  6. 8
      src/Chamilo/CoreBundle/Entity/Portfolio.php
  7. 24
      src/Chamilo/CoreBundle/Entity/PortfolioComment.php

@ -1172,16 +1172,48 @@ class PortfolioController
$commentsRepo = $this->em->getRepository(PortfolioComment::class);
$query = $commentsRepo->createQueryBuilder('comment')
->where('comment.item = :item')
$commentsQueryBuilder = $commentsRepo->createQueryBuilder('comment');
$commentsQueryBuilder->where('comment.item = :item');
if ($this->advancedSharingEnabled) {
$commentsQueryBuilder
->leftJoin(
CItemProperty::class,
'cip',
Join::WITH,
"cip.ref = comment.id
AND cip.tool = :cip_tool
AND cip.course = :course
AND cip.lasteditType = 'visible'
AND cip.toUser = :current_user"
)
->andWhere(
sprintf(
'comment.visibility = %d
OR (
comment.visibility = %d AND cip IS NOT NULL OR comment.author = :current_user
)',
PortfolioComment::VISIBILITY_VISIBLE,
PortfolioComment::VISIBILITY_PER_USER
)
)
->setParameter('cip_tool', TOOL_PORTFOLIO_COMMENT)
->setParameter('current_user', $this->owner->getId())
->setParameter('course', $item->getCourse())
;
}
$comments = $commentsQueryBuilder
->orderBy('comment.root, comment.lft', 'ASC')
->setParameter('item', $item)
->getQuery();
->getQuery()
->getArrayResult()
;
$clockIcon = Display::returnFontAwesomeIcon('clock-o', '', true);
$commentsHtml = $commentsRepo->buildTree(
$query->getArrayResult(),
$comments,
[
'decorate' => true,
'rootOpen' => '<div class="media-list">',
@ -1296,6 +1328,13 @@ class PortfolioController
}
if ($this->commentBelongsToOwner($comment)) {
if ($this->advancedSharingEnabled) {
$commentActions[] = Display::url(
Display::return_icon('visible.png', get_lang('ChooseRecipients')),
$this->baseUrl.http_build_query(['action' => 'comment_visiblity_choose', 'id' => $comment->getId()])
);
}
$commentActions[] = Display::url(
Display::return_icon('edit.png', get_lang('Edit')),
$this->baseUrl.http_build_query(['action' => 'edit_comment', 'id' => $comment->getId()])
@ -1335,6 +1374,7 @@ class PortfolioController
$template->assign('baseurl', $this->baseUrl);
$template->assign('item', $item);
$template->assign('item_content', $this->generateItemContent($item));
$template->assign('count_comments', count($comments));
$template->assign('comments', $commentsHtml);
$template->assign('form', $form);
$template->assign('attachment_list', $this->generateAttachmentList($item));
@ -3182,6 +3222,131 @@ class PortfolioController
);
}
public function commentVisibilityChooser(PortfolioComment $comment)
{
global $interbreadcrumb;
if (!$this->commentBelongsToOwner($comment)) {
api_not_allowed(true);
}
$em = Database::getManager();
$tblItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
$courseId = $this->course->getId();
$sessionId = $this->session ? $this->session->getId() : 0;
$item = $comment->getItem();
$formAction = $this->baseUrl.http_build_query(['action' => 'comment_visiblity_choose', 'id' => $comment->getId()]);
$form = new FormValidator('visibility', 'post', $formAction);
CourseManager::addUserGroupMultiSelect($form, ['USER:'.$this->owner->getId()]);
$form->addLabel(
'',
Display::return_message(
get_lang('OnlySelectedUsersWillSeeTheContent')
.'<br>'.get_lang('LeaveEmptyToEnableTheContentForEveryone'),
'info',
false
)
);
$form->addButtonSave(get_lang('Save'));
if ($form->validate()) {
$values = $form->exportValues();
$recipients = CourseManager::separateUsersGroups($values['users'])['users'];
$courseInfo = api_get_course_info_by_id($courseId);
Database::delete(
$tblItemProperty,
[
'c_id = ? ' => [$courseId],
'AND tool = ? AND ref = ? ' => [TOOL_PORTFOLIO_COMMENT, $comment->getId()],
'AND lastedit_type = ? ' => ['visible'],
]
);
foreach ($recipients as $userId) {
api_item_property_update(
$courseInfo,
TOOL_PORTFOLIO_COMMENT,
$comment->getId(),
'visible',
api_get_user_id(),
[],
$userId,
'',
'',
$sessionId
);
}
if (empty($recipients)) {
$comment->setVisibility(PortfolioComment::VISIBILITY_VISIBLE);
} else {
$comment->setVisibility(PortfolioComment::VISIBILITY_PER_USER);
}
$em->flush();
Display::addFlash(
Display::return_message(get_lang('VisibilityChanged'), 'success')
);
header("Location: $formAction");
exit;
}
$result = Database::select(
'to_user_id',
$tblItemProperty,
[
'where' => [
'c_id = ? ' => [$courseId],
'AND tool = ? AND ref = ? ' => [TOOL_PORTFOLIO_COMMENT, $comment->getId()],
'AND to_user_id IS NOT NULL ' => [],
],
]
);
$recipients = array_map(
function (array $itemProperty): string {
return 'USER:'.$itemProperty['to_user_id'];
},
$result
);
$form->setDefaults(['users' => $recipients]);
$form->protect();
$interbreadcrumb[] = [
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
$interbreadcrumb[] = [
'name' => $item->getExcerpt(40),
'url' => $this->baseUrl.http_build_query(['action' => 'view', 'id' => $item->getId()]),
];
$interbreadcrumb[] = [
'name' => $comment->getExcerpt(40),
'url' => $this->baseUrl
.http_build_query(['action' => 'view', 'id' => $item->getId()])
.'#comment-'.$comment->getId(),
];
$actions = [];
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.http_build_query(['action' => 'view', 'id' => $item->getId()])
);
$this->renderView(
$form->returnForm(),
get_lang('ChooseRecipients'),
$actions
);
}
private function isAllowed(): bool
{
$isSubscribedInCourse = false;
@ -4179,6 +4344,34 @@ class PortfolioController
;
}
if ($this->advancedSharingEnabled) {
$queryBuilder
->leftJoin(
CItemProperty::class,
'cip',
Join::WITH,
"cip.ref = c.id
AND cip.tool = :cip_tool
AND cip.course = :course
AND cip.lasteditType = 'visible'
AND cip.toUser = :current_user"
)
->andWhere(
sprintf(
'c.visibility = %d
OR (
c.visibility = %d AND cip IS NOT NULL OR c.author = :current_user
)',
PortfolioComment::VISIBILITY_VISIBLE,
PortfolioComment::VISIBILITY_PER_USER
)
)
->setParameter('cip_tool', TOOL_PORTFOLIO_COMMENT)
->setParameter('current_user', $this->owner->getId())
->setParameter('course', $this->course)
;
}
$queryBuilder->orderBy('c.date', 'DESC');
return $queryBuilder->getQuery()->getResult();

@ -1087,7 +1087,9 @@ ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472613FECDF FOREIGN KEY (se
// and follow the instructions about the @ORM\Entity() line
// - launch composer install to rebuild the autoload.php
//$_configuration['allow_portfolio_tool'] = false;
// Allow advanced selection of who can view the posts.
// Allow advanced selection of who can view the posts and comments. It requires DB changes:
// ALTER TABLE portfolio_comment ADD visibility SMALLINT DEFAULT 1 NOT NULL;
// Then add the "@" symbol to the CPortfolioComment::$visibility property in the ORM\Column() line.
//$_configuration['portfolio_advanced_sharing'] = false;
// Enable best score column in gradebook. Previously called disable_gradebook_stats

@ -156,6 +156,17 @@ switch ($action) {
$controller->itemVisibilityChooser($item);
break;
case 'comment_visiblity_choose':
$id = $httpRequest->query->getInt('id');
$comment = $em->find(PortfolioComment::class, $id);
if (empty($comment)) {
break;
}
$controller->commentVisibilityChooser($comment);
break;
case 'delete_item':
$id = $httpRequest->query->getInt('id');

@ -9,7 +9,7 @@
<section class="portfolio-items">
{% for item in items %}
{% set item_url = baseurl ~ {'action':'view', 'id':item.id}|url_encode %}
{% set comments = item.lastComments %}
{% set comments = item.lastComments(3, is_advanced_sharing_enabled) %}
<div class="panel panel-default">
<article class="panel-body portfolio-item" id="portfolio-item-{{ item.id }}">
@ -117,7 +117,7 @@
{% if comments|length > 0 %}
<h4>
<a href="{{ item_url }}#portfolio-item-comments">
{{ 'XComments'|get_lang|format(item.comments.count) }}
{{ 'XComments'|get_lang|format(comments|length) }}
</a>
&centerdot;
<a href="{{ item_url }}#frm_comment">{{ 'AddNewComment'|get_lang }}</a>

@ -58,7 +58,7 @@
<section id="portfolio-item-comments">
<h1 class="h3">
<span class="fa fa-fw fa-comment-o" aria-hidden="true"></span>
{{ 'XComments'|get_lang|format(item.comments.count) }}
{{ 'XComments'|get_lang|format(count_comments) }}
</h1>
{{ comments }}

@ -376,13 +376,19 @@ class Portfolio
return $this->comments;
}
public function getLastComments(int $number = 3): Collection
public function getLastComments(int $number = 3, bool $avoidPerUserVisibility = false): Collection
{
$criteria = Criteria::create();
$criteria
->orderBy(['date' => 'DESC'])
->setMaxResults($number);
if ($avoidPerUserVisibility) {
$criteria->where(
Criteria::expr()->neq('visibility', PortfolioComment::VISIBILITY_PER_USER)
);
}
return $this->comments->matching($criteria);
}

@ -22,6 +22,17 @@ use Gedmo\Mapping\Annotation as Gedmo;
*/
class PortfolioComment
{
public const VISIBILITY_VISIBLE = 1;
public const VISIBILITY_PER_USER = 2;
/**
* @var int
*
* Add @ to the next line if portfolio_advanced_sharing config setting is true
* ORM\Column(name="visibility", type="smallint", options={"default": 1})
*/
protected $visibility = 1;
/**
* @var int
*
@ -128,6 +139,7 @@ class PortfolioComment
{
$this->isImportant = false;
$this->children = new ArrayCollection();
$this->visibility = 1;
}
public function getId(): int
@ -268,4 +280,16 @@ class PortfolioComment
return $this;
}
public function getVisibility(): int
{
return $this->visibility;
}
public function setVisibility(int $visibility): PortfolioComment
{
$this->visibility = $visibility;
return $this;
}
}

Loading…
Cancel
Save