mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Do not cache entities directly in NodesListBuilder but cache only the IDs instead
Otherwise the doctrine proxies break, and we get issues with loading the preview_images in structural Elements.
This commit is contained in:
parent
2e8cb35acc
commit
8ce5f4a796
9 changed files with 173 additions and 25 deletions
42
composer.lock
generated
42
composer.lock
generated
|
@ -15014,16 +15014,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.10.25",
|
"version": "1.10.26",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "578f4e70d117f9a90699324c555922800ac38d8c"
|
"reference": "5d660cbb7e1b89253a47147ae44044f49832351f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/578f4e70d117f9a90699324c555922800ac38d8c",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f",
|
||||||
"reference": "578f4e70d117f9a90699324c555922800ac38d8c",
|
"reference": "5d660cbb7e1b89253a47147ae44044f49832351f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -15072,7 +15072,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-07-06T12:11:37+00:00"
|
"time": "2023-07-19T12:44:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-doctrine",
|
"name": "phpstan/phpstan-doctrine",
|
||||||
|
@ -15396,12 +15396,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Roave/SecurityAdvisories.git",
|
"url": "https://github.com/Roave/SecurityAdvisories.git",
|
||||||
"reference": "e5af9ce18347a240cb120454a8c2665c5b162aa1"
|
"reference": "bd50a5b0522c94e65c90eb8d8cc040a630a07b0c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e5af9ce18347a240cb120454a8c2665c5b162aa1",
|
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/bd50a5b0522c94e65c90eb8d8cc040a630a07b0c",
|
||||||
"reference": "e5af9ce18347a240cb120454a8c2665c5b162aa1",
|
"reference": "bd50a5b0522c94e65c90eb8d8cc040a630a07b0c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
|
@ -15435,6 +15435,7 @@
|
||||||
"aws/aws-sdk-php": ">=3,<3.2.1",
|
"aws/aws-sdk-php": ">=3,<3.2.1",
|
||||||
"azuracast/azuracast": "<0.18.3",
|
"azuracast/azuracast": "<0.18.3",
|
||||||
"backdrop/backdrop": "<1.24.2",
|
"backdrop/backdrop": "<1.24.2",
|
||||||
|
"backpack/crud": "<3.4.9",
|
||||||
"badaso/core": "<2.7",
|
"badaso/core": "<2.7",
|
||||||
"bagisto/bagisto": "<0.1.5",
|
"bagisto/bagisto": "<0.1.5",
|
||||||
"barrelstrength/sprout-base-email": "<1.2.7",
|
"barrelstrength/sprout-base-email": "<1.2.7",
|
||||||
|
@ -15620,6 +15621,7 @@
|
||||||
"joomla/filesystem": "<1.6.2|>=2,<2.0.1",
|
"joomla/filesystem": "<1.6.2|>=2,<2.0.1",
|
||||||
"joomla/filter": "<1.4.4|>=2,<2.0.1",
|
"joomla/filter": "<1.4.4|>=2,<2.0.1",
|
||||||
"joomla/input": ">=2,<2.0.2",
|
"joomla/input": ">=2,<2.0.2",
|
||||||
|
"joomla/joomla-cms": ">=3,<3.9.12",
|
||||||
"joomla/session": "<1.3.1",
|
"joomla/session": "<1.3.1",
|
||||||
"joyqi/hyper-down": "<=2.4.27",
|
"joyqi/hyper-down": "<=2.4.27",
|
||||||
"jsdecena/laracom": "<2.0.9",
|
"jsdecena/laracom": "<2.0.9",
|
||||||
|
@ -15639,7 +15641,7 @@
|
||||||
"laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1",
|
"laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1",
|
||||||
"laminas/laminas-http": "<2.14.2",
|
"laminas/laminas-http": "<2.14.2",
|
||||||
"laravel/fortify": "<1.11.1",
|
"laravel/fortify": "<1.11.1",
|
||||||
"laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75",
|
"laravel/framework": "<6.20.44|>=7,<7.30.6|>=8,<8.75",
|
||||||
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
|
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
|
||||||
"latte/latte": "<2.10.8",
|
"latte/latte": "<2.10.8",
|
||||||
"lavalite/cms": "= 9.0.0|<=9",
|
"lavalite/cms": "= 9.0.0|<=9",
|
||||||
|
@ -15656,7 +15658,7 @@
|
||||||
"lms/routes": "<2.1.1",
|
"lms/routes": "<2.1.1",
|
||||||
"localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2",
|
"localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2",
|
||||||
"luyadev/yii-helpers": "<1.2.1",
|
"luyadev/yii-helpers": "<1.2.1",
|
||||||
"magento/community-edition": "<=2.4",
|
"magento/community-edition": "= 2.4.0|<=2.4",
|
||||||
"magento/magento1ce": "<1.9.4.3",
|
"magento/magento1ce": "<1.9.4.3",
|
||||||
"magento/magento1ee": ">=1,<1.14.4.3",
|
"magento/magento1ee": ">=1,<1.14.4.3",
|
||||||
"magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2",
|
"magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2",
|
||||||
|
@ -15681,6 +15683,7 @@
|
||||||
"monolog/monolog": ">=1.8,<1.12",
|
"monolog/monolog": ">=1.8,<1.12",
|
||||||
"moodle/moodle": "<4.2-rc.2|= 3.7|= 3.9|= 3.8|= 4.2.0|= 3.11",
|
"moodle/moodle": "<4.2-rc.2|= 3.7|= 3.9|= 3.8|= 4.2.0|= 3.11",
|
||||||
"movim/moxl": ">=0.8,<=0.10",
|
"movim/moxl": ">=0.8,<=0.10",
|
||||||
|
"mpdf/mpdf": "<=7.1.7",
|
||||||
"mustache/mustache": ">=2,<2.14.1",
|
"mustache/mustache": ">=2,<2.14.1",
|
||||||
"namshi/jose": "<2.2",
|
"namshi/jose": "<2.2",
|
||||||
"neoan3-apps/template": "<1.1.1",
|
"neoan3-apps/template": "<1.1.1",
|
||||||
|
@ -15789,6 +15792,7 @@
|
||||||
"scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11",
|
"scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11",
|
||||||
"sensiolabs/connect": "<4.2.3",
|
"sensiolabs/connect": "<4.2.3",
|
||||||
"serluck/phpwhois": "<=4.2.6",
|
"serluck/phpwhois": "<=4.2.6",
|
||||||
|
"sfroemken/url_redirect": "<=1.2.1",
|
||||||
"sheng/yiicms": "<=1.2",
|
"sheng/yiicms": "<=1.2",
|
||||||
"shopware/core": "<=6.4.20",
|
"shopware/core": "<=6.4.20",
|
||||||
"shopware/platform": "<=6.4.20",
|
"shopware/platform": "<=6.4.20",
|
||||||
|
@ -15797,6 +15801,7 @@
|
||||||
"shopware/storefront": "<=6.4.8.1",
|
"shopware/storefront": "<=6.4.8.1",
|
||||||
"shopxo/shopxo": "<2.2.6",
|
"shopxo/shopxo": "<2.2.6",
|
||||||
"showdoc/showdoc": "<2.10.4",
|
"showdoc/showdoc": "<2.10.4",
|
||||||
|
"silverstripe-australia/advancedreports": ">=1,<=2",
|
||||||
"silverstripe/admin": "<1.12.7",
|
"silverstripe/admin": "<1.12.7",
|
||||||
"silverstripe/assets": ">=1,<1.11.1",
|
"silverstripe/assets": ">=1,<1.11.1",
|
||||||
"silverstripe/cms": "<4.11.3",
|
"silverstripe/cms": "<4.11.3",
|
||||||
|
@ -15805,6 +15810,7 @@
|
||||||
"silverstripe/framework": "<4.12.5",
|
"silverstripe/framework": "<4.12.5",
|
||||||
"silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1",
|
"silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1",
|
||||||
"silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1",
|
"silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1",
|
||||||
|
"silverstripe/recipe-cms": ">=4.5,<4.5.3",
|
||||||
"silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
|
"silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
|
||||||
"silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4",
|
"silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4",
|
||||||
"silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1",
|
"silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1",
|
||||||
|
@ -15820,6 +15826,7 @@
|
||||||
"simplesamlphp/simplesamlphp-module-openidprovider": "<0.9",
|
"simplesamlphp/simplesamlphp-module-openidprovider": "<0.9",
|
||||||
"simplito/elliptic-php": "<1.0.6",
|
"simplito/elliptic-php": "<1.0.6",
|
||||||
"sitegeist/fluid-components": "<3.5",
|
"sitegeist/fluid-components": "<3.5",
|
||||||
|
"sjbr/sr-freecap": "<=2.5.2",
|
||||||
"slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1",
|
"slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1",
|
||||||
"slim/slim": "<2.6",
|
"slim/slim": "<2.6",
|
||||||
"smarty/smarty": "<3.1.48|>=4,<4.3.1",
|
"smarty/smarty": "<3.1.48|>=4,<4.3.1",
|
||||||
|
@ -15828,6 +15835,7 @@
|
||||||
"socialiteproviders/steam": "<1.1",
|
"socialiteproviders/steam": "<1.1",
|
||||||
"spatie/browsershot": "<3.57.4",
|
"spatie/browsershot": "<3.57.4",
|
||||||
"spipu/html2pdf": "<5.2.4",
|
"spipu/html2pdf": "<5.2.4",
|
||||||
|
"spoon/library": "<1.4.1",
|
||||||
"spoonity/tcpdf": "<6.2.22",
|
"spoonity/tcpdf": "<6.2.22",
|
||||||
"squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1",
|
"squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1",
|
||||||
"ssddanbrown/bookstack": "<22.2.3",
|
"ssddanbrown/bookstack": "<22.2.3",
|
||||||
|
@ -16024,7 +16032,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-07-17T11:04:34+00:00"
|
"time": "2023-07-20T19:04:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/diff",
|
"name": "sebastian/diff",
|
||||||
|
@ -16095,16 +16103,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/array-to-xml",
|
"name": "spatie/array-to-xml",
|
||||||
"version": "3.1.6",
|
"version": "3.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/array-to-xml.git",
|
"url": "https://github.com/spatie/array-to-xml.git",
|
||||||
"reference": "e210b98957987c755372465be105d32113f339a4"
|
"reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4",
|
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7",
|
||||||
"reference": "e210b98957987c755372465be105d32113f339a4",
|
"reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -16142,7 +16150,7 @@
|
||||||
"xml"
|
"xml"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/spatie/array-to-xml/tree/3.1.6"
|
"source": "https://github.com/spatie/array-to-xml/tree/3.2.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -16154,7 +16162,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-05-11T14:04:07+00:00"
|
"time": "2023-07-19T18:30:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/browser-kit",
|
"name": "symfony/browser-kit",
|
||||||
|
|
|
@ -26,6 +26,7 @@ use App\Entity\Base\AbstractNamedDBElement;
|
||||||
use App\Entity\Base\MasterAttachmentTrait;
|
use App\Entity\Base\MasterAttachmentTrait;
|
||||||
use App\Entity\Contracts\HasAttachmentsInterface;
|
use App\Entity\Contracts\HasAttachmentsInterface;
|
||||||
use App\Entity\Contracts\HasMasterAttachmentInterface;
|
use App\Entity\Contracts\HasMasterAttachmentInterface;
|
||||||
|
use App\Repository\AttachmentContainingDBElementRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
@ -34,7 +35,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
/**
|
/**
|
||||||
* @template-covariant AT of Attachment
|
* @template-covariant AT of Attachment
|
||||||
*/
|
*/
|
||||||
#[ORM\MappedSuperclass]
|
#[ORM\MappedSuperclass(repositoryClass: AttachmentContainingDBElementRepository::class)]
|
||||||
abstract class AttachmentContainingDBElement extends AbstractNamedDBElement implements HasMasterAttachmentInterface, HasAttachmentsInterface
|
abstract class AttachmentContainingDBElement extends AbstractNamedDBElement implements HasMasterAttachmentInterface, HasAttachmentsInterface
|
||||||
{
|
{
|
||||||
use MasterAttachmentTrait;
|
use MasterAttachmentTrait;
|
||||||
|
|
|
@ -35,6 +35,8 @@ trait MasterAttachmentTrait
|
||||||
* @var Attachment|null
|
* @var Attachment|null
|
||||||
* Mapping is done in the subclasses (e.g. Part), like with the attachments.
|
* Mapping is done in the subclasses (e.g. Part), like with the attachments.
|
||||||
* If this is done here (which is possible in theory), the attachment is not lazy loaded anymore, which causes unnecessary overhead.
|
* If this is done here (which is possible in theory), the attachment is not lazy loaded anymore, which causes unnecessary overhead.
|
||||||
|
*
|
||||||
|
* !!! If you change this name, you have to change it in the fetchHint in the AttachmentContainingDBElementRepository (getElementsAndPreviewAttachmentByIDs()) too !!!
|
||||||
*/
|
*/
|
||||||
#[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')]
|
#[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')]
|
||||||
protected ?Attachment $master_picture_attachment = null;
|
protected ?Attachment $master_picture_attachment = null;
|
||||||
|
|
72
src/Repository/AttachmentContainingDBElementRepository.php
Normal file
72
src/Repository/AttachmentContainingDBElementRepository.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TEntityClass of AttachmentContainingDBElement
|
||||||
|
* @extends NamedDBElementRepository<TEntityClass>
|
||||||
|
*/
|
||||||
|
class AttachmentContainingDBElementRepository extends NamedDBElementRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array This array is used to cache the results of getElementsAndPreviewAttachmentByIDs function.
|
||||||
|
*/
|
||||||
|
private array $elementsAndPreviewAttachmentCache = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the findByIDInMatchingOrder function, but it also hints to doctrine that the master picture attachment should be fetched eagerly.
|
||||||
|
* @param array $ids
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getElementsAndPreviewAttachmentByIDs(array $ids): array
|
||||||
|
{
|
||||||
|
//Convert the ids to a string
|
||||||
|
$cache_key = implode(',', $ids);
|
||||||
|
|
||||||
|
//Check if the result is already cached
|
||||||
|
if (isset($this->elementsAndPreviewAttachmentCache[$cache_key])) {
|
||||||
|
return $this->elementsAndPreviewAttachmentCache[$cache_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb = $this->createQueryBuilder('element');
|
||||||
|
$q = $qb->select('element')
|
||||||
|
->where('element.id IN (?1)')
|
||||||
|
->setParameter(1, $ids)
|
||||||
|
->getQuery();
|
||||||
|
|
||||||
|
$q->setFetchMode($this->getEntityName(), 'master_picture_attachment', ClassMetadataInfo::FETCH_EAGER);
|
||||||
|
|
||||||
|
$result = $q->getResult();
|
||||||
|
$result = array_combine($ids, $result);
|
||||||
|
$result = array_map(fn ($id) => $result[$id], $ids);
|
||||||
|
|
||||||
|
//Cache the result
|
||||||
|
$this->elementsAndPreviewAttachmentCache[$cache_key] = $result;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,8 @@ use ReflectionClass;
|
||||||
*/
|
*/
|
||||||
class DBElementRepository extends EntityRepository
|
class DBElementRepository extends EntityRepository
|
||||||
{
|
{
|
||||||
|
private array $find_elements_by_id_cache = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the ID of the given element to a new value.
|
* Changes the ID of the given element to a new value.
|
||||||
* You should only use it to undelete former existing elements, everything else is most likely a bad idea!
|
* You should only use it to undelete former existing elements, everything else is most likely a bad idea!
|
||||||
|
@ -91,6 +93,38 @@ class DBElementRepository extends EntityRepository
|
||||||
return $q->getResult();
|
return $q->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the elements with the given IDs in the same order, as they were given in the input array.
|
||||||
|
*
|
||||||
|
* @param array $ids
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findByIDInMatchingOrder(array $ids): array
|
||||||
|
{
|
||||||
|
$cache_key = implode(',', $ids);
|
||||||
|
|
||||||
|
//Check if the result is already cached
|
||||||
|
if (isset($this->find_elements_by_id_cache[$cache_key])) {
|
||||||
|
return $this->find_elements_by_id_cache[$cache_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Otherwise do the query
|
||||||
|
$qb = $this->createQueryBuilder('element');
|
||||||
|
$q = $qb->select('element')
|
||||||
|
->where('element.id IN (?1)')
|
||||||
|
->setParameter(1, $ids)
|
||||||
|
->getQuery();
|
||||||
|
|
||||||
|
$result = $q->getResult();
|
||||||
|
$result = array_combine($ids, $result);
|
||||||
|
$result = array_map(fn ($id) => $result[$id], $ids);
|
||||||
|
|
||||||
|
//Cache the result
|
||||||
|
$this->find_elements_by_id_cache[$cache_key] = $result;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
protected function setField(AbstractDBElement $element, string $field, int $new_value): void
|
protected function setField(AbstractDBElement $element, string $field, int $new_value): void
|
||||||
{
|
{
|
||||||
$reflection = new ReflectionClass($element::class);
|
$reflection = new ReflectionClass($element::class);
|
||||||
|
|
|
@ -65,11 +65,11 @@ class NamedDBElementRepository extends DBElementRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of all nodes to use in a select box.
|
* Returns a flattened list of all nodes.
|
||||||
* @return AbstractNamedDBElement[]
|
* @return AbstractNamedDBElement[]
|
||||||
* @phpstan-return array<int, AbstractNamedDBElement>
|
* @phpstan-return array<int, AbstractNamedDBElement>
|
||||||
*/
|
*/
|
||||||
public function toNodesList(): array
|
public function getFlatList(): array
|
||||||
{
|
{
|
||||||
//All nodes are sorted by name
|
//All nodes are sorted by name
|
||||||
return $this->findBy([], ['name' => 'ASC']);
|
return $this->findBy([], ['name' => 'ASC']);
|
||||||
|
|
|
@ -32,7 +32,7 @@ use RecursiveIteratorIterator;
|
||||||
* @template TEntityClass of AbstractStructuralDBElement
|
* @template TEntityClass of AbstractStructuralDBElement
|
||||||
* @extends NamedDBElementRepository<TEntityClass>
|
* @extends NamedDBElementRepository<TEntityClass>
|
||||||
*/
|
*/
|
||||||
class StructuralDBElementRepository extends NamedDBElementRepository
|
class StructuralDBElementRepository extends AttachmentContainingDBElementRepository
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var array An array containing all new entities created by getNewEntityByPath.
|
* @var array An array containing all new entities created by getNewEntityByPath.
|
||||||
|
@ -85,7 +85,7 @@ class StructuralDBElementRepository extends NamedDBElementRepository
|
||||||
* @return AbstractStructuralDBElement[] a flattened list containing the tree elements
|
* @return AbstractStructuralDBElement[] a flattened list containing the tree elements
|
||||||
* @phpstan-return array<int, TEntityClass>
|
* @phpstan-return array<int, TEntityClass>
|
||||||
*/
|
*/
|
||||||
public function toNodesList(?AbstractStructuralDBElement $parent = null): array
|
public function getFlatList(?AbstractStructuralDBElement $parent = null): array
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,12 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Services\Trees;
|
namespace App\Services\Trees;
|
||||||
|
|
||||||
|
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||||
|
use App\Entity\Base\AbstractDBElement;
|
||||||
|
use App\Entity\Base\AbstractNamedDBElement;
|
||||||
use App\Entity\Base\AbstractStructuralDBElement;
|
use App\Entity\Base\AbstractStructuralDBElement;
|
||||||
|
use App\Repository\AttachmentContainingDBElementRepository;
|
||||||
|
use App\Repository\DBElementRepository;
|
||||||
use App\Repository\StructuralDBElementRepository;
|
use App\Repository\StructuralDBElementRepository;
|
||||||
use App\Services\UserSystem\UserCacheKeyGenerator;
|
use App\Services\UserSystem\UserCacheKeyGenerator;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
@ -49,6 +54,31 @@ class NodesListBuilder
|
||||||
* @return AbstractStructuralDBElement[] a flattened list containing the tree elements
|
* @return AbstractStructuralDBElement[] a flattened list containing the tree elements
|
||||||
*/
|
*/
|
||||||
public function typeToNodesList(string $class_name, ?AbstractStructuralDBElement $parent = null): array
|
public function typeToNodesList(string $class_name, ?AbstractStructuralDBElement $parent = null): array
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* We can not cache the entities directly, because loading them from cache will break the doctrine proxies.
|
||||||
|
*/
|
||||||
|
//Retrieve the IDs of the elements
|
||||||
|
$ids = $this->getFlattenedIDs($class_name, $parent);
|
||||||
|
|
||||||
|
//Retrieve the elements from the IDs, the order is the same as in the $ids array
|
||||||
|
/** @var DBElementRepository $repo */
|
||||||
|
$repo = $this->em->getRepository($class_name);
|
||||||
|
|
||||||
|
if ($repo instanceof AttachmentContainingDBElementRepository) {
|
||||||
|
return $repo->getElementsAndPreviewAttachmentByIDs($ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $repo->getElementsFromIDArray($ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This functions returns the (cached) list of the IDs of the elements for the flattened tree.
|
||||||
|
* @param string $class_name
|
||||||
|
* @param AbstractStructuralDBElement|null $parent
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getFlattenedIDs(string $class_name, ?AbstractStructuralDBElement $parent = null): array
|
||||||
{
|
{
|
||||||
$parent_id = $parent instanceof AbstractStructuralDBElement ? $parent->getID() : '0';
|
$parent_id = $parent instanceof AbstractStructuralDBElement ? $parent->getID() : '0';
|
||||||
// Backslashes are not allowed in cache keys
|
// Backslashes are not allowed in cache keys
|
||||||
|
@ -58,10 +88,11 @@ class NodesListBuilder
|
||||||
return $this->cache->get($key, function (ItemInterface $item) use ($class_name, $parent, $secure_class_name) {
|
return $this->cache->get($key, function (ItemInterface $item) use ($class_name, $parent, $secure_class_name) {
|
||||||
// Invalidate when groups, an element with the class or the user changes
|
// Invalidate when groups, an element with the class or the user changes
|
||||||
$item->tag(['groups', 'tree_list', $this->keyGenerator->generateKey(), $secure_class_name]);
|
$item->tag(['groups', 'tree_list', $this->keyGenerator->generateKey(), $secure_class_name]);
|
||||||
|
|
||||||
/** @var StructuralDBElementRepository $repo */
|
/** @var StructuralDBElementRepository $repo */
|
||||||
$repo = $this->em->getRepository($class_name);
|
$repo = $this->em->getRepository($class_name);
|
||||||
|
|
||||||
return $repo->toNodesList($parent);
|
return array_map(fn(AbstractDBElement $element) => $element->getID(), $repo->getFlatList($parent));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class StructuralDBElementRepositoryTest extends WebTestCase
|
||||||
public function testToNodesListRoot(): void
|
public function testToNodesListRoot(): void
|
||||||
{
|
{
|
||||||
//List all root nodes and their children
|
//List all root nodes and their children
|
||||||
$nodes = $this->repo->toNodesList();
|
$nodes = $this->repo->getFlatList();
|
||||||
|
|
||||||
$this->assertCount(7, $nodes);
|
$this->assertCount(7, $nodes);
|
||||||
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
|
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
|
||||||
|
@ -109,7 +109,7 @@ class StructuralDBElementRepositoryTest extends WebTestCase
|
||||||
{
|
{
|
||||||
//List all nodes that are children to Node 1
|
//List all nodes that are children to Node 1
|
||||||
$node1 = $this->repo->find(1);
|
$node1 = $this->repo->find(1);
|
||||||
$nodes = $this->repo->toNodesList($node1);
|
$nodes = $this->repo->getFlatList($node1);
|
||||||
|
|
||||||
$this->assertCount(3, $nodes);
|
$this->assertCount(3, $nodes);
|
||||||
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
|
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue