From dc18b9293406b5ba758b320d4bde60732a3d5bf8 Mon Sep 17 00:00:00 2001 From: Marco Lengua Date: Mon, 8 Dec 2025 13:17:33 +0100 Subject: [PATCH 1/2] Introduce Document Service to load current Document only once for all controllers --- Classes/Controller/AbstractController.php | 148 ++++-------------- Classes/Service/DocumentService.php | 182 ++++++++++++++++++++++ Configuration/Services.yaml | 3 + 3 files changed, 211 insertions(+), 122 deletions(-) create mode 100644 Classes/Service/DocumentService.php diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index caeee5cc6..052b1941f 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -15,6 +15,7 @@ use Kitodo\Dlf\Common\Helper; use Kitodo\Dlf\Domain\Model\Document; use Kitodo\Dlf\Domain\Repository\DocumentRepository; +use Kitodo\Dlf\Service\DocumentService; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; @@ -26,6 +27,7 @@ use TYPO3\CMS\Core\Pagination\PaginatorInterface; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + /** * Abstract controller class for most of the plugin controller. * @@ -40,24 +42,6 @@ abstract class AbstractController extends ActionController implements LoggerAwar { use LoggerAwareTrait; - /** - * @access protected - * @var DocumentRepository - */ - protected DocumentRepository $documentRepository; - - /** - * @access public - * - * @param DocumentRepository $documentRepository - * - * @return void - */ - public function injectDocumentRepository(DocumentRepository $documentRepository): void - { - $this->documentRepository = $documentRepository; - } - /** * @access protected * @var Document|null This holds the current document @@ -87,7 +71,25 @@ public function injectDocumentRepository(DocumentRepository $documentRepository) * @var int */ protected int $pageUid; + /** + * @access protected + * @var DocumentRepository + */ + protected DocumentRepository $documentRepository; + /** + * @access protected + * @var DocumentService + */ + protected DocumentService $documentService; + public function injectDocumentRepository(DocumentRepository $repo): void + { + $this->documentRepository = $repo; + } + public function injectDocumentService(DocumentService $service): void + { + $this->documentService = $service; + } /** * Initialize the plugin controller * @@ -108,64 +110,27 @@ protected function initialize(): void $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); + $this->documentService = GeneralUtility::makeInstance(DocumentService::class); + $this->viewData = [ 'pageUid' => $this->pageUid, 'uniqueId' => uniqid(), 'requestData' => $this->requestData ]; } - /** - * Loads the current document into $this->document + * Load the current Document to Globals Temp just once with Document Service. * * @access protected - * - * @param int $documentId The document's UID (fallback: $this->requestData[id]) - * * @return void */ - protected function loadDocument(int $documentId = 0): void + protected function loadDocument(): void { - // Sanitize FlexForm settings to avoid later casting. $this->sanitizeSettings(); - - // Get document ID from request data if not passed as parameter. - if ($documentId === 0 && !empty($this->requestData['id'])) { - $documentId = $this->requestData['id']; - } - - // Try to get document format from database - if (!empty($documentId)) { - - $doc = null; - - if (MathUtility::canBeInterpretedAsInteger($documentId)) { - $doc = $this->getDocumentByUid($documentId); - } elseif (GeneralUtility::isValidUrl($documentId)) { - $doc = $this->getDocumentByUrl($documentId); - } - - if ($this->document !== null && $doc !== null) { - $this->document->setCurrentDocument($doc); - } - - } elseif (!empty($this->requestData['recordId'])) { - - $this->document = $this->documentRepository->findOneByRecordId($this->requestData['recordId']); - - if ($this->document !== null) { - $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, true); - if ($doc !== null) { - $this->document->setCurrentDocument($doc); - } else { - $this->logger->error('Failed to load document with record ID "' . $this->requestData['recordId'] . '"'); - } - } - } else { - $this->logger->error('Invalid ID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading'); - } + $this->document = $this->documentService->getDocument($this->requestData['id'], $this->settings); } + /** * Configure URL for proxy. * @@ -500,65 +465,4 @@ protected function buildSimplePagination(PaginationInterface $pagination, Pagina 'pagesR' => $pagesSect ]; } - - /** - * Get document from repository by uid. - * - * @access private - * - * @param int $documentId The document's UID - * - * @return AbstractDocument - */ - private function getDocumentByUid(int $documentId) - { - $doc = null; - $this->document = $this->documentRepository->findOneByIdAndSettings($documentId); - - if ($this->document) { - $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, false); - } else { - $this->logger->error('Invalid UID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading'); - } - - return $doc; - } - - /** - * Get document by URL. - * - * @access private - * - * @param string $documentId The document's URL - * - * @return AbstractDocument - */ - private function getDocumentByUrl(string $documentId) - { - $doc = AbstractDocument::getInstance($documentId, $this->settings, true); - - if ($doc !== null) { - if ($doc->recordId) { - // find document from repository by recordId - $docFromRepository = $this->documentRepository->findOneByRecordId($doc->recordId); - if ($docFromRepository !== null) { - $this->document = $docFromRepository; - } else { - // create new dummy Document object - $this->document = GeneralUtility::makeInstance(Document::class); - } - } - - // Make sure configuration PID is set when applicable - if ($doc->cPid == 0) { - $doc->cPid = max($this->settings['storagePid'], 0); - } - - $this->document->setLocation($documentId); - } else { - $this->logger->error('Invalid location given "' . $documentId . '" for document loading'); - } - - return $doc; - } } diff --git a/Classes/Service/DocumentService.php b/Classes/Service/DocumentService.php new file mode 100644 index 000000000..71b73cf26 --- /dev/null +++ b/Classes/Service/DocumentService.php @@ -0,0 +1,182 @@ + + * + * This file is part of the Kitodo and TYPO3 projects. + * + * @license GNU General Public License version 3 or later. + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + */ + +namespace Kitodo\Dlf\Service; + +use Kitodo\Dlf\Domain\Repository\DocumentRepository; +use TYPO3\CMS\Core\Log\LogManager; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use Kitodo\Dlf\Common\AbstractDocument; +use Kitodo\Dlf\Domain\Model\Document; +use TYPO3\CMS\Core\Utility\MathUtility; +/** + * (Service For Abstract Controller) Service that decouples the loading of documents from each controller to only once. + * + * @package TYPO3 + * @subpackage dlf + * + * @access public + */ +class DocumentService +{ + /** + * @access protected + * @var Document|null This holds the current document + */ + protected ?Document $document = null; + /** + * @access protected + * @var array + */ + protected $settings; + /** + * @access protected + * @var array + */ + protected $logger; + protected DocumentRepository $documentRepository; + + public function __construct() + { + $this->documentRepository = GeneralUtility::makeInstance(DocumentRepository::class); + $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); + } + + protected function init() + { + return true; + } + protected function reset() + { + } + /** + * @access public + * @param int $recordId + * @param array $settings + * @return ?Document + */ + public function getDocument($recordId, $settings) + { + if (isset($GLOBALS['TX_DLF_TEMP_DOCUMENT'])) { + return $GLOBALS['TX_DLF_TEMP_DOCUMENT']; + } else { + $this->serviceLoadDocument($recordId, $settings); + $GLOBALS['TX_DLF_TEMP_DOCUMENT'] = $this->document; + return $this->document; + } + } + /** + * @access public + * @param int $recordId + * @param array $settings + */ + private function serviceLoadDocument($recordId, $settings){ + + $this->settings = $settings; + + // Get document ID from request data if not passed as parameter. + if (!empty($recordId)) { + $documentId = $recordId; + } + + // Try to get document format from database + if (!empty($documentId)) { + + $doc = null; + + if (MathUtility::canBeInterpretedAsInteger($documentId)) { + $doc = $this->getDocumentByUid($documentId); + } elseif (GeneralUtility::isValidUrl($documentId)) { + $doc = $this->getDocumentByUrl($documentId); + } + + if ($this->document !== null && $doc !== null) { + $this->document->setCurrentDocument($doc); + } + + } elseif (!empty($this->requestData['recordId'])) { + + $this->document = $this->documentRepository->findOneByRecordId($this->requestData['recordId']); + + if ($this->document !== null) { + $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, false); + if ($doc !== null) { + $this->document->setCurrentDocument($doc); + } else { + $this->logger->error('Failed to load document with record ID "' . $this->requestData['recordId'] . '"'); + } + } + } else { + $this->logger->error('Invalid ID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading'); + } + } + /** + * Get document from repository by uid. + * + * @access private + * + * @param int $documentId The document's UID + * + * @return AbstractDocument + */ + private function getDocumentByUid(int $documentId): AbstractDocument|null + { + $doc = null; + $this->document = $this->documentRepository->findOneByIdAndSettings($documentId); + + if ($this->document) { + $doc = AbstractDocument::getInstance($this->document->getLocation(), $this->settings, false); + } else { + $this->logger->error('Invalid UID "' . $documentId . '" or PID "' . $this->settings['storagePid'] . '" for document loading'); + } + + return $doc; + } + + /** + * Get document by URL. + * + * @access private + * + * @param string $documentId The document's URL + * + * @return AbstractDocument + */ + private function getDocumentByUrl(string $documentId) + { + $doc = AbstractDocument::getInstance($documentId, $this->settings, false); + + if ($doc !== null) { + if ($doc->recordId) { + // find document from repository by recordId + $docFromRepository = $this->documentRepository->findOneByRecordId($doc->recordId); + if ($docFromRepository !== null) { + $this->document = $docFromRepository; + } else { + // create new dummy Document object + $this->document = GeneralUtility::makeInstance(Document::class); + } + } + + // Make sure configuration PID is set when applicable + if ($doc->cPid == 0) { + $doc->cPid = max($this->settings['storagePid'], 0); + } + + $this->document->setLocation($documentId); + } else { + $this->logger->error('Invalid location given "' . $documentId . '" for document loading'); + } + + return $doc; + } +} +?> diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index fd009aeb3..acc5e6b0b 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -21,3 +21,6 @@ services: tags: - name: 'console.command' command: 'kitodo:reindex' + + Kitodo\Dlf\Service\DocumentService: + public: true \ No newline at end of file From 6a83b9e6d7f71be75a898cdf9abf661006df5f24 Mon Sep 17 00:00:00 2001 From: Marco Lengua Date: Mon, 8 Dec 2025 13:33:55 +0100 Subject: [PATCH 2/2] Extend comment for loadDocument method --- Classes/Controller/AbstractController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index 052b1941f..bd8e44e83 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -119,7 +119,7 @@ protected function initialize(): void ]; } /** - * Load the current Document to Globals Temp just once with Document Service. + * Load the current Document to Globals Temp just once with Document Service - it will then be available for all controllers. * * @access protected * @return void