Merge pull request #4600 from AngelFQC/BT18201

Portfolio: Add portfolio_advanced_sharing config setting
pull/4605/head
Nicolas Ducoulombier 3 years ago committed by GitHub
commit 9dc1ba04fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 466
      main/inc/lib/PortfolioController.php
  2. 4
      main/install/configuration.dist.php
  3. 23
      main/portfolio/index.php
  4. 35
      main/template/default/portfolio/items.html.twig
  5. 2
      main/template/default/portfolio/view.html.twig
  6. 11
      src/Chamilo/CoreBundle/Entity/Portfolio.php
  7. 24
      src/Chamilo/CoreBundle/Entity/PortfolioComment.php

@ -12,6 +12,7 @@ use Chamilo\CoreBundle\Entity\PortfolioCategory;
use Chamilo\CoreBundle\Entity\PortfolioComment; use Chamilo\CoreBundle\Entity\PortfolioComment;
use Chamilo\CoreBundle\Entity\PortfolioRelTag; use Chamilo\CoreBundle\Entity\PortfolioRelTag;
use Chamilo\CoreBundle\Entity\Tag; use Chamilo\CoreBundle\Entity\Tag;
use Chamilo\CourseBundle\Entity\CItemProperty;
use Chamilo\UserBundle\Entity\User; use Chamilo\UserBundle\Entity\User;
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Join;
use Mpdf\MpdfException; use Mpdf\MpdfException;
@ -43,6 +44,10 @@ class PortfolioController
* @var \Doctrine\ORM\EntityManager * @var \Doctrine\ORM\EntityManager
*/ */
private $em; private $em;
/**
* @var bool
*/
private $advancedSharingEnabled;
/** /**
* PortfolioController constructor. * PortfolioController constructor.
@ -57,6 +62,9 @@ class PortfolioController
$cidreq = api_get_cidreq(); $cidreq = api_get_cidreq();
$this->baseUrl = api_get_self().'?'.($cidreq ? $cidreq.'&' : ''); $this->baseUrl = api_get_self().'?'.($cidreq ? $cidreq.'&' : '');
$this->advancedSharingEnabled = true === api_get_configuration_value('portfolio_advanced_sharing')
&& $this->course;
} }
/** /**
@ -1129,7 +1137,23 @@ class PortfolioController
global $interbreadcrumb; global $interbreadcrumb;
if (!$this->itemBelongToOwner($item)) { if (!$this->itemBelongToOwner($item)) {
if ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN if ($this->advancedSharingEnabled) {
$courseInfo = api_get_course_info_by_id($this->course->getId());
$sessionId = $this->session ? $this->session->getId() : 0;
$itemPropertyVisiblity = api_get_item_visibility(
$courseInfo,
TOOL_PORTFOLIO,
$item->getId(),
$sessionId,
$this->owner->getId(),
'visible'
);
if ($item->getVisibility() === Portfolio::VISIBILITY_PER_USER && 1 !== $itemPropertyVisiblity) {
api_not_allowed(true);
}
} elseif ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN
|| ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER && !api_is_allowed_to_edit()) || ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER && !api_is_allowed_to_edit())
) { ) {
api_not_allowed(true); api_not_allowed(true);
@ -1148,16 +1172,48 @@ class PortfolioController
$commentsRepo = $this->em->getRepository(PortfolioComment::class); $commentsRepo = $this->em->getRepository(PortfolioComment::class);
$query = $commentsRepo->createQueryBuilder('comment') $commentsQueryBuilder = $commentsRepo->createQueryBuilder('comment');
->where('comment.item = :item') $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') ->orderBy('comment.root, comment.lft', 'ASC')
->setParameter('item', $item) ->setParameter('item', $item)
->getQuery(); ->getQuery()
->getArrayResult()
;
$clockIcon = Display::returnFontAwesomeIcon('clock-o', '', true); $clockIcon = Display::returnFontAwesomeIcon('clock-o', '', true);
$commentsHtml = $commentsRepo->buildTree( $commentsHtml = $commentsRepo->buildTree(
$query->getArrayResult(), $comments,
[ [
'decorate' => true, 'decorate' => true,
'rootOpen' => '<div class="media-list">', 'rootOpen' => '<div class="media-list">',
@ -1272,6 +1328,13 @@ class PortfolioController
} }
if ($this->commentBelongsToOwner($comment)) { 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( $commentActions[] = Display::url(
Display::return_icon('edit.png', get_lang('Edit')), Display::return_icon('edit.png', get_lang('Edit')),
$this->baseUrl.http_build_query(['action' => 'edit_comment', 'id' => $comment->getId()]) $this->baseUrl.http_build_query(['action' => 'edit_comment', 'id' => $comment->getId()])
@ -1311,6 +1374,7 @@ class PortfolioController
$template->assign('baseurl', $this->baseUrl); $template->assign('baseurl', $this->baseUrl);
$template->assign('item', $item); $template->assign('item', $item);
$template->assign('item_content', $this->generateItemContent($item)); $template->assign('item_content', $this->generateItemContent($item));
$template->assign('count_comments', count($comments));
$template->assign('comments', $commentsHtml); $template->assign('comments', $commentsHtml);
$template->assign('form', $form); $template->assign('form', $form);
$template->assign('attachment_list', $this->generateAttachmentList($item)); $template->assign('attachment_list', $this->generateAttachmentList($item));
@ -1323,7 +1387,7 @@ class PortfolioController
$itemSession ? $itemSession->getId() : 0 $itemSession ? $itemSession->getId() : 0
); );
if ($propertyInfo) { if ($propertyInfo && empty($propertyInfo['to_user_id'])) {
$template->assign( $template->assign(
'last_edit', 'last_edit',
[ [
@ -1363,23 +1427,30 @@ class PortfolioController
$this->baseUrl.http_build_query(['action' => 'template', 'id' => $item->getId()]) $this->baseUrl.http_build_query(['action' => 'template', 'id' => $item->getId()])
); );
$visibilityUrl = $this->baseUrl.http_build_query(['action' => 'visibility', 'id' => $item->getId()]); if ($this->advancedSharingEnabled) {
if ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN) {
$actions[] = Display::url(
Display::return_icon('invisible.png', get_lang('MakeVisible'), [], ICON_SIZE_MEDIUM),
$visibilityUrl
);
} elseif ($item->getVisibility() === Portfolio::VISIBILITY_VISIBLE) {
$actions[] = Display::url(
Display::return_icon('visible.png', get_lang('MakeVisibleForTeachers'), [], ICON_SIZE_MEDIUM),
$visibilityUrl
);
} elseif ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER) {
$actions[] = Display::url( $actions[] = Display::url(
Display::return_icon('eye-slash.png', get_lang('MakeInvisible'), [], ICON_SIZE_MEDIUM), Display::return_icon('visible.png', get_lang('ChooseRecipients'), [], ICON_SIZE_MEDIUM),
$visibilityUrl $this->baseUrl.http_build_query(['action' => 'item_visiblity_choose', 'id' => $item->getId()])
); );
} else {
$visibilityUrl = $this->baseUrl.http_build_query(['action' => 'visibility', 'id' => $item->getId()]);
if ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN) {
$actions[] = Display::url(
Display::return_icon('invisible.png', get_lang('MakeVisible'), [], ICON_SIZE_MEDIUM),
$visibilityUrl
);
} elseif ($item->getVisibility() === Portfolio::VISIBILITY_VISIBLE) {
$actions[] = Display::url(
Display::return_icon('visible.png', get_lang('MakeVisibleForTeachers'), [], ICON_SIZE_MEDIUM),
$visibilityUrl
);
} elseif ($item->getVisibility() === Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER) {
$actions[] = Display::url(
Display::return_icon('eye-slash.png', get_lang('MakeInvisible'), [], ICON_SIZE_MEDIUM),
$visibilityUrl
);
}
} }
$actions[] = Display::url( $actions[] = Display::url(
@ -3033,6 +3104,249 @@ class PortfolioController
exit; exit;
} }
public function itemVisibilityChooser(Portfolio $item)
{
global $interbreadcrumb;
if (!$this->itemBelongToOwner($item)) {
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;
$formAction = $this->baseUrl.http_build_query(['action' => 'item_visiblity_choose', 'id' => $item->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, $item->getId()],
'AND lastedit_type = ? ' => ['visible'],
]
);
foreach ($recipients as $userId) {
api_item_property_update(
$courseInfo,
TOOL_PORTFOLIO,
$item->getId(),
'visible',
api_get_user_id(),
[],
$userId,
'',
'',
$sessionId
);
}
if (empty($recipients)) {
$item->setVisibility(Portfolio::VISIBILITY_VISIBLE);
} else {
$item->setVisibility(Portfolio::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, $item->getId()],
'AND to_user_id IS NOT NULL ' => [],
],
]
);
$recipients = array_map(
function (array $item): string {
return 'USER:'.$item['to_user_id'];
},
$result
);
$form->setDefaults(['users' => $recipients]);
$form->protect();
$interbreadcrumb[] = [
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
$interbreadcrumb[] = [
'name' => $item->getTitle(true),
'url' => $this->baseUrl.http_build_query(['action' => 'view', 'id' => $item->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
);
}
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 private function isAllowed(): bool
{ {
$isSubscribedInCourse = false; $isSubscribedInCourse = false;
@ -3367,14 +3681,38 @@ class PortfolioController
$queryBuilder->andWhere('pi.session IS NULL'); $queryBuilder->andWhere('pi.session IS NULL');
} }
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE]; if ($this->advancedSharingEnabled) {
$queryBuilder
->leftJoin(
CItemProperty::class,
'cip',
Join::WITH,
"cip.ref = pi.id
AND cip.tool = :cip_tool
AND cip.course = pi.course
AND cip.lasteditType = 'visible'
AND cip.toUser = :current_user"
)
->andWhere(
sprintf(
'pi.visibility = %d
OR (
pi.visibility = %d AND cip IS NOT NULL OR pi.user = :current_user
)',
Portfolio::VISIBILITY_VISIBLE,
Portfolio::VISIBILITY_PER_USER
)
)
->setParameter('cip_tool', TOOL_PORTFOLIO)
;
} else {
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE];
if (api_is_allowed_to_edit()) { if (api_is_allowed_to_edit()) {
$visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER; $visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER;
} }
$queryBuilder $queryBuilder->andWhere(
->andWhere(
$queryBuilder->expr()->orX( $queryBuilder->expr()->orX(
'pi.user = :current_user', 'pi.user = :current_user',
$queryBuilder->expr()->andX( $queryBuilder->expr()->andX(
@ -3382,9 +3720,10 @@ class PortfolioController
$queryBuilder->expr()->in('pi.visibility', $visibilityCriteria) $queryBuilder->expr()->in('pi.visibility', $visibilityCriteria)
) )
) )
) );
->setParameter('current_user', api_get_user_id()); }
$queryBuilder->setParameter('current_user', api_get_user_id());
$queryBuilder->orderBy('pi.creationDate', 'DESC'); $queryBuilder->orderBy('pi.creationDate', 'DESC');
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();
@ -3483,14 +3822,38 @@ class PortfolioController
->setParameter('user', $this->owner); ->setParameter('user', $this->owner);
} }
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE]; if ($this->advancedSharingEnabled) {
$queryBuilder
->leftJoin(
CItemProperty::class,
'cip',
Join::WITH,
"cip.ref = pi.id
AND cip.tool = :cip_tool
AND cip.course = pi.course
AND cip.lasteditType = 'visible'
AND cip.toUser = :current_user"
)
->andWhere(
sprintf(
'pi.visibility = %d
OR (
pi.visibility = %d AND cip IS NOT NULL OR pi.user = :current_user
)',
Portfolio::VISIBILITY_VISIBLE,
Portfolio::VISIBILITY_PER_USER
)
)
->setParameter('cip_tool', TOOL_PORTFOLIO)
;
} else {
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE];
if (api_is_allowed_to_edit()) { if (api_is_allowed_to_edit()) {
$visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER; $visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER;
} }
$queryBuilder $queryBuilder->andWhere(
->andWhere(
$queryBuilder->expr()->orX( $queryBuilder->expr()->orX(
'pi.user = :current_user', 'pi.user = :current_user',
$queryBuilder->expr()->andX( $queryBuilder->expr()->andX(
@ -3498,9 +3861,10 @@ class PortfolioController
$queryBuilder->expr()->in('pi.visibility', $visibilityCriteria) $queryBuilder->expr()->in('pi.visibility', $visibilityCriteria)
) )
) )
) );
->setParameter('current_user', $currentUserId); }
$queryBuilder->setParameter('current_user', $currentUserId);
$queryBuilder->orderBy('pi.creationDate', 'DESC'); $queryBuilder->orderBy('pi.creationDate', 'DESC');
$items = $queryBuilder->getQuery()->getResult(); $items = $queryBuilder->getQuery()->getResult();
@ -3980,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'); $queryBuilder->orderBy('c.date', 'DESC');
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();

@ -1087,6 +1087,10 @@ ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472613FECDF FOREIGN KEY (se
// and follow the instructions about the @ORM\Entity() line // and follow the instructions about the @ORM\Entity() line
// - launch composer install to rebuild the autoload.php // - launch composer install to rebuild the autoload.php
//$_configuration['allow_portfolio_tool'] = false; //$_configuration['allow_portfolio_tool'] = false;
// 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 // Enable best score column in gradebook. Previously called disable_gradebook_stats
//$_configuration['gradebook_enable_best_score'] = false; //$_configuration['gradebook_enable_best_score'] = false;

@ -144,6 +144,29 @@ switch ($action) {
$controller->showHideItem($item); $controller->showHideItem($item);
return; return;
case 'item_visiblity_choose':
$id = $httpRequest->query->getInt('id');
/** @var Portfolio $item */
$item = $em->find(Portfolio::class, $id);
if (empty($item)) {
break;
}
$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': case 'delete_item':
$id = $httpRequest->query->getInt('id'); $id = $httpRequest->query->getInt('id');

@ -4,11 +4,12 @@
{% set invisible_img = 'invisible.png'|img(22, 'Visible'|get_lang) %} {% set invisible_img = 'invisible.png'|img(22, 'Visible'|get_lang) %}
{% set delete_img = 'delete.png'|img(22, 'Delete'|get_lang) %} {% set delete_img = 'delete.png'|img(22, 'Delete'|get_lang) %}
{% set baseurl = _p.web_self ~ '?' ~ (_p.web_cid_query ? _p.web_cid_query ~ '&' : '') %} {% set baseurl = _p.web_self ~ '?' ~ (_p.web_cid_query ? _p.web_cid_query ~ '&' : '') %}
{% set is_advanced_sharing_enabled = 'portfolio_advanced_sharing'|api_get_configuration_value and not _c is empty %}
<section class="portfolio-items"> <section class="portfolio-items">
{% for item in items %} {% for item in items %}
{% set item_url = baseurl ~ {'action':'view', 'id':item.id}|url_encode %} {% 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"> <div class="panel panel-default">
<article class="panel-body portfolio-item" id="portfolio-item-{{ item.id }}"> <article class="panel-body portfolio-item" id="portfolio-item-{{ item.id }}">
@ -17,19 +18,27 @@
<a href="{{ baseurl ~ {'action':'edit_item', 'id':item.id}|url_encode }}"> <a href="{{ baseurl ~ {'action':'edit_item', 'id':item.id}|url_encode }}">
{{ 'edit.png'|img(22, 'Edit'|get_lang) }} {{ 'edit.png'|img(22, 'Edit'|get_lang) }}
</a> </a>
{% if item.visibility == 0 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}"> {% if is_advanced_sharing_enabled %}
{{ 'invisible.png'|img(22, 'MakeVisible'|get_lang) }} <a href="{{ baseurl ~ {'action':'item_visiblity_choose', 'id':item.id}|url_encode }}">
</a> {{ 'visible.png'|img(22, 'ChooseRecipients'|get_lang) }}
{% elseif item.visibility == 1 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}">
{{ 'visible.png'|img(22, 'MakeVisibleForTeachers'|get_lang) }}
</a>
{% elseif item.visibility == 2 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}">
{{ 'eye-slash.png'|img(22, 'MakeInvisible'|get_lang) }}
</a> </a>
{% else %}
{% if item.visibility == 0 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}">
{{ 'invisible.png'|img(22, 'MakeVisible'|get_lang) }}
</a>
{% elseif item.visibility == 1 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}">
{{ 'visible.png'|img(22, 'MakeVisibleForTeachers'|get_lang) }}
</a>
{% elseif item.visibility == 2 %}
<a href="{{ baseurl ~ {'action':'visibility', 'id':item.id}|url_encode }}">
{{ 'eye-slash.png'|img(22, 'MakeInvisible'|get_lang) }}
</a>
{% endif %}
{% endif %} {% endif %}
<a href="{{ baseurl ~ {'action':'delete_item', 'id':item.id}|url_encode }}" class="btn-delete"> <a href="{{ baseurl ~ {'action':'delete_item', 'id':item.id}|url_encode }}" class="btn-delete">
{{ 'delete.png'|img(22, 'Delete'|get_lang) }} {{ 'delete.png'|img(22, 'Delete'|get_lang) }}
</a> </a>
@ -108,7 +117,7 @@
{% if comments|length > 0 %} {% if comments|length > 0 %}
<h4> <h4>
<a href="{{ item_url }}#portfolio-item-comments"> <a href="{{ item_url }}#portfolio-item-comments">
{{ 'XComments'|get_lang|format(item.comments.count) }} {{ 'XComments'|get_lang|format(comments|length) }}
</a> </a>
&centerdot; &centerdot;
<a href="{{ item_url }}#frm_comment">{{ 'AddNewComment'|get_lang }}</a> <a href="{{ item_url }}#frm_comment">{{ 'AddNewComment'|get_lang }}</a>

@ -58,7 +58,7 @@
<section id="portfolio-item-comments"> <section id="portfolio-item-comments">
<h1 class="h3"> <h1 class="h3">
<span class="fa fa-fw fa-comment-o" aria-hidden="true"></span> <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> </h1>
{{ comments }} {{ comments }}

@ -34,6 +34,7 @@ class Portfolio
public const VISIBILITY_HIDDEN = 0; public const VISIBILITY_HIDDEN = 0;
public const VISIBILITY_VISIBLE = 1; public const VISIBILITY_VISIBLE = 1;
public const VISIBILITY_HIDDEN_EXCEPT_TEACHER = 2; public const VISIBILITY_HIDDEN_EXCEPT_TEACHER = 2;
public const VISIBILITY_PER_USER = 3;
/** /**
* @var int * @var int
@ -96,7 +97,7 @@ class Portfolio
protected $updateDate; protected $updateDate;
/** /**
* @var bool * @var int
* *
* @ORM\Column(name="visibility", type="smallint", options={"default": 1}) * @ORM\Column(name="visibility", type="smallint", options={"default": 1})
*/ */
@ -375,13 +376,19 @@ class Portfolio
return $this->comments; return $this->comments;
} }
public function getLastComments(int $number = 3): Collection public function getLastComments(int $number = 3, bool $avoidPerUserVisibility = false): Collection
{ {
$criteria = Criteria::create(); $criteria = Criteria::create();
$criteria $criteria
->orderBy(['date' => 'DESC']) ->orderBy(['date' => 'DESC'])
->setMaxResults($number); ->setMaxResults($number);
if ($avoidPerUserVisibility) {
$criteria->where(
Criteria::expr()->neq('visibility', PortfolioComment::VISIBILITY_PER_USER)
);
}
return $this->comments->matching($criteria); return $this->comments->matching($criteria);
} }

@ -22,6 +22,17 @@ use Gedmo\Mapping\Annotation as Gedmo;
*/ */
class PortfolioComment 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 * @var int
* *
@ -128,6 +139,7 @@ class PortfolioComment
{ {
$this->isImportant = false; $this->isImportant = false;
$this->children = new ArrayCollection(); $this->children = new ArrayCollection();
$this->visibility = 1;
} }
public function getId(): int public function getId(): int
@ -268,4 +280,16 @@ class PortfolioComment
return $this; return $this;
} }
public function getVisibility(): int
{
return $this->visibility;
}
public function setVisibility(int $visibility): PortfolioComment
{
$this->visibility = $visibility;
return $this;
}
} }

Loading…
Cancel
Save