For coders TYPO3 Tech Corner

[PHP] Show the editor responsible for a page tree in the TYPO3 backend

[PHP] Show the editor responsible for a page tree in the TYPO3 backend

ext_tables.sql:

CREATE TABLE pages ( responsible_name varchar(255) DEFAULT '' NOT NULL, responsible_email varchar(255) DEFAULT '' NOT NULL, );

ext_localconf.php:

<?php defined('TYPO3_MODE') || die(); call_user_func( function () { /** * Show responsible person in backend page module */ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'][] = \Unitue\Project\Hooks\PageModule::class . '->manipulate'; } );

PageModule.php:

<?php declare(strict_types=1); namespace Unitue\Project\Hooks; use TYPO3\CMS\Backend\Controller\PageLayoutController; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException; use TYPO3\CMS\Fluid\View\StandaloneView; use Unitue\Project\Utility\DatabaseUtility; use Unitue\Project\Utility\ObjectUtility; /** * Class PageModule */ class PageModule { /** * @var string */ protected $templatePathAndFile = 'EXT:project/Resources/Private/Templates/Hooks/ResponsiblePageModule.html'; /** * @param array $params * @param PageLayoutController $pageLayoutController * @return string * @throws InvalidExtensionNameException */ public function manipulate(array $params, PageLayoutController $pageLayoutController): string { unset($params); $pageIdentifier = $pageLayoutController->id; $properties = $this->getResponsiblePropertiesToPage($pageIdentifier); $properties = $properties + $this->getLastChangedPropertiesToPage($pageIdentifier); $properties = $properties + $this->getUserPropertiesToIdentifier($properties['userid']); return $this->renderMarkup($properties); } /** * @param int $pageIdentifier * @return array */ protected function getResponsiblePropertiesToPage(int $pageIdentifier): array { $properties = $this->getPropertiesToPage($pageIdentifier, ['responsible_name', 'responsible_email']); if (empty($properties['responsible_name']) && empty($properties['responsible_email'])) { $parentPageIdentifier = $this->getPropertiesToPage($pageIdentifier, ['pid'])['pid']; if ($parentPageIdentifier > 0) { $properties = $this->getResponsiblePropertiesToPage($parentPageIdentifier); } } return $properties; } /** * @param int $pageIdentifier * @param array $properties * @return array */ protected function getPropertiesToPage(int $pageIdentifier, array $properties): array { $queryBuilder = DatabaseUtility::getQueryBuilderForTable('pages', true); $rows = $queryBuilder ->select(...$properties) ->from('pages') ->where('uid=' . (int)$pageIdentifier) ->setMaxResults(1) ->execute() ->fetchAll(); return $rows[0]; } /** * @param int $pageIdentifier * @return array */ protected function getLastChangedPropertiesToPage(int $pageIdentifier): array { $contentElements = $this->getContentElementsToPage($pageIdentifier); $queryBuilder = DatabaseUtility::getQueryBuilderForTable('sys_log'); $rows = $queryBuilder ->select('userid', 'tstamp') ->from('sys_log') ->where('tablename="tt_content" and recuid in (' . implode(',', $contentElements) . ')') ->orderBy('tstamp', 'desc') ->setMaxResults(1) ->execute() ->fetchAll(); $properties = [ 'userid' => 0, 'tstamp' => 0 ]; if (!empty($rows[0])) { $properties = $rows[0]; } return $properties; } /** * @param int $userIdentifier * @return array */ protected function getUserPropertiesToIdentifier(int $userIdentifier): array { $queryBuilder = DatabaseUtility::getQueryBuilderForTable('be_users'); $rows = $queryBuilder ->select('username', 'realName', 'email') ->from('be_users') ->where('uid=' . (int)$userIdentifier) ->execute() ->fetchAll(); $properties = [ 'username' => '', 'realName' => '', 'email' => '' ]; if (!empty($rows[0])) { $properties = $rows[0]; } return $properties; } /** * @param int $pageIdentifier * @return array */ protected function getContentElementsToPage(int $pageIdentifier): array { $queryBuilder = DatabaseUtility::getQueryBuilderForTable('tt_content', true); $rows = $queryBuilder ->select('uid') ->from('tt_content') ->where('pid=' . (int)$pageIdentifier . ' and deleted=0') ->execute() ->fetchAll(); $contentElements = [0]; foreach ($rows as $row) { $contentElements[] = $row['uid']; } return $contentElements; } /** * @param array $properties * @return string * @throws InvalidExtensionNameException */ protected function renderMarkup(array $properties): string { /** @var StandaloneView $standaloneView */ $standaloneView = ObjectUtility::getObjectManager()->get(StandaloneView::class); $standaloneView->getRequest()->setControllerExtensionName('in2template'); $standaloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($this->templatePathAndFile)); $standaloneView->assignMultiple($properties); return $standaloneView->render(); } }

ResponsiblePageModule.html:

{namespace p=Unitue\Project\ViewHelpers} <f:if condition="{responsible_name} || {responsible_email}"> <div class="callout callout-warning"> <div class="media"> <div class="media-left"> <span class="fa-stack fa-lg callout-icon"> <i class="fa fa-circle fa-stack-2x"></i> <i class="fa fa-info fa-stack-1x"></i> </span> </div> <div class="media-body"> <h4 class="callout-title"> <f:translate key="LLL:EXT:project/Resources/Private/Language/Backend/locallang.xlf:pageModuleResponsible.responsiblename">Responsible</f:translate> </h4> <div class="callout-body"> <f:render section="ResponsibleName" arguments="{_all}" /> <f:render section="LastChange" arguments="{_all}" /> </div> </div> </div> </div> </f:if> <f:section name="ResponsibleName"> <p> <strong> <f:link.typolink parameter="{responsible_email}"> <f:if condition="{responsible_name}"> <f:then>{responsible_name}</f:then> <f:else>{responsible_email}</f:else> </f:if> </f:link.typolink> </strong> </p> </f:section> <f:section name="LastChange"> <f:if condition="{userid} > 0"> <p> <f:translate key="LLL:EXT:project/Resources/Private/Language/Backend/locallang.xlf:pageModuleResponsible.lastchangename">Last change</f:translate> <f:render section="UserName" arguments="{_all}" /> <span title="{f:format.date(format:'%d.%m.%Y %H:%M', date:'@{tstamp}')}">(<p:format.readableDate>{tstamp}</p:format.readableDate>)</span> </p> </f:if> </f:section> <f:section name="UserName"> <f:link.typolink parameter="{email}"> <f:if condition="{realName}"> <f:then>{realName}</f:then> <f:else>{username}</f:else> </f:if> </f:link.typolink> </f:section>

Back

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us