Skip to content

Commit 6ee2bda

Browse files
committed
Portfolio: Fixing queries related to resource node structure
1 parent b342840 commit 6ee2bda

File tree

4 files changed

+196
-103
lines changed

4 files changed

+196
-103
lines changed

public/main/inc/lib/PortfolioController.php

Lines changed: 31 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,123 +3795,53 @@ private function getItemsForIndex(
37953795
&& true === api_get_configuration_value('portfolio_show_base_course_post_in_sessions');
37963796

37973797
$portfolioRepo = Container::getPortfolioRepository();
3798-
$queryBuilder = $portfolioRepo->getResources();
3799-
$portfolioRepo->addCourseQueryBuilder($this->course, $queryBuilder);
3798+
$portfolioCategoryHelper = Container::getPortfolioCategoryHelper();
38003799

3801-
if ($this->session) {
3802-
if ($showBaseContentInSession) {
3803-
$portfolioRepo->addSessionAndBaseContentQueryBuilder($this->session, $queryBuilder);
3804-
} else {
3805-
$portfolioRepo->addSessionOnlyQueryBuilder($this->session, $queryBuilder);
3806-
}
3807-
} else {
3808-
$portfolioRepo->addSessionNullQueryBuilder($queryBuilder);
3809-
}
3800+
$filters = $frmFilterList && $frmFilterList->validate() ? $frmFilterList->exportValues() : [];
38103801

3811-
if ($frmFilterList && $frmFilterList->validate()) {
3812-
$values = $frmFilterList->exportValues();
3802+
$searchInCategories = [];
38133803

3814-
if (!empty($values['date'])) {
3815-
$queryBuilder
3816-
->andWhere('resource.creationDate >= :date')
3817-
->setParameter(':date', api_get_utc_datetime($values['date'], false, true))
3818-
;
3819-
}
3804+
if ($categoryId = $filters['categoryId'] ?? null) {
3805+
$searchInCategories[] = $categoryId;
38203806

3821-
if (!empty($values['tags'])) {
3822-
$queryBuilder
3823-
->innerJoin(ExtraFieldRelTag::class, 'efrt', Join::WITH, 'efrt.itemId = resource.id')
3824-
->innerJoin(ExtraFieldEntity::class, 'ef', Join::WITH, 'ef.id = efrt.fieldId')
3825-
->andWhere('ef.extraFieldType = :efType')
3826-
->andWhere('ef.variable = :variable')
3827-
->andWhere('efrt.tagId IN (:tags)');
3828-
3829-
$queryBuilder->setParameter('efType', ExtraFieldEntity::PORTFOLIO_TYPE);
3830-
$queryBuilder->setParameter('variable', 'tags');
3831-
$queryBuilder->setParameter('tags', $values['tags']);
3807+
foreach ($portfolioCategoryHelper->getListForIndex($categoryId) as $subCategory) {
3808+
$searchInCategories[] = $subCategory->getId();
38323809
}
3810+
}
38333811

3834-
if (!empty($values['text'])) {
3835-
$queryBuilder->andWhere(
3836-
$queryBuilder->expr()->orX(
3837-
$queryBuilder->expr()->like('resource.title', ':text'),
3838-
$queryBuilder->expr()->like('resource.content', ':text')
3839-
)
3840-
);
3812+
$searchNotInCategories = [];
38413813

3842-
$queryBuilder->setParameter('text', '%'.$values['text'].'%');
3843-
}
3814+
if ($subCategoryIdList = $filters['subCategoryIds'] ?? '') {
3815+
$diff = [];
38443816

3845-
// Filters by category level 0
3846-
$searchCategories = [];
3847-
if (!empty($values['categoryId'])) {
3848-
$searchCategories[] = $values['categoryId'];
3849-
$subCategories = $this->getCategoriesForIndex($values['categoryId']);
3850-
if (count($subCategories) > 0) {
3851-
foreach ($subCategories as $subCategory) {
3852-
$searchCategories[] = $subCategory->getId();
3853-
}
3854-
}
3855-
$queryBuilder->andWhere('resource.category IN('.implode(',', $searchCategories).')');
3817+
if ('all' !== $subCategoryIdList) {
3818+
$subCategoryIds = explode(',', $subCategoryIdList);
3819+
$diff = array_diff($searchInCategories, $subCategoryIds);
3820+
} elseif (trim($subCategoryIdList) === '') {
3821+
$diff = $searchInCategories;
38563822
}
38573823

3858-
// Filters by sub-category, don't show the selected values
3859-
$diff = [];
3860-
if (!empty($values['subCategoryIds']) && !('all' === $values['subCategoryIds'])) {
3861-
$subCategoryIds = explode(',', $values['subCategoryIds']);
3862-
$diff = array_diff($searchCategories, $subCategoryIds);
3863-
} else {
3864-
if (trim($values['subCategoryIds']) === '') {
3865-
$diff = $searchCategories;
3866-
}
3867-
}
38683824
if (!empty($diff)) {
38693825
unset($diff[0]);
3870-
if (!empty($diff)) {
3871-
$queryBuilder->andWhere('resource.category NOT IN('.implode(',', $diff).')');
3872-
}
3873-
}
3874-
}
38753826

3876-
if ($listByUser) {
3877-
$queryBuilder
3878-
->andWhere('resource.user = :user')
3879-
->setParameter('user', $this->owner);
3880-
}
3881-
3882-
if ($this->advancedSharingEnabled) {
3883-
$queryBuilder->andWhere(
3884-
$queryBuilder->expr()->orX(
3885-
$queryBuilder->expr()->eq('resource.visibility', Portfolio::VISIBILITY_VISIBLE),
3886-
$queryBuilder->expr()->eq('links.user', ':current_user')
3887-
)
3888-
);
3889-
} else {
3890-
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE];
3891-
3892-
if (api_is_allowed_to_edit()) {
3893-
$visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER;
3827+
$searchNotInCategories = $diff;
38943828
}
3895-
3896-
$queryBuilder->andWhere(
3897-
$queryBuilder->expr()->orX(
3898-
'node.creator = :current_user',
3899-
$queryBuilder->expr()->andX(
3900-
'node.creator != :current_user',
3901-
$queryBuilder->expr()->in('resource.visibility', $visibilityCriteria)
3902-
)
3903-
)
3904-
);
3905-
}
3906-
3907-
$queryBuilder->setParameter('current_user', $currentUserId);
3908-
if ($alphabeticalOrder || true === api_get_configuration_value('portfolio_order_post_by_alphabetical_order')) {
3909-
$queryBuilder->orderBy('resource.title', 'ASC');
3910-
} else {
3911-
$queryBuilder->orderBy('node.createdAt', 'DESC');
39123829
}
39133830

3914-
$items = $queryBuilder->getQuery()->getResult();
3831+
$items = $portfolioRepo->getIndexCourseItems(
3832+
api_get_user_entity(),
3833+
$this->owner,
3834+
$this->course,
3835+
$this->session,
3836+
$showBaseContentInSession,
3837+
$listByUser,
3838+
$filters['date'] ?? null,
3839+
$filters['tags'] ?? [],
3840+
$filters['text'] ?? '',
3841+
$searchInCategories,
3842+
$searchNotInCategories,
3843+
$this->advancedSharingEnabled
3844+
);
39153845

39163846
if ($showBaseContentInSession) {
39173847
$items = array_filter(

src/CoreBundle/Framework/Container.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
1212
use Chamilo\CoreBundle\Helpers\ContainerHelper;
1313
use Chamilo\CoreBundle\Helpers\PluginHelper;
14+
use Chamilo\CoreBundle\Helpers\PortfolioCategoryHelper;
1415
use Chamilo\CoreBundle\Helpers\ThemeHelper;
1516
use Chamilo\CoreBundle\Repository\AccessUrlRelPluginRepository;
1617
use Chamilo\CoreBundle\Repository\AssetRepository;
@@ -709,4 +710,12 @@ public static function getPortfolioRepository(): PortfolioRepository
709710

710711
return $repo;
711712
}
713+
714+
public static function getPortfolioCategoryHelper(): PortfolioCategoryHelper
715+
{
716+
/** @var PortfolioCategoryHelper $helper */
717+
$helper = self::$container->get(PortfolioCategoryHelper::class);
718+
719+
return $helper;
720+
}
712721
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/* For licensing terms, see /license.txt */
4+
5+
declare(strict_types=1);
6+
7+
namespace Chamilo\CoreBundle\Helpers;
8+
9+
use Chamilo\CoreBundle\Entity\PortfolioCategory;
10+
use Chamilo\CoreBundle\Entity\User;
11+
use Doctrine\ORM\EntityManagerInterface;
12+
use Doctrine\ORM\EntityRepository;
13+
use Symfony\Bundle\SecurityBundle\Security;
14+
15+
class PortfolioCategoryHelper
16+
{
17+
private EntityRepository $categoryRepo;
18+
19+
public function __construct(
20+
private readonly Security $security,
21+
EntityManagerInterface $entityManager,
22+
) {
23+
$this->categoryRepo = $entityManager->getRepository(PortfolioCategory::class);
24+
}
25+
26+
/**
27+
* @return array<int, PortfolioCategory>
28+
*/
29+
public function getListForIndex(
30+
?int $parentId = null,
31+
?User $owner = null,
32+
): array {
33+
$categoriesCriteria = [];
34+
35+
if (!$this->security->isGranted('ROLE_ADMIN') && null !== $owner?->getId()) {
36+
$categoriesCriteria['isVisible'] = true;
37+
}
38+
39+
if ($parentId) {
40+
$categoriesCriteria['parent'] = $parentId;
41+
}
42+
43+
return $this->categoryRepo->findBy($categoriesCriteria);
44+
}
45+
}

src/CoreBundle/Repository/Node/PortfolioRepository.php

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
namespace Chamilo\CoreBundle\Repository\Node;
88

99
use Chamilo\CoreBundle\Entity\Course;
10+
use Chamilo\CoreBundle\Entity\ExtraField;
11+
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
1012
use Chamilo\CoreBundle\Entity\Portfolio;
1113
use Chamilo\CoreBundle\Entity\Session;
1214
use Chamilo\CoreBundle\Entity\User;
1315
use Chamilo\CoreBundle\Repository\ResourceRepository;
16+
use Doctrine\ORM\Query\Expr\Join;
1417
use Doctrine\Persistence\ManagerRegistry;
1518

1619
class PortfolioRepository extends ResourceRepository
1720
{
18-
public function __construct(ManagerRegistry $registry)
19-
{
21+
public function __construct(ManagerRegistry $registry) {
2022
parent::__construct($registry, Portfolio::class);
2123
}
2224

@@ -54,4 +56,111 @@ public function findTemplates(User $creator, ?Course $course, ?Session $session)
5456
->getResult()
5557
;
5658
}
59+
60+
public function getIndexCourseItems(
61+
User $currentUser,
62+
User $owner,
63+
Course $course,
64+
?Session $session = null,
65+
bool $showBaseContentInSession = false,
66+
bool $listByUser = false,
67+
?\DateTime $date = null,
68+
array $tags = [],
69+
?string $searchText = null,
70+
array $searchCategories = [],
71+
array $searchNoInCategories = [],
72+
bool $advancedSharingEnabled = false
73+
): array {
74+
$queryBuilder = $this->getResources();
75+
$this->addCourseQueryBuilder($course, $queryBuilder);
76+
77+
if ($session) {
78+
if ($showBaseContentInSession) {
79+
$this->addSessionAndBaseContentQueryBuilder($session, $queryBuilder);
80+
} else {
81+
$this->addSessionOnlyQueryBuilder($session, $queryBuilder);
82+
}
83+
} else {
84+
$this->addSessionNullQueryBuilder($queryBuilder);
85+
}
86+
87+
if ($date) {
88+
$queryBuilder
89+
->andWhere('resource.creationDate >= :date')
90+
->setParameter(':date', $date)
91+
;
92+
}
93+
94+
if ($tags) {
95+
$queryBuilder
96+
->innerJoin(ExtraFieldRelTag::class, 'efrt', Join::WITH, 'efrt.itemId = resource.id')
97+
->innerJoin(ExtraField::class, 'ef', Join::WITH, 'ef.id = efrt.fieldId')
98+
->andWhere('ef.extraFieldType = :efType')
99+
->andWhere('ef.variable = :variable')
100+
->andWhere('efrt.tagId IN (:tags)');
101+
102+
$queryBuilder->setParameter('efType', ExtraField::PORTFOLIO_TYPE);
103+
$queryBuilder->setParameter('variable', 'tags');
104+
$queryBuilder->setParameter('tags', $tags);
105+
}
106+
107+
if (!empty($searchText)) {
108+
$queryBuilder->andWhere(
109+
$queryBuilder->expr()->orX(
110+
$queryBuilder->expr()->like('resource.title', ':text'),
111+
$queryBuilder->expr()->like('resource.content', ':text')
112+
)
113+
);
114+
115+
$queryBuilder->setParameter('text', '%'.$searchText.'%');
116+
}
117+
118+
if ($searchCategories) {
119+
$queryBuilder->andWhere(
120+
$queryBuilder->expr()->in('resource.category', $searchCategories)
121+
);
122+
}
123+
124+
if ($searchNoInCategories) {
125+
$queryBuilder->andWhere('resource.category NOT IN('.implode(',', $searchNoInCategories).')');
126+
}
127+
128+
if ($listByUser) {
129+
$queryBuilder
130+
->andWhere('resource.user = :user')
131+
->setParameter('user', $owner);
132+
}
133+
134+
if ($advancedSharingEnabled) {
135+
$queryBuilder->andWhere(
136+
$queryBuilder->expr()->orX(
137+
$queryBuilder->expr()->eq('resource.visibility', Portfolio::VISIBILITY_VISIBLE),
138+
$queryBuilder->expr()->eq('links.user', ':current_user')
139+
)
140+
);
141+
} else {
142+
$visibilityCriteria = [Portfolio::VISIBILITY_VISIBLE];
143+
144+
if (api_is_allowed_to_edit()) {
145+
$visibilityCriteria[] = Portfolio::VISIBILITY_HIDDEN_EXCEPT_TEACHER;
146+
}
147+
148+
$queryBuilder->andWhere(
149+
$queryBuilder->expr()->orX(
150+
'node.creator = :current_user',
151+
$queryBuilder->expr()->andX(
152+
'node.creator != :current_user',
153+
$queryBuilder->expr()->in('resource.visibility', $visibilityCriteria)
154+
)
155+
)
156+
);
157+
}
158+
159+
$queryBuilder
160+
->setParameter('current_user', $currentUser->getId())
161+
->orderBy('node.createdAt', 'DESC')
162+
;
163+
164+
return $queryBuilder->getQuery()->getResult();
165+
}
57166
}

0 commit comments

Comments
 (0)