From 13260d99adaada50c96a6fad28291d6a779a166f Mon Sep 17 00:00:00 2001
From: Georg Ringer <georg.ringer@gmail.com>
Date: Thu, 1 Mar 2018 19:30:44 +0100
Subject: [PATCH] [FEATURE] Make position of sys notes configurable

Add a new field "position" to allow editors to define where the
sys_note record is rendered.

Resolves: #83965
Releases: master
Change-Id: I22c6b5c66ce5ab58a112f844fd763a18788552f9
Reviewed-on: https://review.typo3.org/55976
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Guido Schmechel <littlegee@web.de>
Tested-by: Guido Schmechel <littlegee@web.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
---
 ...965-MakePositionOfSysNotesConfigurable.rst | 15 +++++++++++
 .../Classes/Controller/NoteController.php     |  5 ++--
 .../Domain/Repository/SysNoteRepository.php   | 18 +++++++++----
 .../sysext/sys_note/Classes/Hook/PageHook.php | 19 ++++++++++++--
 .../sys_note/Classes/Hook/RecordListHook.php  | 18 +++++++++++--
 .../sys_note/Configuration/TCA/sys_note.php   | 25 ++++++++++++++++++-
 .../Private/Language/locallang_tca.xlf        |  9 +++++++
 typo3/sysext/sys_note/ext_localconf.php       |  8 +++---
 typo3/sysext/sys_note/ext_tables.sql          |  1 +
 9 files changed, 103 insertions(+), 15 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-83965-MakePositionOfSysNotesConfigurable.rst

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-83965-MakePositionOfSysNotesConfigurable.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-83965-MakePositionOfSysNotesConfigurable.rst
new file mode 100644
index 000000000000..98edc36e3bad
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-83965-MakePositionOfSysNotesConfigurable.rst
@@ -0,0 +1,15 @@
+.. include:: ../../Includes.txt
+
+=========================================================
+Feature: #83965 - Make position of sys notes configurable
+=========================================================
+
+See :issue:`83965`
+
+Description
+===========
+
+Sys_note records can now be rendered either in the top or bottom of the page and list module by
+defining the position in the record itself.
+
+.. index:: Backend, ext:sys_note
diff --git a/typo3/sysext/sys_note/Classes/Controller/NoteController.php b/typo3/sysext/sys_note/Classes/Controller/NoteController.php
index e038ef0508e0..ddb7292b935f 100644
--- a/typo3/sysext/sys_note/Classes/Controller/NoteController.php
+++ b/typo3/sysext/sys_note/Classes/Controller/NoteController.php
@@ -40,15 +40,16 @@ class NoteController
      * Render notes by single PID or PID list
      *
      * @param string $pids Single PID or comma separated list of PIDs
+     * @param int|null $position null for no restriction, integer for defined position
      * @return string
      */
-    public function listAction($pids): string
+    public function listAction($pids, int $position = null): string
     {
         if (empty($pids) || empty($GLOBALS['BE_USER']->user['uid'])) {
             return '';
         }
 
-        $notes = $this->notesRepository->findByPidsAndAuthorId($pids, (int)$GLOBALS['BE_USER']->user['uid']);
+        $notes = $this->notesRepository->findByPidsAndAuthorId($pids, (int)$GLOBALS['BE_USER']->user['uid'], $position);
         if ($notes) {
             $view = GeneralUtility::makeInstance(StandaloneView::class);
             $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
diff --git a/typo3/sysext/sys_note/Classes/Domain/Repository/SysNoteRepository.php b/typo3/sysext/sys_note/Classes/Domain/Repository/SysNoteRepository.php
index 58a6d20a82d8..153272719a66 100644
--- a/typo3/sysext/sys_note/Classes/Domain/Repository/SysNoteRepository.php
+++ b/typo3/sysext/sys_note/Classes/Domain/Repository/SysNoteRepository.php
@@ -26,21 +26,24 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class SysNoteRepository
 {
+    const SYS_NOTE_POSITION_BOTTOM = 0;
+    const SYS_NOTE_POSITION_TOP = 1;
 
     /**
      * Find notes by given pids and author
      *
      * @param string $pids Single PID or comma separated list of PIDs
      * @param int $author author uid
+     * @param int|null $position null for no restriction, integer for defined position
      * @return array
      */
-    public function findByPidsAndAuthorId($pids, int $author): array
+    public function findByPidsAndAuthorId($pids, int $author, int $position = null): array
     {
         $pids = GeneralUtility::intExplode(',', (string)$pids);
 
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('sys_note');
-        $rows = $queryBuilder
+        $res = $queryBuilder
             ->select('sys_note.*', 'be_users.username', 'be_users.realName')
             ->from('sys_note')
             ->leftJoin(
@@ -57,9 +60,14 @@ class SysNoteRepository
                 )
             )
             ->orderBy('sorting', 'asc')
-            ->addOrderBy('crdate', 'desc')
-            ->execute()->fetchAll();
+            ->addOrderBy('crdate', 'desc');
 
-        return $rows;
+        if ($position !== null) {
+            $res->andWhere(
+                $queryBuilder->expr()->eq('sys_note.position', $queryBuilder->createNamedParameter($position, \PDO::PARAM_INT))
+            );
+        }
+
+        return $res->execute()->fetchAll();
     }
 }
diff --git a/typo3/sysext/sys_note/Classes/Hook/PageHook.php b/typo3/sysext/sys_note/Classes/Hook/PageHook.php
index f3f443005a31..050944e57e73 100644
--- a/typo3/sysext/sys_note/Classes/Hook/PageHook.php
+++ b/typo3/sysext/sys_note/Classes/Hook/PageHook.php
@@ -17,12 +17,27 @@ namespace TYPO3\CMS\SysNote\Hook;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\SysNote\Controller\NoteController;
+use TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository;
 
 /**
  * Hook for the page module
  */
 class PageHook
 {
+
+    /**
+     * Add sys_notes as additional content to the header of the page module
+     *
+     * @param array $params
+     * @param \TYPO3\CMS\Backend\Controller\PageLayoutController $parentObject
+     * @return string
+     */
+    public function renderInHeader(array $params = [], \TYPO3\CMS\Backend\Controller\PageLayoutController $parentObject)
+    {
+        $controller = GeneralUtility::makeInstance(NoteController::class);
+        return $controller->listAction($parentObject->id, SysNoteRepository::SYS_NOTE_POSITION_TOP);
+    }
+
     /**
      * Add sys_notes as additional content to the footer of the page module
      *
@@ -30,9 +45,9 @@ class PageHook
      * @param \TYPO3\CMS\Backend\Controller\PageLayoutController $parentObject
      * @return string
      */
-    public function render(array $params = [], \TYPO3\CMS\Backend\Controller\PageLayoutController $parentObject)
+    public function renderInFooter(array $params = [], \TYPO3\CMS\Backend\Controller\PageLayoutController $parentObject)
     {
         $controller = GeneralUtility::makeInstance(NoteController::class);
-        return $controller->listAction($parentObject->id);
+        return $controller->listAction($parentObject->id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM);
     }
 }
diff --git a/typo3/sysext/sys_note/Classes/Hook/RecordListHook.php b/typo3/sysext/sys_note/Classes/Hook/RecordListHook.php
index 4f78348dffbf..c5241a522d64 100644
--- a/typo3/sysext/sys_note/Classes/Hook/RecordListHook.php
+++ b/typo3/sysext/sys_note/Classes/Hook/RecordListHook.php
@@ -17,12 +17,26 @@ namespace TYPO3\CMS\SysNote\Hook;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\SysNote\Controller\NoteController;
+use TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository;
 
 /**
  * Hook for the list module
  */
 class RecordListHook
 {
+    /**
+     * Add sys_notes as additional content to the header of the list module
+     *
+     * @param array $params
+     * @param \TYPO3\CMS\Recordlist\RecordList $parentObject
+     * @return string
+     */
+    public function renderInHeader(array $params = [], \TYPO3\CMS\Recordlist\RecordList $parentObject)
+    {
+        $controller = GeneralUtility::makeInstance(NoteController::class);
+        return $controller->listAction($parentObject->id, SysNoteRepository::SYS_NOTE_POSITION_TOP);
+    }
+
     /**
      * Add sys_notes as additional content to the footer of the list module
      *
@@ -30,9 +44,9 @@ class RecordListHook
      * @param \TYPO3\CMS\Recordlist\RecordList $parentObject
      * @return string
      */
-    public function render(array $params = [], \TYPO3\CMS\Recordlist\RecordList $parentObject)
+    public function renderInFooter(array $params = [], \TYPO3\CMS\Recordlist\RecordList $parentObject)
     {
         $controller = GeneralUtility::makeInstance(NoteController::class);
-        return $controller->listAction($parentObject->id);
+        return $controller->listAction($parentObject->id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM);
     }
 }
diff --git a/typo3/sysext/sys_note/Configuration/TCA/sys_note.php b/typo3/sysext/sys_note/Configuration/TCA/sys_note.php
index 9223b393c64f..4283014b4336 100644
--- a/typo3/sysext/sys_note/Configuration/TCA/sys_note.php
+++ b/typo3/sysext/sys_note/Configuration/TCA/sys_note.php
@@ -58,12 +58,35 @@ return [
             'config' => [
                 'type' => 'check'
             ]
+        ],
+        'position' => [
+            'label' => 'LLL:EXT:sys_note/Resources/Private/Language/locallang_tca.xlf:sys_note.position',
+            'config' => [
+                'type' => 'select',
+                'renderType' => 'selectSingle',
+                'items' => [
+                    [
+                        'LLL:EXT:sys_note/Resources/Private/Language/locallang_tca.xlf:sys_note.position.top',
+                        \TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::SYS_NOTE_POSITION_TOP
+                    ],
+                    [
+                        'LLL:EXT:sys_note/Resources/Private/Language/locallang_tca.xlf:sys_note.position.bottom',
+                        \TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::SYS_NOTE_POSITION_BOTTOM
+                    ],
+                ],
+                'default' => \TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository::SYS_NOTE_POSITION_BOTTOM,
+                'fieldWizard' => [
+                    'selectIcons' => [
+                        'disabled' => false,
+                    ],
+                ],
+            ]
         ]
     ],
     'types' => [
         '0' => ['showitem' => '
             --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
-                category, subject,message,
+                category, subject,message,position,
             --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access,
                 personal,
             --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended,
diff --git a/typo3/sysext/sys_note/Resources/Private/Language/locallang_tca.xlf b/typo3/sysext/sys_note/Resources/Private/Language/locallang_tca.xlf
index 468d1e194373..d7c48262721e 100644
--- a/typo3/sysext/sys_note/Resources/Private/Language/locallang_tca.xlf
+++ b/typo3/sysext/sys_note/Resources/Private/Language/locallang_tca.xlf
@@ -27,6 +27,15 @@
 			<trans-unit id="sys_note.personal">
 				<source>Personal:</source>
 			</trans-unit>
+			<trans-unit id="sys_note.position">
+				<source>Position</source>
+			</trans-unit>
+			<trans-unit id="sys_note.position.top">
+				<source>Top</source>
+			</trans-unit>
+			<trans-unit id="sys_note.position.bottom">
+				<source>Bottom</source>
+			</trans-unit>
 		</body>
 	</file>
 </xliff>
diff --git a/typo3/sysext/sys_note/ext_localconf.php b/typo3/sysext/sys_note/ext_localconf.php
index b0de093baaf1..87595c9572de 100644
--- a/typo3/sysext/sys_note/ext_localconf.php
+++ b/typo3/sysext/sys_note/ext_localconf.php
@@ -2,8 +2,10 @@
 defined('TYPO3_MODE') or die();
 
 // Hook into the list module
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\RecordListHook::class . '->render';
-// Hook into the page module
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\PageHook::class . '->render';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\RecordListHook::class . '->renderInHeader';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\RecordListHook::class . '->renderInFooter';
+// Hook into the page modules
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\PageHook::class . '->renderInHeader';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\PageHook::class . '->renderInFooter';
 // Hook into the info module
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/web_info/class.tx_cms_webinfo.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\InfoModuleHook::class . '->render';
diff --git a/typo3/sysext/sys_note/ext_tables.sql b/typo3/sysext/sys_note/ext_tables.sql
index 8ca87eb3e859..c0a48d52f1e8 100644
--- a/typo3/sysext/sys_note/ext_tables.sql
+++ b/typo3/sysext/sys_note/ext_tables.sql
@@ -12,6 +12,7 @@ CREATE TABLE sys_note (
   message text,
   personal tinyint(3) unsigned DEFAULT '0' NOT NULL,
   category tinyint(3) unsigned DEFAULT '0' NOT NULL,
+  position int(11) DEFAULT '0' NOT NULL,
   sorting int(11) DEFAULT '0' NOT NULL,
   PRIMARY KEY (uid),
   KEY parent (pid)
-- 
GitLab