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>