Skip to content

Commit

Permalink
Portfolio: Tags management by course - refs BT#18201
Browse files Browse the repository at this point in the history
Requires DB changes:

CREATE TABLE portfolio_rel_tag (id INT AUTO_INCREMENT NOT NULL, tag_id INT NOT NULL, c_id INT NOT NULL, session_id INT DEFAULT NULL, INDEX IDX_DB734472BAD26311 (tag_id), INDEX IDX_DB73447291D79BD3 (c_id), INDEX IDX_DB734472613FECDF (session_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472BAD26311 FOREIGN KEY (tag_id) REFERENCES tag (id) ON DELETE CASCADE;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB73447291D79BD3 FOREIGN KEY (c_id) REFERENCES course (id) ON DELETE CASCADE;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472613FECDF FOREIGN KEY (session_id) REFERENCES session (id) ON DELETE CASCADE;

You also need to edit src/Chamilo/CoreBundle/Entity/PortfolioRelTag.php and follow the instructions about the @Orm\Entity() line
  • Loading branch information
AngelFQC committed Sep 14, 2022
1 parent 0f0e95d commit 088402a
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 26 deletions.
17 changes: 13 additions & 4 deletions main/inc/ajax/extra_field.ajax.php
Expand Up @@ -46,10 +46,19 @@
exit;
}

$tags = Database::getManager()
->getRepository(Tag::class)
->findByFieldIdAndText($fieldId, $tag, $pageLimit)
;
$tagRepo = Database::getManager()->getRepository(Tag::class);

if ('portfolio' === $type) {
$tags = $tagRepo
->findForPortfolioInCourseQuery(
api_get_course_entity(),
api_get_session_entity()
)
->getQuery()
->getResult();
} else {
$tags = $tagRepo->findByFieldIdAndText($fieldId, $tag, $pageLimit);
}

/** @var Tag $tag */
foreach ($tags as $tag) {
Expand Down
188 changes: 187 additions & 1 deletion main/inc/lib/PortfolioController.php
Expand Up @@ -10,6 +10,7 @@
use Chamilo\CoreBundle\Entity\PortfolioAttachment;
use Chamilo\CoreBundle\Entity\PortfolioCategory;
use Chamilo\CoreBundle\Entity\PortfolioComment;
use Chamilo\CoreBundle\Entity\PortfolioRelTag;
use Chamilo\CoreBundle\Entity\Tag;
use Chamilo\UserBundle\Entity\User;
use Doctrine\ORM\Query\Expr\Join;
Expand Down Expand Up @@ -1004,6 +1005,13 @@ public function index(HttpRequest $httpRequest)
}
}

if (api_is_allowed_to_edit()) {
$actions[] = Display::url(
Display::return_icon('tickets.png', get_lang('Tags'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=tags'
);
}

$frmStudentList = null;
$frmTagList = null;

Expand Down Expand Up @@ -2647,6 +2655,182 @@ public function markAsTemplateComment(PortfolioComment $comment)
exit;
}

public function listTags(HttpRequest $request)
{
global $interbreadcrumb;

api_protect_course_script();
api_protect_teacher_script();

$em = Database::getManager();
$tagRepo = $em->getRepository(Tag::class);

$tagsQuery = $tagRepo->findForPortfolioInCourseQuery($this->course, $this->session);

$tag = $request->query->has('id')
? $tagRepo->find($request->query->getInt('id'))
: null;

$formAction = ['action' => $request->query->get('action')];

if ($tag) {
$formAction['id'] = $tag->getId();
}

$form = new FormValidator('frm_add_tag', 'post', $this->baseUrl.http_build_query($formAction));
$form->addText('name', get_lang('Tag'));

if ($tag) {
$form->addButtonUpdate(get_lang('Edit'));
} else {
$form->addButtonCreate(get_lang('Add'));
}

if ($form->validate()) {
$values = $form->exportValues();

$extraFieldInfo = (new ExtraField('portfolio'))->get_handler_field_info_by_field_variable('tags');

if (!$tag) {
$tag = (new Tag())->setCount(0);

$portfolioRelTag = (new PortfolioRelTag())
->setTag($tag)
->setCourse($this->course)
->setSession($this->session)
;

$em->persist($tag);
$em->persist($portfolioRelTag);
}

$tag
->setTag($values['name'])
->setFieldId((int) $extraFieldInfo['id'])
;

$em->flush();

Display::addFlash(
Display::return_message(get_lang('TagSaved'), 'success')
);

header('Location: '.$this->baseUrl.http_build_query($formAction));
exit();
} else {
$form->protect();

if ($tag) {
$form->setDefaults(['name' => $tag->getTag()]);
}
}

$langTags = get_lang('Tags');
$langEdit = get_lang('Edit');

$deleteIcon = Display::return_icon('delete.png', get_lang('Delete'));
$editIcon = Display::return_icon('edit.png', $langEdit);

$table = new SortableTable(
'portfolio_tags',
function () use ($tagsQuery) {
return (int) $tagsQuery
->select('COUNT(t)')
->getQuery()
->getSingleScalarResult()
;
},
function ($from, $limit, $column, $direction) use ($tagsQuery) {
$data = [];

/** @var array<int, Tag> $tags */
$tags = $tagsQuery
->select('t')
->orderBy('t.tag', $direction)
->setFirstResult($from)
->setMaxResults($limit)
->getQuery()
->getResult();

foreach ($tags as $tag) {
$data[] = [
$tag->getTag(),
$tag->getId(),
];
}

return $data;
},
0,
40
);
$table->set_header(0, get_lang('Name'));
$table->set_header(1, get_lang('Actions'), false, ['class' => 'text-right'], ['class' => 'text-right']);
$table->set_column_filter(
1,
function ($id) use ($editIcon, $deleteIcon) {
$editParams = http_build_query(['action' => 'edit_tag', 'id' => $id]);
$deleteParams = http_build_query(['action' => 'delete_tag', 'id' => $id]);

return Display::url($editIcon, $this->baseUrl.$editParams).PHP_EOL
.Display::url($deleteIcon, $this->baseUrl.$deleteParams).PHP_EOL;
}
);
$table->set_additional_parameters(
[
'action' => 'tags',
'cidReq' => $this->course->getCode(),
'id_session' => $this->session ? $this->session->getId() : 0,
'gidReq' => 0,
]
);

$content = $form->returnForm().PHP_EOL
.$table->return_table();

$interbreadcrumb[] = [
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];

$pageTitle = $langTags;

if ($tag) {
$pageTitle = $langEdit;

$interbreadcrumb[] = [
'name' => $langTags,
'url' => $this->baseUrl.'action=tags',
];
}

$this->renderView($content, $pageTitle);
}

public function deleteTag(Tag $tag)
{
api_protect_course_script();
api_protect_teacher_script();

$em = Database::getManager();
$portfolioTagRepo = $em->getRepository(PortfolioRelTag::class);

$portfolioTag = $portfolioTagRepo
->findOneBy(['tag' => $tag, 'course' => $this->course, 'session' => $this->session]);

if ($portfolioTag) {
$em->remove($portfolioTag);
$em->flush();

Display::addFlash(
Display::return_message(get_lang('TagDeleted'), 'success')
);
}

header('Location: '.$this->baseUrl.http_build_query(['action' => 'tags']));
exit();
}

/**
* @param bool $showHeader
*/
Expand Down Expand Up @@ -2797,7 +2981,9 @@ private function createFormTagFilter(bool $listByUser = false): FormValidator
{
$tags = Database::getManager()
->getRepository(Tag::class)
->findForPortfolioInCourse($this->course, $this->session)
->findForPortfolioInCourseQuery($this->course, $this->session)
->getQuery()
->getResult()
;

$frmTagList = new FormValidator(
Expand Down
8 changes: 7 additions & 1 deletion main/inc/lib/extra_field.lib.php
Expand Up @@ -1427,6 +1427,12 @@ public function set_extra_fields_in_form(
$url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
}

$allowAsTags = 'true';

if ('portfolio' === $this->type) {
$allowAsTags = 'false';
}

$form->setDefaults(
[
'extra_'.$field_details['variable'] => $selectedOptions,
Expand All @@ -1445,7 +1451,7 @@ public function set_extra_fields_in_form(
}
},
cache: false,
tags: true,
tags: $allowAsTags,
tokenSeparators: [','],
placeholder: '".get_lang('StartToType')."'
});
Expand Down
6 changes: 5 additions & 1 deletion main/install/configuration.dist.php
Expand Up @@ -1064,9 +1064,13 @@
ALTER TABLE portfolio_comment ADD CONSTRAINT FK_C2C17DA2727ACA70 FOREIGN KEY (parent_id) REFERENCES portfolio_comment (id) ON DELETE CASCADE;
ALTER TABLE portfolio_comment ADD is_template TINYINT(1) DEFAULT '0' NOT NULL;
ALTER TABLE portfolio_category ADD parent_id INT(11) NOT NULL DEFAULT 0;
CREATE TABLE portfolio_rel_tag (id INT AUTO_INCREMENT NOT NULL, tag_id INT NOT NULL, c_id INT NOT NULL, session_id INT DEFAULT NULL, INDEX IDX_DB734472BAD26311 (tag_id), INDEX IDX_DB73447291D79BD3 (c_id), INDEX IDX_DB734472613FECDF (session_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472BAD26311 FOREIGN KEY (tag_id) REFERENCES tag (id) ON DELETE CASCADE;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB73447291D79BD3 FOREIGN KEY (c_id) REFERENCES course (id) ON DELETE CASCADE;
ALTER TABLE portfolio_rel_tag ADD CONSTRAINT FK_DB734472613FECDF FOREIGN KEY (session_id) REFERENCES session (id) ON DELETE CASCADE;
*/
// In 1.11.8, before enabling this feature, you also need to:
// - edit src/Chamilo/CoreBundle/Entity/Portfolio.php, PortfolioCategory.php, PortfolioAttachment.php and PortfolioComment.php
// - edit src/Chamilo/CoreBundle/Entity/Portfolio.php, PortfolioCategory.php, PortfolioAttachment.php and PortfolioComment.php PortfolioRelTag.php
// and follow the instructions about the @ORM\Entity() line
// - launch composer install to rebuild the autoload.php
//$_configuration['allow_portfolio_tool'] = false;
Expand Down
16 changes: 16 additions & 0 deletions main/portfolio/index.php
Expand Up @@ -5,6 +5,7 @@
use Chamilo\CoreBundle\Entity\Portfolio;
use Chamilo\CoreBundle\Entity\PortfolioCategory;
use Chamilo\CoreBundle\Entity\PortfolioComment;
use Chamilo\CoreBundle\Entity\Tag;
use Symfony\Component\HttpFoundation\Request as HttpRequest;

// Make sure we void the course context if we are in the social network section
Expand Down Expand Up @@ -307,6 +308,21 @@

$controller->markAsTemplateComment($comment);
break;
case 'tags':
case 'edit_tag':
$controller->listTags($httpRequest);
break;
case 'delete_tag':
$id = $httpRequest->query->getInt('id');

$tag = $em->find(Tag::class, $id);

if (empty($tag)) {
break;
}

$controller->deleteTag($tag);
break;
case 'list':
default:
$controller->index($httpRequest);
Expand Down
88 changes: 88 additions & 0 deletions src/Chamilo/CoreBundle/Entity/PortfolioRelTag.php
@@ -0,0 +1,88 @@
<?php

/* For licensing terms, see /license.txt */

namespace Chamilo\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Table(name="portfolio_rel_tag")
* ORM\Entity()
*/
class PortfolioRelTag
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue
*/
protected $id;

/**
* @var Tag
*
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Tag")
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $tag;

/**
* @var Course
*
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course")
* @ORM\JoinColumn(name="c_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $course;

/**
* @var Session|null
*
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Session")
* @ORM\JoinColumn(name="session_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $session;

public function getId(): int
{
return $this->id;
}

public function getTag(): Tag
{
return $this->tag;
}

public function setTag(Tag $tag): PortfolioRelTag
{
$this->tag = $tag;

return $this;
}

public function getCourse(): Course
{
return $this->course;
}

public function setCourse(Course $course): PortfolioRelTag
{
$this->course = $course;

return $this;
}

public function getSession(): ?Session
{
return $this->session;
}

public function setSession(?Session $session): PortfolioRelTag
{
$this->session = $session;

return $this;
}
}

0 comments on commit 088402a

Please sign in to comment.