diff --git a/app/Resources/public/css/base.css b/app/Resources/public/css/base.css index b7236dae45..7da7eb41f9 100644 --- a/app/Resources/public/css/base.css +++ b/app/Resources/public/css/base.css @@ -3266,6 +3266,10 @@ form .formw .freeze { font-weight: normal; font-size: 90%; } +.label.origin-style { + font-weight: bold; + font-size: 75%; +} .requirements td { padding: 5px; diff --git a/main/inc/lib/PortfolioController.php b/main/inc/lib/PortfolioController.php index 464f9a45d0..775e349e81 100644 --- a/main/inc/lib/PortfolioController.php +++ b/main/inc/lib/PortfolioController.php @@ -588,7 +588,7 @@ class PortfolioController
'; }, 'childClose' => '
', - 'nodeDecorator' => function ($node) use ($commentsRepo, $clockIcon) { + 'nodeDecorator' => function ($node) use ($commentsRepo, $clockIcon, $item) { /** @var PortfolioComment $comment */ $comment = $commentsRepo->find($node['id']); @@ -615,7 +615,9 @@ class PortfolioController ) ); - if (api_is_allowed_to_edit()) { + $isAllowedToEdit = api_is_allowed_to_edit(); + + if ($isAllowedToEdit) { $commentActions .= Display::url( Display::return_icon('copy.png', get_lang('CopyToStudentPortfolio')), $this->baseUrl.http_build_query( @@ -626,11 +628,47 @@ class PortfolioController ] ) ); + + if ($comment->isImportant()) { + $commentActions .= Display::url( + Display::return_icon('drawing-pin.png', get_lang('UnmarkCommentAsImportant')), + $this->baseUrl.http_build_query( + [ + 'action' => 'mark_important', + 'item' => $item->getId(), + 'id' => $comment->getId(), + ] + ) + ); + } else { + $commentActions .= Display::url( + Display::return_icon('drawing-pin.png', get_lang('MarkCommentAsImportant')), + $this->baseUrl.http_build_query( + [ + 'action' => 'mark_important', + 'item' => $item->getId(), + 'id' => $comment->getId(), + ] + ) + ); + } + } + + $nodeHtml = '

'.PHP_EOL + .$comment->getAuthor()->getCompleteName().''.PHP_EOL.''.$clockIcon.PHP_EOL + .Display::dateToStringAgoAndLongDate($comment->getDate()).''.PHP_EOL; + + if ($comment->isImportant() && + ($this->itemBelongToOwner($comment->getItem()) || $isAllowedToEdit) + ) { + $nodeHtml .= ''.get_lang('CommentMarkedAsImportant') + .''.PHP_EOL; } - return '

'.$comment->getAuthor()->getCompleteName().PHP_EOL.'' - .$clockIcon.PHP_EOL.Display::dateToStringAgoAndLongDate($comment->getDate()).'' - .'

'.$commentActions.'
'.$comment->getContent().PHP_EOL; + $nodeHtml .= '

'.PHP_EOL + .'
'.$commentActions.'
'.$comment->getContent().PHP_EOL; + + return $nodeHtml; }, ] ); @@ -890,6 +928,34 @@ class PortfolioController $this->renderView($content, $toolName); } + /** + * @param \Chamilo\CoreBundle\Entity\Portfolio $item + * @param \Chamilo\CoreBundle\Entity\PortfolioComment $comment + * + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function markImportantCommentInItem(Portfolio $item, PortfolioComment $comment) + { + if ($comment->getItem()->getId() !== $item->getId()) { + api_not_allowed(true); + } + + $comment->setIsImportant( + !$comment->isImportant() + ); + + $this->em->persist($comment); + $this->em->flush(); + + Display::addFlash( + Display::return_message(get_lang('CommentMarkedAsImportant'), 'success') + ); + + header("Location: $this->baseUrl".http_build_query(['action' => 'view', 'id' => $item->getId()])); + exit; + } + /** * @param bool $showHeader */ @@ -935,14 +1001,6 @@ class PortfolioController private function itemBelongToOwner(Portfolio $item): bool { - if ($this->session && $item->getSession()->getId() != $this->session->getId()) { - return false; - } - - if ($this->course && $item->getCourse()->getId() != $this->course->getId()) { - return false; - } - if ($item->getUser()->getId() != $this->owner->getId()) { return false; } diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php index d8967a3f01..60f5d1d5ae 100755 --- a/main/install/configuration.dist.php +++ b/main/install/configuration.dist.php @@ -920,7 +920,7 @@ ALTER TABLE portfolio ADD CONSTRAINT FK_A9ED1062613FECDF FOREIGN KEY (session_id ALTER TABLE portfolio ADD CONSTRAINT FK_A9ED106212469DE2 FOREIGN KEY (category_id) REFERENCES portfolio_category (id) ON DELETE SET NULL; ALTER TABLE portfolio_category ADD CONSTRAINT FK_7AC64359A76ED395 FOREIGN KEY (user_id) REFERENCES user (id); INSERT INTO settings_current(variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES('course_create_active_tools','portfolio','checkbox','Tools','true','CourseCreateActiveToolsTitle','CourseCreateActiveToolsComment',NULL,'Portfolio', 0); -CREATE TABLE portfolio_comment (id INT AUTO_INCREMENT NOT NULL, author_id INT NOT NULL, item_id INT NOT NULL, tree_root INT DEFAULT NULL, parent_id INT DEFAULT NULL, content LONGTEXT NOT NULL, date DATETIME NOT NULL, lft INT NOT NULL, lvl INT NOT NULL, rgt INT NOT NULL, INDEX IDX_C2C17DA2F675F31B (author_id), INDEX IDX_C2C17DA2126F525E (item_id), INDEX IDX_C2C17DA2A977936C (tree_root), INDEX IDX_C2C17DA2727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; +CREATE TABLE portfolio_comment (id INT AUTO_INCREMENT NOT NULL, author_id INT NOT NULL, item_id INT NOT NULL, tree_root INT DEFAULT NULL, parent_id INT DEFAULT NULL, content LONGTEXT NOT NULL, date DATETIME NOT NULL, is_important TINYINT(1) DEFAULT '0' NOT NULL, lft INT NOT NULL, lvl INT NOT NULL, rgt INT NOT NULL, INDEX IDX_C2C17DA2F675F31B (author_id), INDEX IDX_C2C17DA2126F525E (item_id), INDEX IDX_C2C17DA2A977936C (tree_root), INDEX IDX_C2C17DA2727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; ALTER TABLE portfolio_comment ADD CONSTRAINT FK_C2C17DA2F675F31B FOREIGN KEY (author_id) REFERENCES user (id); ALTER TABLE portfolio_comment ADD CONSTRAINT FK_C2C17DA2126F525E FOREIGN KEY (item_id) REFERENCES portfolio (id); ALTER TABLE portfolio_comment ADD CONSTRAINT FK_C2C17DA2A977936C FOREIGN KEY (tree_root) REFERENCES portfolio_comment (id) ON DELETE CASCADE; diff --git a/main/portfolio/index.php b/main/portfolio/index.php index 73cd769f31..19674e219e 100755 --- a/main/portfolio/index.php +++ b/main/portfolio/index.php @@ -159,6 +159,21 @@ switch ($action) { } break; + case 'mark_important': + if (!api_is_allowed_to_edit()) { + api_not_allowed(true); + break; + } + + $item = $em->find(Portfolio::class, $httpRequest->query->getInt('item')); + $comment = $em->find(PortfolioComment::class, $httpRequest->query->getInt('id')); + + if (empty($item) || empty($comment)) { + break; + } + + $controller->markImportantCommentInItem($item, $comment); + return; case 'list': default: $controller->index(); diff --git a/src/Chamilo/CoreBundle/Entity/PortfolioComment.php b/src/Chamilo/CoreBundle/Entity/PortfolioComment.php index 1c453a6c6d..27e6164f8e 100644 --- a/src/Chamilo/CoreBundle/Entity/PortfolioComment.php +++ b/src/Chamilo/CoreBundle/Entity/PortfolioComment.php @@ -56,6 +56,12 @@ class PortfolioComment * @ORM\Column(name="date", type="datetime") */ private $date; + /** + * @var bool + * + * @ORM\Column(name="is_important", type="boolean", options={"default":false}) + */ + private $isImportant; /** * @var int * @@ -106,6 +112,7 @@ class PortfolioComment */ public function __construct() { + $this->isImportant = false; $this->children = new ArrayCollection(); } @@ -197,4 +204,20 @@ class PortfolioComment return $this; } + + /** + * @return bool + */ + public function isImportant(): bool + { + return $this->isImportant; + } + + /** + * @param bool $isImportant + */ + public function setIsImportant(bool $isImportant): void + { + $this->isImportant = $isImportant; + } }