Portfolio: Tags management by course - refs BT#18201

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
pull/4385/head
Angel Fernando Quiroz Campos 3 years ago
parent 0f0e95d250
commit 088402a2f0
  1. 17
      main/inc/ajax/extra_field.ajax.php
  2. 188
      main/inc/lib/PortfolioController.php
  3. 8
      main/inc/lib/extra_field.lib.php
  4. 6
      main/install/configuration.dist.php
  5. 16
      main/portfolio/index.php
  6. 88
      src/Chamilo/CoreBundle/Entity/PortfolioRelTag.php
  7. 27
      src/Chamilo/CoreBundle/Entity/Repository/TagRepository.php

@ -46,10 +46,19 @@ switch ($action) {
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) {

@ -10,6 +10,7 @@ use Chamilo\CoreBundle\Entity\Portfolio;
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;
@ -1004,6 +1005,13 @@ class PortfolioController
}
}
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;
@ -2647,6 +2655,182 @@ class PortfolioController
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
*/
@ -2797,7 +2981,9 @@ class PortfolioController
{
$tags = Database::getManager()
->getRepository(Tag::class)
->findForPortfolioInCourse($this->course, $this->session)
->findForPortfolioInCourseQuery($this->course, $this->session)
->getQuery()
->getResult()
;
$frmTagList = new FormValidator(

@ -1427,6 +1427,12 @@ class ExtraField extends Model
$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,
@ -1445,7 +1451,7 @@ class ExtraField extends Model
}
},
cache: false,
tags: true,
tags: $allowAsTags,
tokenSeparators: [','],
placeholder: '".get_lang('StartToType')."'
});

@ -1064,9 +1064,13 @@ ALTER TABLE portfolio_comment ADD CONSTRAINT FK_C2C17DA2A977936C FOREIGN KEY (tr
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;

@ -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
@ -307,6 +308,21 @@ switch ($action) {
$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);

@ -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;
}
}

@ -5,13 +5,11 @@
namespace Chamilo\CoreBundle\Entity\Repository;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ExtraField;
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
use Chamilo\CoreBundle\Entity\Portfolio;
use Chamilo\CoreBundle\Entity\PortfolioRelTag;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\Tag;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
/**
* @method array findById(int|array $ids)
@ -36,33 +34,24 @@ class TagRepository extends EntityRepository
->getResult();
}
/**
* @return array<Tag>
*/
public function findForPortfolioInCourse(Course $course, ?Session $session = null): array
public function findForPortfolioInCourseQuery(Course $course, ?Session $session = null): QueryBuilder
{
$qb = $this
->createQueryBuilder('t')
->innerJoin(ExtraField::class, 'ef', Join::WITH, 't.fieldId = ef.id')
->innerJoin(ExtraFieldRelTag::class, 'efrt', Join::WITH, 't.id = efrt.tagId AND ef.id = efrt.fieldId')
->innerJoin(Portfolio::class, 'p', Join::WITH, 'efrt.itemId = p.id')
->where('ef.variable = :variable')
->andWhere('ef.extraFieldType = :type')
->andWhere('p.course = :course')
->setParameter('variable', 'tags')
->setParameter('type', ExtraField::PORTFOLIO_TYPE)
->innerJoin(PortfolioRelTag::class, 'prt', Join::WITH, 't = prt.tag')
->where('prt.course = :course')
->setParameter('course', $course)
;
if ($session) {
$qb
->andWhere('p.session = :session')
->andWhere('prt.session = :session')
->setParameter('session', $session)
;
} else {
$qb->andWhere('p.session IS NULL');
$qb->andWhere('prt.session IS NULL');
}
return $qb->getQuery()->getResult();
return $qb;
}
}

Loading…
Cancel
Save