Skip to content

Commit

Permalink
[!!!][FEATURE] Add automatic image scaling for structure elements
Browse files Browse the repository at this point in the history
In templates bootstrap columns can now be created with the view
helper `pp.render.bootstrap.column` or wrapped with the
`pp:structure.wrap.column` view helper allowing to propagate
information regarding the available content with.

CORRECTIVE ACTION: On sites using extension to structure the
content area (e.g. `pp_gridelements` or `flux_elements`) the
field `Image scaling` (register `Image` from content element)
needs to be reviewed. In most cases it can be set to its default
value since the scaling is now automatically calculated.
  • Loading branch information
buepro committed Jun 4, 2020
1 parent 6ddb79f commit df299b4
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 131 deletions.
92 changes: 92 additions & 0 deletions Classes/Utility/StructureMultiplierUtility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php


namespace Buepro\Pizpalue\Utility;

use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Used to calculate the structure multiplier.
*/
class StructureMultiplierUtility
{
private static $defaultMultiplier = [
'extrasmall' => 1,
'small' => 1,
'medium' => 1,
'large' => 1,
'default' => 1
];

private static $breakpointMap = [
'extrasmall' => '',
'small' => 'sm',
'medium' => 'md',
'large' => 'lg',
'default' => 'xl'
];

/**
* Calculates the factor for a breakpoint based on the css items used to define the column and the column count
* from the row.
*
* @param array $items CSS items defining the column (e.g. ['col', 'col-md', 'col-lg-4'])
* @param int $count
* @param string $breakpoint
* @return bool|float|int
*/
private static function getColumnFactorForBreakpoint(array $items, int $count, string $breakpoint) {
$factor = false;
foreach ($items as $item) {
$parts = GeneralUtility::trimExplode('-', $item, true);
if ($parts[0] !== 'col') {
continue;
}
// CSS definition `col`
if (count($parts) === 1 && $breakpoint === 'extrasmall') {
$factor = 1 / $count;
}
// CSS definition `col-3`
if (count($parts) === 2 && (int) $parts[1] > 0 && $breakpoint === 'extrasmall') {
$factor = ((int) $parts[1]) / 12;
}
// CSS definition `col-md`
if (count($parts) === 2 && $parts[1] === self::$breakpointMap[$breakpoint]) {
$factor = 1 / $count;
}
// CSS definition `col-md-3`
if (count($parts) === 3 && $parts[1] === self::$breakpointMap[$breakpoint]) {
$factor = ((int) $parts[2]) / 12;
}
}
return $factor;
}

/**
* Calculates a new multiplier based on the current one, the column css and the column count
*
* @param array $currentMultiplier
* @param string $class CSS classes used to define the column
* @param int $count Columns count in row
* @return array
*/
public static function getMultiplierForColumn(array $currentMultiplier = [], string $class = '', int $count = 1): array {
// Set initial multiplier
$multiplier = array_merge(self::$defaultMultiplier, $currentMultiplier);
$multiplier = array_intersect_key($multiplier, self::$defaultMultiplier);
// Calculate new multipliers
$items = GeneralUtility::trimExplode(' ', $class, true);
$previousFactor = 1.0;
foreach ($multiplier as $breakpoint => $value) {
$factor = self::getColumnFactorForBreakpoint($items, $count, $breakpoint);
if (false === $factor) {
// No column definition was present hence column width remains as for previous break point
$multiplier[$breakpoint] = $previousFactor * $value;
} else {
$multiplier[$breakpoint] = $factor * $value;
$previousFactor = $factor;
}
}
return $multiplier;
}
}
124 changes: 0 additions & 124 deletions Classes/ViewHelpers/GetColumnMultiplierViewHelper.php

This file was deleted.

84 changes: 84 additions & 0 deletions Classes/ViewHelpers/Render/Bootstrap/ColumnViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php


namespace Buepro\Pizpalue\ViewHelpers\Render\Bootstrap;

use Buepro\Pizpalue\Utility\StructureMultiplierUtility;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;

/**
* By using this view helper to create a div-tag defining a bootstrap column the available width within
* the column is being registered allowing to adjust the rendering. This allows images to be created with
* the size that fits the column.
*
* It is achieved by calculating a multiplier and pushing it to a stack. The latest multiplier is stored to the register
* `structureMultiplier` from where it is available to all elements rendering images (e.g. see
* `Resources\Private\Layouts\ContentElements\Default.html`).
*
* ### Example:
*
* <pp:render.bootstrap.column class="col col-md-8 col-xl-6" count="2">
* <v:content.render contentUids="{0: item.data.uid}" />
* </pp:render.bootstrap.column>
*/
class ColumnViewHelper extends AbstractTagBasedViewHelper
{
/**
* @var array
*/
private static $multiplierStack = [];

protected $tagName = 'div';

/**
* Returns last added element from $multiplierStack
*
* @return array|mixed
*/
private static function getCurrentMultiplier()
{
$currentMultiplier = [];
if (count(self::$multiplierStack)) {
$currentMultiplier = array_pop(self::$multiplierStack);
self::$multiplierStack[] = $currentMultiplier;
}
return $currentMultiplier;
}

public function initializeArguments()
{
parent::initializeArguments();
$this->registerUniversalTagAttributes();
$this->registerArgument('count', 'int', 'Column count in row',false, 1);
$this->registerArgument('tagName', 'string', 'Tag name', false, 'div');
}

public function render()
{
$this->tagName = $this->arguments['tagName'];
if ($GLOBALS['TSFE'] instanceof TypoScriptFrontendController) {
// Initialize
$currentMultiplier = self::getCurrentMultiplier();

// Get multiplier for current structure
$multiplier = StructureMultiplierUtility::getMultiplierForColumn(
$currentMultiplier,
$this->arguments['class'],
$this->arguments['count']
);

// Push multiplier -> render content -> pop multiplier
self::$multiplierStack[] = $multiplier;
$GLOBALS['TSFE']->register['structureMultiplier'] = $multiplier;
$this->tag->setContent($this->renderChildren());
$content = $this->tag->render();
array_pop(self::$multiplierStack);
$GLOBALS['TSFE']->register['structureMultiplier'] = self::getCurrentMultiplier();
return $content;
} else {
$this->tag->setContent($this->renderChildren());
return $this->tag->render();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php


namespace Buepro\Pizpalue\ViewHelpers\Structure\Multiplier;

use Buepro\Pizpalue\Utility\StructureMultiplierUtility;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;

/**
* Used to generate a multiplier array used for creating image variants.
* A start multiplier can be provided which is useful when being used in nested structures (e.g. column in column).
*
* Currently just supports css from bootstrap framework.
*
* Usage:
* {pp:structure.multiplier.getForColumn(as: 'multiplier', multiplier: multiplier, class: 'col-sm col-md-8 col-lg-10', count: 3)}
*/
class GetForColumnViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;

/**
* @return void
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('as', 'string', 'Name of variable to create.', true);
$this->registerArgument('multiplier', 'array', 'Initial multiplier', false);
$this->registerArgument('class', 'string', 'CSS classes used for defining the column', false);
$this->registerArgument('count', 'int', 'Column count in row', false);

}

/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
* @return mixed
*/
public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
) {
$multiplier = $arguments['multiplier'] ?? [];
$class = $arguments['class'] ?? '';
$count = $arguments['count'] ?? 1;
$multiplier = StructureMultiplierUtility::getMultiplierForColumn($multiplier, $class, $count);
$renderingContext->getVariableProvider()->add($arguments['as'], $multiplier);
}

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?php


namespace Buepro\Pizpalue\ViewHelpers;
namespace Buepro\Pizpalue\ViewHelpers\Structure\Multiplier;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;

/**
* Class GetImageMultiplierViewHelper
* Class GetFromTextViewHelper
*/
class GetImageMultiplierViewHelper extends AbstractViewHelper
class GetFromTextViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;

Expand Down
Loading

0 comments on commit df299b4

Please sign in to comment.