acf
This commit is contained in:
36
plugins/system/nrframework/NRFramework/Controls/Border.php
Normal file
36
plugins/system/nrframework/NRFramework/Controls/Border.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Tassos Marinos <info@tassos.gr>
|
||||
* @link http://www.tassos.gr
|
||||
* @copyright Copyright © 2022 Tassos Marinos All Rights Reserved
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
|
||||
*/
|
||||
|
||||
namespace NRFramework\Controls;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
class Border extends Control
|
||||
{
|
||||
protected function generateCSSProperty($value, $unit)
|
||||
{
|
||||
// We require all border attributes
|
||||
if (!isset($value['width']) || !isset($value['style']) || !isset($value['color']))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the width is > 0
|
||||
if (intval($value['width']) === 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->property . ':' . implode(' ', [
|
||||
$value['width'] . $unit,
|
||||
$value['style'],
|
||||
$value['color']
|
||||
]) . ';';
|
||||
}
|
||||
}
|
||||
367
plugins/system/nrframework/NRFramework/Controls/Control.php
Normal file
367
plugins/system/nrframework/NRFramework/Controls/Control.php
Normal file
@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Tassos Marinos <info@tassos.gr>
|
||||
* @link http://www.tassos.gr
|
||||
* @copyright Copyright © 2022 Tassos Marinos All Rights Reserved
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
|
||||
*/
|
||||
|
||||
namespace NRFramework\Controls;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
class Control
|
||||
{
|
||||
/**
|
||||
* The CSS selector related to this control.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
/**
|
||||
* The CSS property related to this control.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $property;
|
||||
|
||||
/**
|
||||
* The CSS property used when there are conditions and we fail to use the property, so we override it using this property.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $fallback_property;
|
||||
|
||||
/**
|
||||
* The CSS property used when there are no conditions and we fail to use the property, so we override it using this value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $fallback_value;
|
||||
|
||||
/**
|
||||
* Some controls may render CSS conditionally, based on the given value.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $values;
|
||||
|
||||
/**
|
||||
* The control value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* The raw control value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value_raw;
|
||||
|
||||
/**
|
||||
* The control value unit.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $unit;
|
||||
|
||||
/**
|
||||
* Exclude specific breakpoints from the control's CSS.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $exclude_breakpoints = [];
|
||||
|
||||
/**
|
||||
* The existing controls we have parsed so far.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $parsedControls = [];
|
||||
|
||||
/**
|
||||
* A control may require some conditions to be set.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $conditions = [];
|
||||
|
||||
/**
|
||||
* Whether to ignore "inherit" values.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $skip_inherit_value = false;
|
||||
|
||||
/**
|
||||
* The current breakpoint we are checking against to set CSS.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $current_breakpoint = 'desktop';
|
||||
|
||||
public function __construct($payload = [])
|
||||
{
|
||||
$this->parsedControls = isset($payload['parsedControls']) ? $payload['parsedControls'] : null;
|
||||
$this->selector = isset($payload['selector']) ? $payload['selector'] : null;
|
||||
$this->conditions = isset($payload['conditions']) ? $payload['conditions'] : [];
|
||||
$this->property = isset($payload['property']) ? $payload['property'] : null;
|
||||
$this->skip_inherit_value = isset($payload['skip_inherit_value']) ? $payload['skip_inherit_value'] : $this->skip_inherit_value;
|
||||
// The fallback_property is used when we have conditions and we don't have a value, so we override it using this property.
|
||||
$this->fallback_property = isset($payload['fallback_property']) ? $payload['fallback_property'] : null;
|
||||
// The fallback_value is used when we don't have conditions and we don't have a value, so we override it using this value.
|
||||
$this->fallback_value = isset($payload['fallback_value']) ? $payload['fallback_value'] : null;
|
||||
$this->values = isset($payload['values']) ? $payload['values'] : [];
|
||||
$this->exclude_breakpoints = isset($payload['exclude_breakpoints']) ? $payload['exclude_breakpoints'] : null;
|
||||
$this->value = isset($payload['value']['value']) ? $payload['value']['value'] : (isset($payload['value']) ? $payload['value'] : null);
|
||||
$this->value_raw = isset($payload['value']['value']) ? $payload['value']['value'] : (isset($payload['value']) ? $payload['value'] : null);
|
||||
$this->unit = isset($payload['value']['unit']) ? $payload['value']['unit'] : (isset($payload['unit']) ? $payload['unit'] : null);
|
||||
|
||||
if (isset($this->value['unit']))
|
||||
{
|
||||
unset($this->value['unit']);
|
||||
}
|
||||
}
|
||||
|
||||
public function getCSS()
|
||||
{
|
||||
if (!$this->isResponsive())
|
||||
{
|
||||
$this->value = $this->generateCSSProperty($this->value, $this->unit);
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
// Prepare value for arrays
|
||||
foreach ($this->value as $breakpoint => &$value)
|
||||
{
|
||||
$this->current_breakpoint = $breakpoint;
|
||||
|
||||
// If this breakpoint is excluded, skip
|
||||
if (is_array($this->exclude_breakpoints) && count($this->exclude_breakpoints) && in_array($breakpoint, $this->exclude_breakpoints))
|
||||
{
|
||||
unset($this->value[$breakpoint]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_scalar($value))
|
||||
{
|
||||
$value = $this->generateCSSProperty($value, $this->unit);
|
||||
}
|
||||
else
|
||||
{
|
||||
$unit = isset($value['unit']) ? $value['unit'] : $this->unit;
|
||||
|
||||
// Remove "unit" property
|
||||
if ($unit)
|
||||
{
|
||||
unset($value['unit']);
|
||||
}
|
||||
|
||||
// Remove "linked" property
|
||||
if (isset($value['linked']))
|
||||
{
|
||||
unset($value['linked']);
|
||||
}
|
||||
|
||||
$value = isset($value['value']) ? $value['value'] : $value;
|
||||
|
||||
// Remove responsive value if no actual value is set
|
||||
if (!$value && $value != '0' && $unit != 'auto')
|
||||
{
|
||||
unset($this->value[$breakpoint]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $this->generateCSSProperty($value, $unit);
|
||||
}
|
||||
|
||||
if (is_null($value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
protected function generateCSSProperty($value, $unit)
|
||||
{
|
||||
if ($this->shouldSkipPropertyGeneration($value, $unit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$conditions_pass = $this->conditionsPass($value);
|
||||
|
||||
$conditionsNotMet = (!$conditions_pass && !$this->fallback_property);
|
||||
$emptyValueWithUnitNotAuto = ($value === '' || is_null($value)) && !$this->fallback_property && $unit !== 'auto';
|
||||
|
||||
if ($conditionsNotMet || $emptyValueWithUnitNotAuto)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->values)
|
||||
{
|
||||
return $this->generateValueCSS($value);
|
||||
}
|
||||
|
||||
$properties = $this->conditions && !$conditions_pass && $this->fallback_property ? $this->fallback_property : $this->property;
|
||||
|
||||
// If we have no conditions and no value, but we have a fallback value, use it.
|
||||
if (!$this->conditions && !$value && $this->fallback_value)
|
||||
{
|
||||
$properties = $this->fallback_value;
|
||||
}
|
||||
|
||||
|
||||
if (is_array($properties))
|
||||
{
|
||||
return $this->generateArrayPropertyCSS($properties, $conditions_pass, $value, $unit);
|
||||
}
|
||||
|
||||
if ($value === 'inherit' && $this->skip_inherit_value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->generateSinglePropertyCSS($value, $unit);
|
||||
}
|
||||
|
||||
private function shouldSkipPropertyGeneration($value, $unit)
|
||||
{
|
||||
return !$value && $value != '0' && $unit != 'auto' && !$this->fallback_property;
|
||||
}
|
||||
|
||||
private function generateValueCSS($value)
|
||||
{
|
||||
$css = '';
|
||||
|
||||
$value = explode(' ', $value);
|
||||
|
||||
foreach ($this->values as $key => $css_value)
|
||||
{
|
||||
if (!in_array($key, $value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$css .= implode('', $css_value);
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
private function generateArrayPropertyCSS($properties, $conditions_pass, $value, $unit)
|
||||
{
|
||||
$css = '';
|
||||
|
||||
// If the conditions did pass and we do not have a value, do not set any CSS.
|
||||
if ($conditions_pass && !$value && $unit !== 'auto')
|
||||
{
|
||||
return $css;
|
||||
}
|
||||
|
||||
foreach ($properties as $prop_key => $prop_value)
|
||||
{
|
||||
$css_line = $prop_key . ':' . str_replace('%value%', $value . $unit, $prop_value) . ';';
|
||||
$css_line = str_replace('%value_raw%', $value , $css_line);
|
||||
|
||||
$css .= $css_line;
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
private function generateSinglePropertyCSS($value, $unit)
|
||||
{
|
||||
$value = \NRFramework\Helpers\Controls\Control::findUnitInValue($value);
|
||||
$val = isset($value['value']) ? $value['value'] : $value;
|
||||
$unit = isset($value['unit']) && $value['unit'] ? $value['unit'] : $unit;
|
||||
|
||||
return $this->getProperty() . ':' . $val . $unit . ';';
|
||||
}
|
||||
|
||||
private function conditionsPass(&$value)
|
||||
{
|
||||
if (!$this->conditions)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->conditions as $conditionItem)
|
||||
{
|
||||
if (!$this->checkCondition($conditionItem, $value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkCondition($conditionItem, &$value)
|
||||
{
|
||||
$foundCondition = array_search($conditionItem['property'], array_column($this->parsedControls, 'property'));
|
||||
|
||||
if ($foundCondition === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$foundConditionControl = isset($this->parsedControls[$foundCondition]) ? $this->parsedControls[$foundCondition] : false;
|
||||
|
||||
if (!$foundConditionControl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$conditionValue = $conditionItem['property'] . ':' . $conditionItem['value'] . ';';
|
||||
$foundConditionControlValues = $foundConditionControl['control']->getValue();
|
||||
$breakpointValue = is_array($foundConditionControlValues) ? ($foundConditionControlValues[$this->current_breakpoint] ?? null) : $foundConditionControlValues;
|
||||
|
||||
if (\NRFramework\Functions::endsWith($breakpointValue, ':inherit;'))
|
||||
{
|
||||
$prevBreakpoint = $this->current_breakpoint === 'tablet' ? 'desktop' : 'tablet';
|
||||
$breakpointValue = is_array($foundConditionControlValues) ? ($foundConditionControlValues[$prevBreakpoint] ?? null) : $foundConditionControlValues;
|
||||
|
||||
// Also update the value
|
||||
$value = isset($this->value_raw[$prevBreakpoint]['value']) || isset($this->value_raw[$prevBreakpoint]) ? '' : $value;
|
||||
|
||||
if (\NRFramework\Functions::endsWith($breakpointValue, ':inherit;') && $this->current_breakpoint === 'mobile' && $prevBreakpoint === 'tablet')
|
||||
{
|
||||
$breakpointValue = is_array($foundConditionControlValues) ? ($foundConditionControlValues['desktop'] ?? null) : $foundConditionControlValues;
|
||||
|
||||
// Also update the value
|
||||
$value = isset($this->value_raw['desktop']['value']) || isset($this->value_raw['desktop']) ? '' : $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $conditionValue === $breakpointValue;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function getSelector()
|
||||
{
|
||||
return $this->selector;
|
||||
}
|
||||
|
||||
public function getProperty()
|
||||
{
|
||||
return $this->property;
|
||||
}
|
||||
|
||||
public function isResponsive()
|
||||
{
|
||||
$keys = ['desktop', 'tablet', 'mobile'];
|
||||
return is_array($this->value) && !empty(array_intersect_key(array_flip($keys), $this->value));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Tassos Marinos <info@tassos.gr>
|
||||
* @link http://www.tassos.gr
|
||||
* @copyright Copyright © 2022 Tassos Marinos All Rights Reserved
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
|
||||
*/
|
||||
|
||||
namespace NRFramework\Controls;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
class ControlFactory
|
||||
{
|
||||
public function createControl($value = [])
|
||||
{
|
||||
if (!isset($value['value']))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$type = isset($value['type']) ? $value['type'] : 'Control';
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 'Control':
|
||||
return new \NRFramework\Controls\Control($value);
|
||||
break;
|
||||
case 'Border':
|
||||
return new \NRFramework\Controls\Border($value);
|
||||
break;
|
||||
case 'Spacing':
|
||||
return new \NRFramework\Controls\Spacing($value);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
134
plugins/system/nrframework/NRFramework/Controls/Controls.php
Normal file
134
plugins/system/nrframework/NRFramework/Controls/Controls.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Tassos Marinos <info@tassos.gr>
|
||||
* @link http://www.tassos.gr
|
||||
* @copyright Copyright © 2022 Tassos Marinos All Rights Reserved
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
|
||||
*/
|
||||
|
||||
namespace NRFramework\Controls;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
class Controls
|
||||
{
|
||||
/**
|
||||
* The Control Factory.
|
||||
*
|
||||
* @var ControlFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The main selector that will be used for all controls generated CSS.
|
||||
*
|
||||
* Each control can override this by setting the "selector" property.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
/**
|
||||
* Define which breakpoints to exclude from the CSS generation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $exclude_breakpoints = [];
|
||||
|
||||
public function __construct($factory = null, $selector = null, $exclude_breakpoints = [])
|
||||
{
|
||||
if (!$factory)
|
||||
{
|
||||
$factory = new ControlFactory();
|
||||
}
|
||||
$this->factory = $factory;
|
||||
|
||||
$this->selector = $selector;
|
||||
$this->exclude_breakpoints = $exclude_breakpoints;
|
||||
}
|
||||
|
||||
public function generateCSS($controls = [])
|
||||
{
|
||||
$cssArray = $this->getCSSArray($controls);
|
||||
|
||||
// Get the final CSS
|
||||
return \NRFramework\Helpers\Controls\CSS::generateCSS($cssArray);
|
||||
}
|
||||
|
||||
protected function getCSSArray($controls = [])
|
||||
{
|
||||
if (!$controls || !is_array($controls))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$parsedControls = [];
|
||||
|
||||
$cssArray = [
|
||||
'desktop' => [],
|
||||
'tablet' => [],
|
||||
'mobile' => []
|
||||
];
|
||||
|
||||
// Get the responsive CSS for each control
|
||||
foreach ($controls as $control_payload)
|
||||
{
|
||||
// Set any breakpoints to exclude when generating CSS
|
||||
$control_payload['exclude_breakpoints'] = $this->exclude_breakpoints;
|
||||
|
||||
// Set the selector
|
||||
if (!isset($control_payload['selector']))
|
||||
{
|
||||
$control_payload['selector'] = $this->selector;
|
||||
}
|
||||
|
||||
$control_payload['parsedControls'] = $parsedControls;
|
||||
|
||||
if (!$control = $this->factory->createControl($control_payload))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$control_css = $control->getCSS())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$selector = $control->getSelector();
|
||||
|
||||
if (isset($control_payload['property']))
|
||||
{
|
||||
$parsedControls[] = [
|
||||
'property' => $control_payload['property'],
|
||||
'control' => $control
|
||||
];
|
||||
}
|
||||
|
||||
if ($control->isResponsive())
|
||||
{
|
||||
foreach ($control_css as $breakpoint => $control_payload)
|
||||
{
|
||||
if (is_null($control_payload))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$cssArray[$breakpoint][] = [
|
||||
'selector' => $selector,
|
||||
'css' => $control_payload
|
||||
];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$cssArray['desktop'][] = [
|
||||
'selector' => $selector,
|
||||
'css' => $control_css
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $cssArray;
|
||||
}
|
||||
}
|
||||
27
plugins/system/nrframework/NRFramework/Controls/Spacing.php
Normal file
27
plugins/system/nrframework/NRFramework/Controls/Spacing.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Tassos Marinos <info@tassos.gr>
|
||||
* @link http://www.tassos.gr
|
||||
* @copyright Copyright © 2022 Tassos Marinos All Rights Reserved
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
|
||||
*/
|
||||
|
||||
namespace NRFramework\Controls;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
class Spacing extends Control
|
||||
{
|
||||
protected function generateCSSProperty($value, $unit)
|
||||
{
|
||||
$value = \NRFramework\Helpers\Controls\Control::getCSSValue($value, $unit);
|
||||
|
||||
if ((is_null($value) || $value === '') && $value != '0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->property . ':' . $value . ';';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user