Commit a15ddcf5 authored by Georg Ringer's avatar Georg Ringer Committed by Frank Nägler
Browse files

[!!!][TASK] Migrate sys_notes away from extbase

Simplify the sys_note handling by removing extbase from it

Resolves: #84055
Releases: master
Change-Id: Ib41d5e88c7ec9d79ee23dc913c3dc1ee0184c372
Reviewed-on: https://review.typo3.org/55804

Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Frank Nägler's avatarFrank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Nägler's avatarFrank Naegler <frank.naegler@typo3.org>
Tested-by: default avatarTYPO3com <no-reply@typo3.com>
parent 5fbab6b6
.. include:: ../../Includes.txt
==============================================================================
Deprecation: #82506 - Remove BackendUserRepository injection in NoteController
==============================================================================
===========================================================================
Breaking: #82506 - Remove BackendUserRepository injection in NoteController
===========================================================================
See :issue:`82506`
......@@ -16,7 +16,7 @@ removed in :php:`\TYPO3\CMS\SysNote\Controller\NoteController`.
Impact
======
The method :php:`\TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::findByPidsAndAuthor` has been marked as deprecated.
The method :php:`\TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::findByPidsAndAuthor` has been removed.
Affected Installations
......@@ -29,7 +29,7 @@ Any installation using third-party extension that use the method
Migration
=========
Use the method :php:`\TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::findByPidsAndAuthorId`. and use the
user id as 2nd argument instead of a `BackendUser` object.
Use the method :php:`\TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::findByPidsAndAuthorId`, and use the
user id as 2nd argument instead of a `BackendUser` object.
.. index:: Backend, PHP-API, FullyScanned, ext:sys_note
.. include:: ../../Includes.txt
======================================================
Breaking: #84055 - Migrate sys_notes away from extbase
======================================================
See :issue:`84055`
Description
===========
To simplify the rendering of sys_note records and improve the performance, the usage of `extbase` has
been removed from the extension `sys_note`.
Impact
======
The model :php:`TYPO3\CMS\SysNote\Domain\Model\SysNote` has been removed,
the repository :php:`TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository` now
returns a plain result instead of objects.
It is not possible anymore more to change the template path of the extension.
Affected Installations
======================
Any installation which relies on the repository and model or changed the template by using TypoScript.
Migration
=========
To change the rendering of notes, override the hook and return a modified output.
.. index:: Backend, PartiallyScanned, ext:sys_note
\ No newline at end of file
......@@ -512,6 +512,11 @@ return [
'Breaking-82426-ExtJSAndExtDirectRemoval.rst',
],
],
'TYPO3\CMS\SysNote\Domain\Model\SysNote' => [
'restFiles' => [
'Breaking-84055-MigrateSys_notesAwayFromExtbase.rst',
],
],
// Removed interfaces
'TYPO3\CMS\Backend\Form\DatabaseFileIconsHookInterface' => [
......
......@@ -1230,7 +1230,7 @@ return [
'numberOfMandatoryArguments' => 2,
'maximumNumberOfArguments' => 2,
'restFiles' => [
'Deprecation-82506-RemoveBackendUserRepositoryInjectionInNoteController.rst',
'Breaking-82506-RemoveBackendUserRepositoryInjectionInNoteController.rst',
],
],
'TYPO3\CMS\Core\Service\AbstractService->devLog' => [
......
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\SysNote\Controller;
/*
......@@ -14,22 +15,25 @@ namespace TYPO3\CMS\SysNote\Controller;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository;
/**
* Note controller
* Renders notes for the current backend user
*
* @internal
*/
class NoteController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
class NoteController
{
/**
* @var \TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository
* @var SysNoteRepository
*/
protected $sysNoteRepository;
protected $notesRepository;
/**
* @param \TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository $sysNoteRepository
*/
public function injectSysNoteRepository(\TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository $sysNoteRepository)
public function __construct()
{
$this->sysNoteRepository = $sysNoteRepository;
$this->notesRepository = GeneralUtility::makeInstance(SysNoteRepository::class);
}
/**
......@@ -38,12 +42,23 @@ class NoteController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
* @param string $pids Single PID or comma separated list of PIDs
* @return string
*/
public function listAction($pids)
public function listAction($pids): string
{
if (empty($pids) || empty($GLOBALS['BE_USER']->user['uid'])) {
return '';
}
$notes = $this->sysNoteRepository->findByPidsAndAuthorId($pids, $GLOBALS['BE_USER']->user['uid']);
$this->view->assign('notes', $notes);
$notes = $this->notesRepository->findByPidsAndAuthorId($pids, (int)$GLOBALS['BE_USER']->user['uid']);
if ($notes) {
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
'EXT:sys_note/Resources/Private/Templates/Note/List.html'
));
$view->getRequest()->setControllerExtensionName('SysNote');
$view->assign('notes', $notes);
return $view->render();
}
return '';
}
}
<?php
namespace TYPO3\CMS\SysNote\Core;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Bootstrap for note module
*/
class Bootstrap
{
/**
* Do not touch if you are not sure what you are doing!
* @var array
*/
protected $extbaseConfiguration = [
'vendorName' => 'TYPO3\\CMS',
'extensionName' => 'SysNote',
'pluginName' => 'Note',
];
/**
* @var array
*/
protected $currentGetArguments;
/**
* Bootstrap extbase and execute controller
*
* @param string $controllerName Controller to execute
* @param string $actionName Action to run
* @param array $arguments Arguments to pass to the controller action
* @return string
*/
public function run($controllerName, $actionName, array $arguments = [])
{
if (!$this->expectOutput($arguments)) {
return '';
}
$arguments['controller'] = ucfirst(trim($controllerName));
$arguments['action'] = lcfirst(trim($actionName));
$this->overrideGetArguments($arguments);
/** @var $extbaseBootstrap \TYPO3\CMS\Extbase\Core\Bootstrap */
$extbaseBootstrap = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class);
$content = $extbaseBootstrap->run('', $this->extbaseConfiguration);
$this->revertGetArguments();
return $content;
}
/**
* Check if the note plugin expects output. If there are no sys_note records on the given
* pages, the extbase bootstrap doesn't have to run the complete plugin.
* This mechanism should increase the performance of the hooked backend modules heavily.
*
* @param array $arguments Arguments for the extbase plugin
* @return bool
*/
protected function expectOutput(array $arguments = [])
{
// no pids set
if (!isset($arguments['pids']) || empty($arguments['pids']) || empty($GLOBALS['BE_USER']->user['uid'])) {
return false;
}
$cleanedPageIds = GeneralUtility::intExplode(',', $arguments['pids'], true);
if (empty($cleanedPageIds)) {
return false;
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_note');
$count = $queryBuilder
->count('uid')
->from('sys_note')
->where(
$queryBuilder->expr()->in(
'pid',
$queryBuilder->createNamedParameter($cleanedPageIds, Connection::PARAM_INT_ARRAY)
)
)
->execute()
->fetchColumn();
return (bool)$count;
}
/**
* Modify $_GET to force specific controller, action and arguments in
* extbase bootstrap process
*
* Note: Overwriting $_GET was the most simple solution here until extbase
* provides a clean way to force a controller and action in backend mode.
*
* @param array $arguments The arguments to set
*/
protected function overrideGetArguments(array $arguments)
{
$this->currentGetArguments = $_GET;
$_GET['tx_sysnote_note'] = $arguments;
}
/**
* Revert previously backuped get arguments
*/
protected function revertGetArguments()
{
if (is_array($this->currentGetArguments)) {
$_GET = $this->currentGetArguments;
}
}
}
<?php
namespace TYPO3\CMS\SysNote\Domain\Model;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* SysNote model
*/
class SysNote extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* @var \DateTime
*/
protected $creationDate;
/**
* @var \DateTime
*/
protected $modificationDate;
/**
* @var \TYPO3\CMS\Extbase\Domain\Model\BackendUser
*/
protected $author;
/**
* @var string
*/
protected $subject;
/**
* @var string
*/
protected $message;
/**
* @var bool
*/
protected $personal;
/**
* @var int
*/
protected $category;
/**
* @return \DateTime $creationDate
*/
public function getCreationDate()
{
return $this->creationDate;
}
/**
* @param \DateTime $creationDate
*/
public function setCreationDate($creationDate)
{
$this->creationDate = $creationDate;
}
/**
* @return \DateTime $modificationDate
*/
public function getModificationDate()
{
return $this->modificationDate;
}
/**
* @param \DateTime $modificationDate
*/
public function setModificationDate($modificationDate)
{
$this->modificationDate = $modificationDate;
}
/**
* @return \TYPO3\CMS\Extbase\Domain\Model\BackendUser $author
*/
public function getAuthor()
{
return $this->author;
}
/**
* @param \TYPO3\CMS\Extbase\Domain\Model\BackendUser $author
*/
public function setAuthor(\TYPO3\CMS\Extbase\Domain\Model\BackendUser $author)
{
$this->author = $author;
}
/**
* @return string $subject
*/
public function getSubject()
{
return $this->subject;
}
/**
* @param string $subject
*/
public function setSubject($subject)
{
$this->subject = $subject;
}
/**
* @return string $message
*/
public function getMessage()
{
return $this->message;
}
/**
* @param string $message
*/
public function setMessage($message)
{
$this->message = $message;
}
/**
* @return bool $personal
*/
public function getPersonal()
{
return $this->personal;
}
/**
* @param bool $personal
*/
public function setPersonal($personal)
{
$this->personal = $personal;
}
/**
* @return int $category
*/
public function getCategory()
{
return $this->category;
}
/**
* @param int $category
*/
public function setCategory($category)
{
$this->category = $category;
}
}
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\SysNote\Domain\Repository;
/*
......@@ -14,76 +15,51 @@ namespace TYPO3\CMS\SysNote\Domain\Repository;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Sys_note repository
*
* @internal
*/
class SysNoteRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
class SysNoteRepository
{
/**
* Initialize the repository
*/
public function initializeObject()
{
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
/**
* Find notes by given pids and author
*
* @param string $pids Single PID or comma separated list of PIDs
* @param \TYPO3\CMS\Extbase\Domain\Model\BackendUser $author The author
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
* @deprecated
*/
public function findByPidsAndAuthor($pids, \TYPO3\CMS\Extbase\Domain\Model\BackendUser $author)
{
trigger_error('Method findByPidsAndAuthor() is deprecated since v9 and will be removed with v10', E_USER_DEPRECATED);
$pids = GeneralUtility::intExplode(',', (string)$pids);
$query = $this->createQuery();
$query->setOrderings([
'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
'creationDate' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
$query->matching(
$query->logicalAnd(
$query->in('pid', $pids),
$query->logicalOr(
$query->equals('personal', 0),
$query->equals('author', $author)
)
)
);
return $query->execute();
}
/**
* Find notes by given pids and author
*
* @param string $pids Single PID or comma separated list of PIDs
* @param int $author author uid
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
* @return array
*/
public function findByPidsAndAuthorId($pids, int $author)
public function findByPidsAndAuthorId($pids, int $author): array
{
$pids = GeneralUtility::intExplode(',', (string)$pids);
$query = $this->createQuery();
$query->setOrderings([
'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
'creationDate' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
$query->matching(
$query->logicalAnd(
$query->in('pid', $pids),
$query->logicalOr(
$query->equals('personal', 0),
$query->equals('author', $author)
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_note');
$rows = $queryBuilder
->select('sys_note.*', 'be_users.username', 'be_users.realName')
->from('sys_note')
->leftJoin(
'sys_note',
'be_users',
'be_users',
$queryBuilder->expr()->eq('sys_note.cruser', $queryBuilder->quoteIdentifier('be_users.uid'))
)
->where(
$queryBuilder->expr()->in('sys_note.pid', $queryBuilder->createNamedParameter($pids, Connection::PARAM_INT_ARRAY)),
$queryBuilder->expr()->orX(
$queryBuilder->expr()->in('sys_note.personal', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
$queryBuilder->expr()->in('sys_note.cruser', $queryBuilder->createNamedParameter($author, \PDO::PARAM_INT))
)
)
);
return $query->execute();
->orderBy('sorting', 'asc')
->addOrderBy('crdate', 'desc')
->execute()->fetchAll();
return $rows;
}
}
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\SysNote\Hook;
/*
......@@ -14,6 +15,9 @@ namespace TYPO3\CMS\SysNote\Hook;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\SysNote\Controller\NoteController;
/**
* Hook for the info module
*/
......@@ -28,8 +32,7 @@ class InfoModuleHook
*/
public function render(array $params = [], \TYPO3\CMS\Info\Controller\PageInformationController $parentObject)
{
/** @var $noteBootstrap \TYPO3\CMS\SysNote\Core\Bootstrap */
$noteBootstrap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\SysNote\Core\Bootstrap::class);
return $noteBootstrap->run('Note', 'list', ['pids' => $parentObject->pObj->id]);
$controller = GeneralUtility::makeInstance(NoteController::class);
return $controller->listAction($parentObject->pObj->id);
}
}
<
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\SysNote\Hook;
/*
......@@ -14,6 +15,9 @@ namespace TYPO3\CMS\SysNote\Hook;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\SysNote\Controller\NoteController;