| Current Path : /home/eolienneia/www/templates/yootheme/vendor/yootheme/builder/src/Builder/ |
| Current File : /home/eolienneia/www/templates/yootheme/vendor/yootheme/builder/src/Builder/ElementTransform.php |
<?php
namespace YOOtheme\Builder;
use YOOtheme\Arr;
use YOOtheme\Builder;
use YOOtheme\View;
class ElementTransform
{
/**
* @var View
*/
protected $view;
public function __construct(View $view)
{
$this->view = $view;
}
/**
* Transform callback.
*
* @param object $node
* @param array $params
*/
public function __invoke($node, array $params)
{
$type = $params['type'];
if ($node->type === 'layout' || !($type->element || $type->container)) {
return;
}
$node->attrs += [
'id' => !empty($node->props['id']) ? $node->props['id'] : null,
'class' => !empty($node->props['class']) ? [$node->props['class']] : [],
];
$this->parallax($node);
$this->visibility($node, $params);
$this->position($node, $params);
$this->margin($node);
$this->maxWidth($node);
$this->textAlign($node);
$this->customAttributes($node);
$this->customCSS($node, $params);
if ($type->element) {
$this->animation($node, $params);
$this->containerPadding($node, $params);
}
}
/**
* @param object $node
* @param array $params
*/
public function animation($node, array $params)
{
/**
* @var Builder $builder
*/
$builder = $params['builder'];
$path = $params['path'];
if (!empty($node->props['image_svg_inline']) && !empty($node->props['image_svg_animate'])) {
$node->props['image_svg_inline'] = [
'stroke-animation: true; attributes: uk-scrollspy-class:uk-animation-stroke',
];
}
if ($builder->parent($path, 'section', 'animation')) {
$attr = 'uk-scrollspy-class';
$value = Arr::get($node->props, 'animation');
$value = in_array($value, ['none', 'parallax'])
? false
: (!empty($value)
? ['uk-animation-{0}' => $value]
: true);
} else {
if (!empty($node->props['image_svg_inline'])) {
$attr = 'uk-scrollspy';
$value = ['target: [uk-scrollspy-class];'];
}
// Reset animation if there is no section animation,
// so no look up is needed in Grid and Gallery to animate filter navigation
if (Arr::get($node->props, 'animation') !== 'parallax') {
$node->props['animation'] = 'none';
}
}
if (!empty($value) && !empty($attr)) {
foreach (!empty($node->props['item_animation']) ? $node->children : [$node] as $child) {
$child->attrs[$attr] = $value;
}
}
}
/**
* @param object $node
*/
public function parallax($node)
{
if (empty($node->props['animation']) || $node->props['animation'] !== 'parallax') {
return;
}
$node->attrs['class'][] = 'uk-position-z-index uk-position-relative {@parallax_zindex}';
$node->attrs['uk-parallax'] = array_merge($this->view->parallaxOptions($node->props), [
'easing: {parallax_easing};',
'target: !.uk-section; {@parallax_target}',
'media: @{parallax_breakpoint};',
'viewport: {parallax_viewport};',
]);
}
/**
* @param object $node
* @param array $params
*/
public function visibility($node, array $params)
{
$parent = $params['parent'];
$visibility = $this->toShowRange(
!empty($node->props['visibility']) ? $node->props['visibility'] : ''
);
$node->attrs['class']['uk-visible@{0}'] = $visibility[0];
$node->attrs['class']['uk-hidden@{0}'] = $visibility[1];
if (empty($parent)) {
return;
}
$parent->props['visibility'] = !empty($parent->props['visibility'])
? $this->mergeShowRange($visibility, $parent->props['visibility'])
: $visibility;
}
/**
* @param object $node
* @param array $params
*/
public function position($node, array $params)
{
if (empty($node->props['position'])) {
return;
}
foreach (['left', 'right', 'top', 'bottom'] as $pos) {
if (
isset($node->props["position_{$pos}"]) &&
is_numeric($node->props["position_{$pos}"])
) {
$node->props["position_{$pos}"] .= 'px';
}
}
$node->attrs['class'][] = 'uk-position-{position} [uk-width-1-1 {@position: absolute}]';
$node->attrs['style'][] = 'left: {position_left}; {@!position_right}';
$node->attrs['style'][] = 'right: {position_right}; {@!position_left}';
$node->attrs['style'][] = 'top: {position_top}; {@!position_bottom}';
$node->attrs['style'][] = 'bottom: {position_bottom}; {@!position_top}';
$node->attrs['style'][] = 'z-index: {position_z_index};';
if ($node->props['position'] == 'absolute') {
$parent = $params['parent'];
$parent->props['element_absolute'] = true;
}
}
/**
* @param object $node
*/
public function margin($node)
{
if (!empty($node->props['position']) && $node->props['position'] === 'absolute') {
return;
}
if ($node->type !== 'row') {
$node->attrs['class'][] = 'uk-margin {@margin: default}';
$node->attrs['class'][] = 'uk-margin-{!margin: |default}';
}
if (empty($node->props['margin']) || $node->props['margin'] !== 'remove-vertical') {
$node->attrs['class'][] = 'uk-margin-remove-top {@margin_remove_top}';
$node->attrs['class'][] = 'uk-margin-remove-bottom {@margin_remove_bottom}';
}
}
/**
* @param object $node
*/
public function maxWidth($node)
{
if (empty($node->props['maxwidth'])) {
return;
}
$node->attrs['class'][] = 'uk-width-{maxwidth}[@{maxwidth_breakpoint}]';
if (empty($node->props['position']) || $node->props['position'] !== 'absolute') {
// Left
$node->attrs['class'][] =
'uk-margin-auto-right{@!block_align}{@block_align_fallback}[@{block_align_breakpoint}]';
$node->attrs['class'][] =
'uk-margin-remove-left{@!block_align}{@block_align_fallback}@{block_align_breakpoint}';
// Right
$node->attrs['class'][] =
'uk-margin-auto-left{@block_align: right}[@{block_align_breakpoint}]';
$node->attrs['class'][] =
'uk-margin-remove-right{@block_align: right}{@block_align_fallback: center}@{block_align_breakpoint}';
// Center
$node->attrs['class'][] =
'uk-margin-auto{@block_align: center}[@{block_align_breakpoint}]';
// Fallback
$node->attrs['class'][] =
'uk-margin-auto-left{@block_align_fallback: right} {@block_align_breakpoint}';
$node->attrs['class'][] =
'uk-margin-auto{@block_align_fallback: center} {@block_align_breakpoint}';
}
}
/**
* @param object $node
*/
public function textAlign($node)
{
if (empty($node->props['text_align'])) {
return;
}
$node->attrs['class'][] =
$node->props['text_align'] === 'justify'
? 'uk-text-{text_align}'
: 'uk-text-{text_align}[@{text_align_breakpoint} [uk-text-{text_align_fallback}]]';
}
/**
* @param object $node
*/
public function customAttributes($node)
{
if (empty($node->props['attributes'])) {
return;
}
foreach (explode("\n", $node->props['attributes']) as $attribute) {
list($name, $value) = array_pad(explode('=', $attribute, 2), 2, '');
$name = trim($name);
if ($name && !in_array($name, ['id', 'class'])) {
$node->attrs[$name] = $value
? preg_replace('/^([\'"])(.*)(\1)/', '$2', $value)
: true;
}
}
}
/**
* @param object $node
* @param array $params
*/
public function customCSS($node, array $params)
{
if (empty($node->props['css'])) {
return;
}
if (empty($node->attrs['id'])) {
$node->attrs['id'] = $node->id;
}
// Put all comma separations in one line to prevent faulty prefixing
$css = static::prefixCSS(
"{$node->props['css']}\n",
'#' . str_replace('#', '\#', $node->attrs['id'])
);
$path = $params['path'];
$layout = end($path);
$layout->props['css'] = (!empty($layout->props['css']) ? $layout->props['css'] : '') . $css;
}
/**
* @param object $node
* @param array $params
*/
public function containerPadding($node, array $params)
{
if (
empty($node->props['container_padding_remove']) ||
(!empty($node->props['position']) && $node->props['position'] === 'absolute')
) {
return;
}
/**
* @var Builder $builder
*/
$builder = $params['builder'];
$path = $params['path'];
$parent = $params['parent'];
// Container Padding Remove
$row = $builder->parent($path, 'row');
$orderFirstColumn = Arr::find($row->children, function ($column) {
$props = (array) $column->props;
return !empty($props['order_first']);
});
$orderLastColumn = Arr::find(array_reverse($row->children), function ($column) {
$props = (array) $column->props;
return empty($props['order_first']);
});
$index = array_search($parent, $row->children);
$first = $parent === $orderFirstColumn || (!$orderFirstColumn && $index === 0);
$last =
$parent === $orderLastColumn ||
(!$orderLastColumn && $index + 1 === count($row->children));
foreach (['row', 'section'] as $type) {
if (
!in_array($builder->parent($path, $type, 'width'), [
'default',
'small',
'large',
'xlarge',
]) ||
!($dir = $builder->parent($path, $type, 'width_expand'))
) {
continue;
}
$node->attrs['class']['uk-container-item-padding-remove-left'] =
$first && $dir === 'left';
$node->attrs['class']['uk-container-item-padding-remove-right'] =
$last && $dir === 'right';
break;
}
}
/**
* Prefix CSS classes.
*
* @param string $css
* @param string $prefix
*
* @return string
*/
protected static function prefixCSS($css, $prefix = '')
{
$pattern = '/([@#:.\w[\]][\\\\@#:,>~="\'+\-^$.()\w\s[\]\*]*)({(?:[^{}]+|(?R))*})/s';
if (preg_match_all($pattern, $css, $matches, PREG_SET_ORDER)) {
$keys = [];
foreach ($matches as $match) {
list($match, $selector, $content) = $match;
if (in_array($key = sha1($match), $keys)) {
continue;
}
if ($selector[0] != '@') {
$selector = preg_replace('/(^|,)\s*/', "$0{$prefix} ", $selector);
$selector = preg_replace('/\s\.el-(element|section|column)/', '', $selector);
}
$css = str_replace($match, $selector . static::prefixCSS($content, $prefix), $css);
$keys[] = $key;
}
}
return $css;
}
/**
* Convert to show range.
*
* @param string|array $visibility
*
* @return array
*/
protected function toShowRange($visibility)
{
if (is_array($visibility)) {
return $visibility;
}
$hidden = str_starts_with($visibility, 'hidden-');
return [$hidden ? '' : $visibility, $hidden ? substr($visibility, 7) : ''];
}
/**
* Merge show ranges.
*
* @param string[] $rangeA
* @param string[] $rangeB
*
* @return string[]
*/
protected function mergeShowRange($rangeA, $rangeB)
{
$visibilities = ['s', 'm', 'l', 'xl'];
return [
$rangeA[0] && $rangeB[0] && !$rangeA[1] && !$rangeB[1]
? ($rangeA[0] !== $rangeB[0]
? $visibilities[
min(
array_search($rangeA[0], $visibilities),
array_search($rangeB[0], $visibilities)
)
]
: $rangeA[0])
: '',
$rangeA[1] && $rangeB[1] && !$rangeA[0] && !$rangeB[0]
? ($rangeA[1] !== $rangeB[1]
? $visibilities[
max(
array_search($rangeA[1], $visibilities),
array_search($rangeB[1], $visibilities)
)
]
: $rangeA[1])
: '',
];
}
}