Skip to content

Commit

Permalink
Prepare 1.0.0 release (pixelant#1)
Browse files Browse the repository at this point in the history
* [FEATURE] Added fallback to PageContentErrorHandler

Wrapped in a try block. If this still doesn't return a result, we show a generic error page.

* [BUGFIX] Compatibility with TYPO3 v9 and v10

* [FEATURE] Override default Page Content error handler by default

Can be disabled through extension configuration.

* [TASK] Increased PHP dependency to ^7.2

* [TASK] Updated description and contact info

* [FEATURE] Handle language fallback and use TYPO3 APIs

* [DOCS] Updated README.md
  • Loading branch information
mabolek authored Jun 10, 2020
1 parent 0e88f56 commit 152922e
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 52 deletions.
76 changes: 43 additions & 33 deletions Classes/Error/PageErrorHandler/LocalPageErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Controller\ErrorPageController;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\HtmlResponse;
Expand All @@ -29,6 +29,7 @@
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
use TYPO3\CMS\Frontend\Http\RequestHandler;

/**
Expand Down Expand Up @@ -58,11 +59,15 @@ public function handlePageError(ServerRequestInterface $request, string $message
}
}

$content = GeneralUtility::makeInstance(ErrorPageController::class)->errorAction(
$this->statusCode,
$this->getHttpUtilityStatusInformationText()
);
return new HtmlResponse($content, $this->statusCode);
try {
return parent::handlePageError($request, $message, $reasons);
} catch (\Exception $exception) {
$content = GeneralUtility::makeInstance(ErrorPageController::class)->errorAction(
$this->statusCode,
$this->getHttpUtilityStatusInformationText()
);
return new HtmlResponse($content, $this->statusCode);
}
}

/**
Expand Down Expand Up @@ -100,11 +105,19 @@ protected function resolveDetails(string $typoLinkUrl): array
protected function buildDispatcher()
{
$requestHandler = GeneralUtility::makeInstance(RequestHandler::class);
$resolver = new MiddlewareStackResolver(
GeneralUtility::makeInstance(PackageManager::class),
GeneralUtility::makeInstance(DependencyOrderingService::class),
GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core')
);

if (VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) >= 10000000) {
$resolver = GeneralUtility::makeInstance(
MiddlewareStackResolver::class
);
} else {
$resolver = GeneralUtility::makeInstance(
MiddlewareStackResolver::class,
GeneralUtility::makeInstance(PackageManager::class),
GeneralUtility::makeInstance(DependencyOrderingService::class),
GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core')
);
}

$middlewares = $resolver->resolve('frontend');
return new MiddlewareDispatcher($requestHandler, $middlewares);
Expand Down Expand Up @@ -142,7 +155,17 @@ protected function resolvePageId(ServerRequestInterface $request, int $pageId):
if ($siteLanguage instanceof SiteLanguage) {
$languageId = $siteLanguage->getLanguageId() ?? 0;
if ($languageId > 0) {
return $this->getLocalizedPageId($pageId, $languageId);
$translatedPageId = $this->getLocalizedPageId($pageId, $languageId);

foreach ($siteLanguage->getFallbackLanguageIds() as $languageId) {
if ($translatedPageId !== null) {
break;
}

$translatedPageId = $this->getLocalizedPageId($pageId, $languageId);
}

return $translatedPageId;
}
}
return $pageId;
Expand All @@ -157,29 +180,16 @@ protected function resolvePageId(ServerRequestInterface $request, int $pageId):
*/
protected function getLocalizedPageId(int $pageId, int $languageId): ?int
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');

$statement = $queryBuilder
->select('uid')
->from('pages')
->where(
$queryBuilder->expr()->eq(
'l10n_parent',
$queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
),
$queryBuilder->expr()->eq(
'sys_language_uid',
$queryBuilder->createNamedParameter($languageId, \PDO::PARAM_INT)
)
)
->execute();

$page = $statement->fetch();
if (empty($page)) {
$page = BackendUtility::getRecordLocalization(
'pages',
$pageId,
$languageId
);

if ($page === false || empty($page)) {
return null;
}
return $page['uid'];
return $page[0]['uid'];
}

/**
Expand Down
26 changes: 17 additions & 9 deletions Configuration/SiteConfiguration/Overrides/site_errorhandling.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
<?php
// Show both errorPhpClassFQCN and errorContentSource for PHP Class error handler
$currentShowItem = $GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem'];
if (strpos($currentShowItem, 'errorContentSource') === false) {
// Add errorContentSource for PHP Class error handler if not already present
$GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem'] = str_replace(
'errorPhpClassFQCN',
'errorPhpClassFQCN, errorContentSource',
$GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem']
);

if (
!TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class
)
->get('pxa_lpeh', 'disableXClass')
) {
// Show both errorPhpClassFQCN and errorContentSource for PHP Class error handler
$currentShowItem = $GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem'];
if (strpos($currentShowItem, 'errorContentSource') === false) {
// Add errorContentSource for PHP Class error handler if not already present
$GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem'] = str_replace(
'errorPhpClassFQCN',
'errorPhpClassFQCN, errorContentSource',
$GLOBALS['SiteConfiguration']['site_errorhandling']['types']['PHP']['showitem']
);
}
}
43 changes: 38 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
# pxa_lpeh
# Local Page Error Handler for TYPO3

Local Page Error Handler
This extension speeds up error page handling and frees up PHP workers by loading local page content without issuing an external HTTP request.

To use as error handler, go to site configuration "Error Handler" tab.
The speed increase depends on the round-trip time for external HTTP requests for your server (including resolving the DNS), but it could easily be 3x what you're having today.

## Installation

1. Download from the TYPO3 Extension Repository or require the extension using Composer: `composer req pixelant/pxa-lpeh`
2. Enable the extension in the Admin tools > Extensions module or run `vendor/bin/typo3 extension:activate pxa_lpeh`

## Configuration

### Default Configuration

No configuration is required by default.

The extension will use the configuration for any "Show Content from Page" error handler.

* Make internal requests where Show Content From Page is to an internal TYPO3 page, e.g. "t3://page?uid=404".
* External requests will behave normally and issue an external request. E.g. where Show Content From Page points to "https://www.example.com".

### Disabling Page Content Error Handler Override

By default, this extension overrides the `PageContentErrorHandler` class and calls this class only if the Error Handler configuration explicitly requires an external request.

You can disable this override in the Admin tools > Settings > Extension Configuration by checking the box "Don't replace the standard 'Show Content from Page' error handler, use 'PHP Class' instead".

This extension can still be used by explicitly configuring a PHP Error Handler Class in Site management > Sites > [Your Site] > Error Handling:

1. Create a new error handling
2. Set "HTTP Error Status Code" to 404
3. Set "How to handle Errors" to "PHP Class"
4. Set "ErrorHandler Class Target (FQCN)" to ```Pixelant\PxaLpeh\Error\PageErrorHandler\LocalPageErrorHandler```
5. Set "Show Content from Page" to a *page* in current Site to generate a link e.g. t3://page?uid=78

If TYPO3 fails to fetch the page, a "generic" TYPO3 error page will be displayed with the http status code.
This might be e.g. the link isn't to a page, the page doesn't exist in this site etc.
### Avoiding Hung HTTP Requests

External requests for error pages can hang your site during high-load situations. We recommend setting `$GLOBALS['TYPO3_CONF_VARS']['HTTP']['timeout']` to a non-zero value to alleviate this problem.

## Ultimate Error Fallback

If fetching the page fails, a "generic" TYPO3 error page will be displayed with the http status code. This might be e.g. the link isn't to a page, the page doesn't exist in this site etc.

## Issues and Contribution

Please feel free to submit issues or contribute pull requests to this extension.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"name": "pixelant/pxa-lpeh",
"description": "Local Page Error Handler for TYPO3 CMS.",
"description": "Speeds up error page handling and frees up PHP workers by loading local page content without issuing an external HTTP request.",
"version": "1.0.0",
"type": "typo3-cms-extension",
"license": "GPL-3.0+",
"authors": [
{
"name": "Pixelant",
"email": "[email protected]",
"homepage": "https://www.pixelant.se",
"role": "Developer"
}
Expand All @@ -23,7 +24,7 @@
"pixelant/pxa-lpeh": "self.version"
},
"require": {
"php": ">= 7.0, <=7.3",
"php": "^7.2",
"typo3/cms-core": "^9.5.0 || ^10.1.0"
},
"autoload": {
Expand Down
2 changes: 2 additions & 0 deletions ext_conf_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# cat=Runtime; type=boolean; label=Don't replace the standard "Show Content from Page" error handler, use "PHP Class" instead
disableXClass = 0
6 changes: 3 additions & 3 deletions ext_emconf.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php
$EM_CONF[$_EXTKEY] = array(
'title' => 'Local Page Error Handler',
'description' => 'Add Local Page Error Handler to TYPO3',
'description' => 'Speeds up error page handling and frees up PHP workers by loading local page content without issuing an external HTTP request.',
'category' => 'fe',
'author' => 'Pixelant',
'author_email' => '',
'author_email' => '[email protected]',
'author_company' => 'Pixelant',
'state' => 'alpha',
'state' => 'stable',
'uploadfolder' => 0,
'createDirs' => '',
'clearCacheOnLoad' => 0,
Expand Down
19 changes: 19 additions & 0 deletions ext_localconf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
defined('TYPO3_MODE') or die();

$boot = function() {
if (
!TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class
)
->get('pxa_lpeh', 'disableXClass')
) {
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler::class] = [
'className' => Pixelant\PxaLpeh\Error\PageErrorHandler\LocalPageErrorHandler::class
];
}

};

$boot();
unset($boot);

0 comments on commit 152922e

Please sign in to comment.