popnoire/site/OFF_plugins/imagekit/lib/complainingthumb.php
2026-02-12 15:22:46 +01:00

225 lines
9.2 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Kirby\Plugins\ImageKit;
use Response;
use Thumb;
use Str;
/**
* An extended version of Kirbys thumb class which is able
* to throw an error, if thumbs are resized with the
* GD Library and PHPs memory limit is exceeded or if
* thumbnail creation failed for another reason.
*/
class ComplainingThumb extends Thumb {
private static $_errorData = [];
private static $_errorFormat = 'image';
private static $_errorListening = false;
private static $_creating = false;
private static $_errorReporting;
private static $_displayErrors;
private static $_targetDimensions;
private static $_sendError = false;
private static $_reservedMemory;
public static function setErrorFormat($format = null) {
if (!is_null($format)) static::$_errorFormat = $format;
static::$_errorFormat;
}
public static function enableSendError() {
static::$_sendError = true;
}
public function create() {
if(!static::$_sendError) {
// Dont setup a error handlers, if complaining is
// not enabled and just return the result of create().
return parent::create();
}
$this->prepareErrorHandler();
$result = parent::create();
$this->restoreErrorHandler();
if(!file_exists($this->destination->root)) {
$message = str::template('Thumbnail creation for "{file}" failed. Please ensure, that the thumbs directory is writable and your driver configuration is correct.', [
'file' => static::$_errorData['file'],
]);
static::sendErrorResponse($message);
exit;
}
return $result;
}
private function prepareErrorHandler() {
// Reserve one additional megabyte of memory to make
// catching of out-of-memory errors more reliable.
// The variables content is deleted in the shutdown
// function to have more available memory to prepare an
// error.
static::$_reservedMemory = str_repeat('#', 1024 * 1024);
$dimensions = $this->source->dimensions();
$filename = str_replace(kirby()->roots()->index() . DS, '', $this->source->root());
$asset = new ProxyAsset($this->destination->root);
$asset->options($this->options);
$asset->original($this->source);
$targetDimensions = $asset->dimensions();
static::$_errorData = [
'file' => $filename,
'width' => $dimensions->width,
'height' => $dimensions->height,
'size' => $this->source->size(),
'targetWidth' => $targetDimensions->width,
'targetHeight' => $targetDimensions->height,
];
static::$_displayErrors = ini_get('display_errors');
static::$_errorReporting = error_reporting();
error_reporting(E_ALL);
ini_set('display_errors', 0);
if (!static::$_errorListening) {
// As of PHP 7.0 there is not way of de-registering a
// shutdown callback. So we only register it once at
// the first time, this method is called.
static::$_errorListening = true;
register_shutdown_function([__CLASS__, 'shutdownCallback']);
}
static::$_creating = true;
}
private function restoreErrorHandler() {
// Delete the reserved memory, because if thumbnail
// creation succeeded, it is not needed any more.
static::$_reservedMemory = null;
ini_set('display_errors', static::$_displayErrors);
error_reporting(static::$_errorReporting);
static::$_creating = false;
}
public static function shutdownCallback() {
// Delete the reserved memory to have more memory for
// preparing an error message.
static::$_reservedMemory = null;
$error = error_get_last();
if(!$error) return;
if($error['type'] == E_ERROR || $error['type'] === E_WARNING) {
if(str::contains($error['message'], 'Allowed Memory Size')) {
$message = str::template('Thumbnail creation for "{file}" failed, because source image is probably too large ({width} × {height} pixels / {size}) To fix this issue, increase the memory limit of PHP or upload a smaller version of this image.', [
'file' => static::$_errorData['file'],
'width' => number_format(static::$_errorData['width']),
'height' => number_format(static::$_errorData['height']),
'size' => number_format(static::$_errorData['size'] / (1024 * 1024), 2) . " MB",
]);
static::sendErrorResponse($message);
} else {
static::sendErrorResponse($error['message']);
}
}
}
public static function sendErrorResponse($message = '') {
// Make sure, that the error message is non-cachable
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
if(static::$_errorFormat === 'image') {
// The returned error image is an SVG file, because it
// can be created just by joined a couple of XML tags
// together and is supported by every modern browser,
// starting with IE 9 (which is of course not
// modern any more …).
header('Content-Type: image/svg+xml');
// Although this is technically not correct, we have
// to send status code 200, otherwise the image does
// not show up in Firefox and Safari, although it
// works with code 500 in Chrome and Edge. Also tested
// in IE 10, IE 11
http_response_code(200);
$width = static::$_errorData['targetWidth'];
$height = static::$_errorData['targetHeight'];
// Return an SVG File with the thumbs dimensions
// Icon Credit: fontawesome.io
?><svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="<?= $width ?>" height="<?= $height ?>"
viewBox="0 0 <?= $width ?> <?= $height ?>"
preserveAspectRatio="none">
<symbol id="icon">
<svg viewBox="0 0 48 44.52" width="48" height="44.52" preserveAspectRatio="xMinYMax meet">
<path d="M27.425,36.789V31.705a0.854,0.854,0,0,0-.254-0.629,0.823,0.823,0,0,0-.6-0.254H21.431a0.823,0.823,0,0,0-.6.254,0.854,0.854,0,0,0-.254.629v5.084a0.854,0.854,0,0,0,.254.629,0.823,0.823,0,0,0,.6.254h5.137a0.823,0.823,0,0,0,.6-0.254A0.854,0.854,0,0,0,27.425,36.789ZM27.371,26.782L27.853,14.5a0.589,0.589,0,0,0-.268-0.508,1.034,1.034,0,0,0-.642-0.294H21.057a1.034,1.034,0,0,0-.642.294,0.64,0.64,0,0,0-.268.562L20.6,26.782a0.514,0.514,0,0,0,.268.441,1.152,1.152,0,0,0,.642.174h4.95a1.088,1.088,0,0,0,.629-0.174A0.6,0.6,0,0,0,27.371,26.782ZM27,1.793L47.545,39.464a3.192,3.192,0,0,1-.054,3.371,3.422,3.422,0,0,1-2.943,1.686H3.452A3.422,3.422,0,0,1,.509,42.835a3.192,3.192,0,0,1-.054-3.371L21,1.793A3.417,3.417,0,0,1,22.261.482a3.381,3.381,0,0,1,3.478,0A3.417,3.417,0,0,1,27,1.793Z" fill="#ffffff"/>
</svg>
</symbol>
<rect width="100%" height="100%" fill="#F4999D" />
<switch>
<foreignObject width="100%" height="100%" requiredExtensions="http://www.w3.org/1999/xhtml">
<body xmlns="http://www.w3.org/1999/xhtml" style="background:#F4999D;text-align:center;color:#fff;box-sizing:border-box;margin:0;padding:0;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif">
<p style="margin:0;word-wrap:break-word;position:absolute;top:50%;transform:translateY(-50%);width: 100%;box-sizing:border-box;padding: 0 1em;">
<svg viewBox="0 0 48 44.52" width="24" height="22.125" xmlns="http://www.w3.org/2000/svg" style="display: block; margin: 0 auto 12px;"><path d="M27.425,36.789V31.705a0.854,0.854,0,0,0-.254-0.629,0.823,0.823,0,0,0-.6-0.254H21.431a0.823,0.823,0,0,0-.6.254,0.854,0.854,0,0,0-.254.629v5.084a0.854,0.854,0,0,0,.254.629,0.823,0.823,0,0,0,.6.254h5.137a0.823,0.823,0,0,0,.6-0.254A0.854,0.854,0,0,0,27.425,36.789ZM27.371,26.782L27.853,14.5a0.589,0.589,0,0,0-.268-0.508,1.034,1.034,0,0,0-.642-0.294H21.057a1.034,1.034,0,0,0-.642.294,0.64,0.64,0,0,0-.268.562L20.6,26.782a0.514,0.514,0,0,0,.268.441,1.152,1.152,0,0,0,.642.174h4.95a1.088,1.088,0,0,0,.629-0.174A0.6,0.6,0,0,0,27.371,26.782ZM27,1.793L47.545,39.464a3.192,3.192,0,0,1-.054,3.371,3.422,3.422,0,0,1-2.943,1.686H3.452A3.422,3.422,0,0,1,.509,42.835a3.192,3.192,0,0,1-.054-3.371L21,1.793A3.417,3.417,0,0,1,22.261.482a3.381,3.381,0,0,1,3.478,0A3.417,3.417,0,0,1,27,1.793Z" fill="#ffffff"/></svg>
<?= $message ?>
</p>
</body>
</foreignObject>
<!-- Fallback -->
<use xlink:href="#icon" transform="translate(<?= number_format($width / 2 - 48 / 2,1,'.','') ?>, <?= number_format($height / 2 - 44.52 / 2,1,'.','') ?>)" />
</switch>
</svg><?php
} else {
// If error format has been set to JSON, return JSON ;-)
header('Content-Type: application/json; charset=utf-8');
http_response_code(500);
echo json_encode([
'status' => '',
'code' => 500,
'message' => $message,
'data' => [
'file' => static::$_errorData,
],
]);
}
exit;
}
}