first commit
This commit is contained in:
commit
e81864e683
2984 files changed
+267797
No files matched your search
@@ -0,0 +1,142 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the package bk2k/bootstrap-package.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace BK2K\BootstrapPackage\Utility;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* ExternalMediaUtility
|
||||
*/
|
||||
class ExternalMediaUtility
|
||||
{
|
||||
/**
|
||||
* @var array Provider that can be handled, the provider is equal the hostname and needs a process function
|
||||
*/
|
||||
protected $mediaProvider = [
|
||||
'youtube',
|
||||
'youtu',
|
||||
'vimeo'
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the embed code for the given url if possible
|
||||
* and add a css class on the iframe
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $class
|
||||
* @return string|null
|
||||
*/
|
||||
public function getEmbedCode(string $url, string $class): ?string
|
||||
{
|
||||
// Prepare url
|
||||
$url = $this->setProtocolToHttps($url);
|
||||
// Get method
|
||||
$method = $this->getMethod($url);
|
||||
if ($method !== null) {
|
||||
$embedUrl = $this->{$method}($url);
|
||||
if ($embedUrl !== null) {
|
||||
return '<iframe ' . GeneralUtility::implodeAttributes([
|
||||
'class' => $class,
|
||||
'src' => $embedUrl,
|
||||
'frameborder' => '0'
|
||||
], true) . ' allowfullscreen></iframe>';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves if possible a method name to process the url
|
||||
*
|
||||
* @param string $url
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getMethod(string $url): ?string
|
||||
{
|
||||
$urlInformation = @parse_url($url);
|
||||
if (is_array($urlInformation) && isset($urlInformation['host'])) {
|
||||
$hostName = GeneralUtility::trimExplode('.', $urlInformation['host'], true);
|
||||
foreach ($this->mediaProvider as $provider) {
|
||||
$functionName = 'process' . ucfirst($provider);
|
||||
if (in_array($provider, $hostName, true) && is_callable([$this, $functionName])) {
|
||||
return $functionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes YouTube url
|
||||
*
|
||||
* @param string $url
|
||||
* @return string|null
|
||||
*/
|
||||
protected function processYoutube(string $url): ?string
|
||||
{
|
||||
$firstMatches = [];
|
||||
$pattern = '%^(?:https?://)?(?:www\.)?(?:youtu\.be/|youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=))([^"&?/ ]{11})(?:.+)?$%xs';
|
||||
if ((bool) preg_match($pattern, $url, $firstMatches)) {
|
||||
$toEmbed = $firstMatches[1];
|
||||
$patternForAdditionalParams = '%^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=))(?:[^"&?\/ ]{11})(.+)?(?:.+)?$%xs';
|
||||
$secondMatches = [];
|
||||
if (preg_match($patternForAdditionalParams, $url, $secondMatches) > 1) {
|
||||
$toEmbed .= '?' . substr($secondMatches[1], 1);
|
||||
}
|
||||
return 'https://www.youtube-nocookie.com/embed/' . $toEmbed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process YouTube short url
|
||||
*
|
||||
* @param string $url
|
||||
* @return string|null
|
||||
*/
|
||||
protected function processYoutu(string $url): ?string
|
||||
{
|
||||
return $this->processYoutube($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes Vimeo url
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
protected function processVimeo(string $url): ?string
|
||||
{
|
||||
$matches = [];
|
||||
if ((bool) preg_match('/[\\/#](\\d+)$/', $url, $matches)) {
|
||||
return 'https://player.vimeo.com/video/' . $matches[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change every protocol to https and add it if missing
|
||||
*
|
||||
* @param string $url URL
|
||||
* @return string
|
||||
*/
|
||||
protected function setProtocolToHttps(string $url): string
|
||||
{
|
||||
$processUrl = trim($url);
|
||||
if (strpos($url, 'http://') === 0) {
|
||||
$processUrl = substr($processUrl, 7);
|
||||
} elseif (strpos($processUrl, 'https://') === 0) {
|
||||
$processUrl = substr($processUrl, 8);
|
||||
} elseif (strpos($processUrl, '//') === 0) {
|
||||
$processUrl = substr($processUrl, 2);
|
||||
}
|
||||
return 'https://' . $processUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the package bk2k/bootstrap-package.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace BK2K\BootstrapPackage\Utility;
|
||||
|
||||
/**
|
||||
* Calculate image variants
|
||||
*/
|
||||
class ImageVariantsUtility
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $allowedVariantProperties = [
|
||||
'breakpoint',
|
||||
'width',
|
||||
'aspectRatio',
|
||||
'sizes',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $defaultVariants = [
|
||||
'default' => [
|
||||
'breakpoint' => 1400,
|
||||
'width' => 1280
|
||||
],
|
||||
'xlarge' => [
|
||||
'breakpoint' => 1200,
|
||||
'width' => 1100
|
||||
],
|
||||
'large' => [
|
||||
'breakpoint' => 992,
|
||||
'width' => 920
|
||||
],
|
||||
'medium' => [
|
||||
'breakpoint' => 768,
|
||||
'width' => 680
|
||||
],
|
||||
'small' => [
|
||||
'breakpoint' => 576,
|
||||
'width' => 500
|
||||
],
|
||||
'extrasmall' => [
|
||||
'width' => 374
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array|null $variants
|
||||
* @param array|null $multiplier
|
||||
* @param array|null $gutters
|
||||
* @param array|null $corrections
|
||||
* @param float|null $aspectRatio
|
||||
* @return array
|
||||
*/
|
||||
public static function getImageVariants(?array $variants = null, ?array $multiplier = null, ?array $gutters = null, ?array $corrections = null, ?float $aspectRatio = null): array
|
||||
{
|
||||
$variants = $variants !== null ? $variants : [];
|
||||
$variants = self::processVariants($variants);
|
||||
$variants = self::processResolutions($variants);
|
||||
if ($gutters !== null) {
|
||||
$variants = self::removeGutters($variants, $gutters);
|
||||
}
|
||||
if ($multiplier !== null) {
|
||||
$variants = self::processMultiplier($variants, $multiplier);
|
||||
}
|
||||
if ($corrections !== null) {
|
||||
$variants = self::processCorrections($variants, $corrections);
|
||||
}
|
||||
if ($aspectRatio !== null) {
|
||||
$variants = self::processAspectRatio($variants, $aspectRatio);
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @return array
|
||||
*/
|
||||
protected static function processResolutions(array $variants): array
|
||||
{
|
||||
foreach ($variants as $variant => $properties) {
|
||||
if (!array_key_exists('sizes', $properties)) {
|
||||
$properties['sizes'] = [];
|
||||
}
|
||||
$properties['sizes'] = self::processSizes($properties['sizes']);
|
||||
$variants[$variant] = $properties;
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sizes
|
||||
* @return array
|
||||
*/
|
||||
protected static function processSizes(array $sizes): array
|
||||
{
|
||||
$resultSizes = [];
|
||||
$workingSizes = [];
|
||||
foreach ($sizes as $key => $settings) {
|
||||
if (!array_key_exists('multiplier', $settings) ||
|
||||
!is_numeric($settings['multiplier']) ||
|
||||
$settings['multiplier'] < 1 ||
|
||||
!self::isValidSizeKey($key)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$settings['multiplier'] = gettype($settings['multiplier']) === 'double' ? $settings['multiplier'] : (int) $settings['multiplier'];
|
||||
$workingSizes[substr($key, 0, -1) . ''] = [
|
||||
'multiplier' => 1 * $settings['multiplier'],
|
||||
];
|
||||
}
|
||||
|
||||
if (!isset($workingSizes['1'])) {
|
||||
$workingSizes['1'] = ['multiplier' => 1];
|
||||
}
|
||||
ksort($workingSizes);
|
||||
foreach ($workingSizes as $workingKey => $workingSettings) {
|
||||
$resultSizes[$workingKey . 'x'] = $workingSettings;
|
||||
}
|
||||
|
||||
return $resultSizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @return array
|
||||
*/
|
||||
protected static function processVariants(array $variants): array
|
||||
{
|
||||
$variants = count($variants) > 0 ? $variants : self::$defaultVariants;
|
||||
foreach ($variants as $variant => $properties) {
|
||||
if (!is_array($properties)) {
|
||||
unset($variants[$variant]);
|
||||
continue;
|
||||
}
|
||||
foreach ($properties as $key => $value) {
|
||||
if (!in_array($key, self::$allowedVariantProperties, true)) {
|
||||
unset($variants[$variant][$key]);
|
||||
continue;
|
||||
}
|
||||
if ($key === 'sizes') {
|
||||
continue;
|
||||
} elseif ($key === 'aspectRatio') {
|
||||
if (is_numeric($value) && $value > 0) {
|
||||
$variants[$variant][$key] = (float) $value;
|
||||
} else {
|
||||
unset($variants[$variant][$key]);
|
||||
}
|
||||
} elseif (is_numeric($value) && $value > 0) {
|
||||
$variants[$variant][$key] = (int) $value;
|
||||
} else {
|
||||
unset($variants[$variant][$key]);
|
||||
}
|
||||
}
|
||||
if (count($variants[$variant]) === 0 || !isset($variants[$variant]['width'])) {
|
||||
unset($variants[$variant]);
|
||||
}
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @param array $gutters
|
||||
* @return array
|
||||
*/
|
||||
protected static function removeGutters(array $variants, array $gutters): array
|
||||
{
|
||||
foreach ($gutters as $variant => $value) {
|
||||
if (is_numeric($value) && $value > 0 && isset($variants[$variant]['width'])) {
|
||||
$variants[$variant]['width'] = (int) ceil($variants[$variant]['width'] - (float) $value);
|
||||
}
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @param array $multiplier
|
||||
* @return array
|
||||
*/
|
||||
protected static function processMultiplier(array $variants, array $multiplier): array
|
||||
{
|
||||
foreach ($multiplier as $variant => $value) {
|
||||
if (is_numeric($value) && $value > 0 && isset($variants[$variant]['width'])) {
|
||||
$variants[$variant]['width'] = (int) ceil($variants[$variant]['width'] * (float) $value);
|
||||
}
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @param array $corrections
|
||||
* @return array
|
||||
*/
|
||||
protected static function processCorrections(array $variants, array $corrections): array
|
||||
{
|
||||
foreach ($corrections as $variant => $value) {
|
||||
if (is_numeric($value) && $value > 0 && isset($variants[$variant]['width'])) {
|
||||
$variants[$variant]['width'] -= $value;
|
||||
}
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @param float $aspectRatio
|
||||
* @return array
|
||||
*/
|
||||
protected static function processAspectRatio(array $variants, float $aspectRatio): array
|
||||
{
|
||||
if ($aspectRatio > 0) {
|
||||
foreach ($variants as $variant => $value) {
|
||||
$variants[$variant]['aspectRatio'] = $aspectRatio;
|
||||
}
|
||||
}
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidSizeKey($key): bool
|
||||
{
|
||||
return !(
|
||||
!is_string($key) ||
|
||||
substr($key, -1, 1) !== 'x' ||
|
||||
!is_numeric(substr($key, 0, -1)) ||
|
||||
(float) substr($key, 0, -1) < 1 ||
|
||||
(float) substr($key, 0, -1) !== round((float) substr($key, 0, -1), 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the package bk2k/bootstrap-package.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace BK2K\BootstrapPackage\Utility;
|
||||
|
||||
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
|
||||
use TYPO3\CMS\Core\Resource\FileInterface;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||
|
||||
/**
|
||||
* SvgUtility
|
||||
*/
|
||||
class SvgUtility
|
||||
{
|
||||
/**
|
||||
* @param string $src
|
||||
* @param FileInterface|null $image
|
||||
* @param int|null $height
|
||||
* @param int|null $width
|
||||
* @param string|null $class
|
||||
* @return string
|
||||
*/
|
||||
public static function getInlineSvg(
|
||||
string $src = '',
|
||||
?FileInterface $image = null,
|
||||
?int $width = null,
|
||||
?int $height = null,
|
||||
?string $class = null
|
||||
): string {
|
||||
if (($src === '' && $image === null) || ($src !== '' && $image !== null)) {
|
||||
throw new \Exception('You must either specify a string src or a File object.', 1530601100);
|
||||
}
|
||||
|
||||
try {
|
||||
$imageService = self::getImageService();
|
||||
$image = $imageService->getImage($src, $image, false);
|
||||
if ($image->getProperty('extension') !== 'svg') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$svgContent = $image->getContents();
|
||||
$svgContent = trim((string) preg_replace('/<script[\s\S]*?>[\s\S]*?<\/script>/i', '', $svgContent));
|
||||
|
||||
// Exit if file does not contain content
|
||||
if ($svgContent === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
|
||||
$previousValueOfEntityLoader = false;
|
||||
if (PHP_MAJOR_VERSION < 8) {
|
||||
$previousValueOfEntityLoader = libxml_disable_entity_loader(true);
|
||||
}
|
||||
$svgElement = simplexml_load_string($svgContent);
|
||||
if (PHP_MAJOR_VERSION < 8) {
|
||||
libxml_disable_entity_loader($previousValueOfEntityLoader);
|
||||
}
|
||||
if (!$svgElement instanceof \SimpleXMLElement) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Override attributes
|
||||
$class = htmlspecialchars($class ?? '');
|
||||
$svgElement = self::setAttribute($svgElement, 'class', $class);
|
||||
$width = intval($width) > 0 ? (string) intval($width) : null;
|
||||
$svgElement = self::setAttribute($svgElement, 'width', $width);
|
||||
$height = intval($height) > 0 ? (string) intval($height) : null;
|
||||
$svgElement = self::setAttribute($svgElement, 'height', $height);
|
||||
|
||||
// remove xml version tag
|
||||
$domXml = dom_import_simplexml($svgElement);
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (!$domXml instanceof \DOMElement || !$domXml->ownerDocument instanceof \DOMDocument) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) $domXml->ownerDocument->saveXML($domXml->ownerDocument->documentElement);
|
||||
} catch (ResourceDoesNotExistException $e) {
|
||||
// thrown if file does not exist
|
||||
throw new \Exception($e->getMessage(), 1530601100, $e);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
// thrown if a file has been replaced with a folder
|
||||
throw new \Exception($e->getMessage(), 1530601101, $e);
|
||||
} catch (\RuntimeException $e) {
|
||||
// RuntimeException thrown if a file is outside of a storage
|
||||
throw new \Exception($e->getMessage(), 1530601102, $e);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
// thrown if file storage does not exist
|
||||
throw new \Exception($e->getMessage(), 1530601103, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $element
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
*/
|
||||
protected static function setAttribute(\SimpleXMLElement $element, string $attribute, ?string $value): \SimpleXMLElement
|
||||
{
|
||||
if ($value !== null) {
|
||||
if (isset($element->attributes()->$attribute)) {
|
||||
$element->attributes()->$attribute = $value;
|
||||
} else {
|
||||
$element->addAttribute($attribute, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of ImageService using object manager
|
||||
*
|
||||
* @return ImageService
|
||||
*/
|
||||
protected static function getImageService(): ImageService
|
||||
{
|
||||
return GeneralUtility::makeInstance(ImageService::class);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user