| Current Path : /var/www/components/com_sppagebuilder/helpers/ |
| Current File : /var/www/components/com_sppagebuilder/helpers/helper.php |
<?php
/**
* @package SP Page Builder
* @author JoomShaper http://www.joomshaper.com
* @copyright Copyright (c) 2010 - 2025 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/
//no direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
require_once JPATH_ROOT . '/components/com_sppagebuilder/builder/classes/base.php';
class SppagebuilderHelperSite
{
/**
* Addon structures
*
* @var array
*/
private static $addonFieldStructures = [];
/**
* Column settings structure
*
* @var array
*/
private static $columnFieldStructures = [];
/**
* Section/row settings structure
*
* @var array
*/
private static $sectionFieldStructures = [];
/**
* Section field types
*
* @var array
*/
private static $sectionFieldTypes = [];
/**
* Column field types
*
* @var array
*/
private static $columnFieldTypes = [];
/**
* The fields types
*
* @var array
*/
private static $addonFieldTypes = [];
/**
* Check if the data come from the version 3 or bellow.
*
* @var boolean
*/
private static $isLegacyData = false;
private static function getAddonGlobalFieldStructures()
{
$structures = [];
$globalSettings = SpPgaeBuilderBase::addonOptions();
foreach ($globalSettings as $setting) {
$structures = array_merge($structures, $setting);
}
return $structures;
}
/**
* Load the addon structure from the admin.php files.
*
* @return void
*/
private static function prepareAddonFieldStructures()
{
self::loadLanguage();
SpPgaeBuilderBase::loadAddons();
$addons = SpAddonsConfig::$addons;
$globalStructures = self::getAddonGlobalFieldStructures();
foreach ($addons as &$addon) {
$addon = AddonsHelper::modernizeAddonStructure($addon);
$addon['addon_name'] = preg_replace('/^sp_/i', '', $addon['addon_name']);
$addon['settings'] = array_merge($addon['settings'], $globalStructures);
}
unset($addon);
self::$addonFieldStructures = $addons;
}
private static function prepareSectionFieldStructures()
{
$sectionSettings = SpPgaeBuilderBase::getRowGlobalSettings();
foreach ($sectionSettings as $setting) {
self::$sectionFieldStructures = array_merge(self::$sectionFieldStructures, $setting);
}
}
private static function prepareColumnFieldStructures()
{
$columnSettings = SpPgaeBuilderBase::getColumnGlobalSettings();
foreach ($columnSettings as $setting) {
self::$columnFieldStructures = array_merge(self::$columnFieldStructures, $setting);
}
}
/**
* Predict the column's fill style if it is fit in a single line
* or multiple line.
*
* @param array $columns The columns array.
*
* @return stdClass The fit value after prediction.
* @since 4.0.0
*/
private static function predictColumnFillStyle(array $columns): stdClass
{
$fitObject = (object) ['xl' => false, 'lg' => false, 'md' => false, 'sm' => false, 'xs' => false];
foreach (['xl', 'lg', 'md', 'sm', 'xs'] as $key) {
$total = 0;
foreach ($columns as $column) {
$width = self::getColumnWidth($column);
$total += (float) $width->$key;
}
if ($total <= 100) {
$fitObject->$key = true;
}
}
return $fitObject;
}
/**
* Generate the column widths from the columns class_name property.
*
* @param stdClass $column The column object.
*
* @return stdClass The generated width object for multiple device.
* @since 4.0.0
*/
public static function getColumnWidth(stdClass $column): stdClass
{
$width = (object) ['xl' => '100%', 'lg' => '100%', 'md' => '100%', 'sm' => '100%', 'xs' => '100%'];
$size = (int) \substr($column->class_name, 7);
$value = self::calculateColumnPercent($size);
$width->xl = $value;
if (!empty($column->class_name) && empty($column->settings->sm_col)) {
$width->lg = $value;
}
if (!empty($column->settings->sm_col)) {
$smSize = (int) \substr($column->settings->sm_col, 7);
$width->lg = self::calculateColumnPercent($smSize);
$width->md = self::calculateColumnPercent($smSize);
}
if (!empty($column->settings->xs_col)) {
$xsSize = (int) \substr($column->settings->xs_col, 7);
$width->sm = self::calculateColumnPercent($xsSize);
$width->xs = self::calculateColumnPercent($xsSize);
}
return $width;
}
private static function isValidWidthValue($width)
{
return preg_match("@^\d+(\.\d+)?%$@", $width);
}
public static function purifyColumnWidth($width)
{
$defaultDevice = SpPgaeBuilderBase::$defaultDevice;
$smallDevices = ['sm', 'xs'];
if (\is_object($width)) {
$deviceData = $width->$defaultDevice;
foreach ($width as $device => $value) {
if (!self::isValidWidthValue($value)) {
if (\in_array($device, $smallDevices)) {
$width->$device = '100%';
} else {
$width->$device = !empty($deviceData) ? $deviceData : '100%';
}
}
}
}
return $width;
}
/**
* Calculate the column percentage from the column size.
*
* @param int $size The size value ranged from 1 to 12.
*
* @return string The percentage value w.r.t the the size.
* @since 4.0.0
*/
private static function calculateColumnPercent(int $size): string
{
return ((100 / 12) * (int) $size) . '%';
}
// Generate unique id
public static function nanoid(int $size = 21): string
{
$urlAlphabet = "ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW";
$id = "";
$i = $size;
while ($i--) {
$id .= $urlAlphabet[rand(0, 63) | 0];
}
return $id;
}
// Generate unique id
public static function numberNanoid(int $size = 21): string
{
$urlAlphabet = "0123456789";
$id = "";
$i = $size;
while ($i--) {
$id .= $urlAlphabet[rand(0, 9) | 0];
}
return intval($id);
}
private static function parseRow(array &$rows, \stdClass &$row)
{
if (isset($row->settings)) {
$row->settings = self::shiftResponsiveSettings($row->settings);
}
if (!empty($row->columns)) {
if (!isset($row->settings->fit_columns)) {
$row->settings->fit_columns = self::predictColumnFillStyle($row->columns);
}
foreach ($row->columns as $i => &$column) {
/** Predict the width from the column class name for the old layouts. */
if (!isset($column->width)) {
$width = self::getColumnWidth($column);
$column->width = $width;
}
if (\is_array($column->settings)) {
$column->settings = (object) $column->settings;
}
if (!isset($column->settings->width)) {
$width = !empty($column->width) ? $column->width : self::getColumnWidth($column);
$column->settings->width = $width;
if (isset($column->settings->width->unit)) {
unset($column->settings->width->unit);
}
}
$column->settings->width = self::purifyColumnWidth($column->settings->width);
if (isset($column->settings)) {
$column
->settings = self::shiftResponsiveSettings($column->settings);
}
if (!empty($column->addons)) {
foreach ($column->addons as $j => &$addon) {
if (isset($addon->settings)) {
$addon->settings = self::shiftResponsiveSettings($addon->settings);
}
// migrate image layouts addon
if (isset($addon->name) && $addon->name === 'image_layouts') {
$addonSettings = $addon->settings;
$isBtnUrlExist = property_exists($addonSettings, 'btn_url');
$isButtonUrlExist = property_exists($addonSettings, 'button_url');
$isBtnTargetExist = property_exists($addonSettings, 'btn_target');
if (!$isButtonUrlExist && $isBtnUrlExist) {
$addonSettings->button_url = [
'type' => 'url',
'url' => $addonSettings->btn_url,
'new_tab' => $isBtnTargetExist ? $addonSettings->btn_target : false,
];
}
$isBtnTextExist = property_exists($addonSettings, 'btn_text');
$isButtonTextExist = property_exists($addonSettings, 'button_text');
if (!$isButtonTextExist && $isBtnTextExist) {
$addonSettings->button_text = $addonSettings->btn_text;
}
$isBtnTypeExist = property_exists($addonSettings, 'btn_type');
$isButtonTypeExist = property_exists($addonSettings, 'button_type');
if (!$isButtonTypeExist && $isBtnTypeExist) {
$addonSettings->button_type = $addonSettings->btn_type;
}
$isBtnShapeExist = property_exists($addonSettings, 'btn_shape');
$isButtonShapeExist = property_exists($addonSettings, 'button_shape');
if (!$isButtonShapeExist && $isBtnShapeExist) {
$addonSettings->button_shape = $addonSettings->btn_shape;
}
$isBtnSizeExist = property_exists($addonSettings, 'btn_size');
$isButtonSizeExist = property_exists($addonSettings, 'button_size');
if (!$isButtonSizeExist && $isBtnSizeExist) {
$addonSettings->button_size = $addonSettings->btn_size;
}
$isBtnColorExist = property_exists($addonSettings, 'btn_color');
$isButtonColorExist = property_exists($addonSettings, 'button_color');
if (!$isButtonColorExist && $isBtnColorExist) {
$addonSettings->button_color = $addonSettings->btn_color;
}
$isBtnColorHoverExist = property_exists($addonSettings, 'btn_color_hover');
$isButtonColorHoverExist = property_exists($addonSettings, 'button_color_hover');
if (!$isButtonColorHoverExist && $isBtnColorHoverExist) {
$addonSettings->button_color_hover = $addonSettings->btn_color_hover;
}
$isBtnAppearanceExist = property_exists($addonSettings, 'btn_appearance');
$isButtonAppearanceExist = property_exists($addonSettings, 'button_appearance');
if (!$isButtonAppearanceExist && $isBtnAppearanceExist) {
$addonSettings->button_appearance = $addonSettings->btn_appearance;
}
$isBtnBackgroundColorExist = property_exists($addonSettings, 'btn_background_color');
$isButtonBackgroundColorExist = property_exists($addonSettings, 'button_background_color');
if (!$isButtonBackgroundColorExist && $isBtnBackgroundColorExist) {
$addonSettings->button_background_color = $addonSettings->btn_background_color;
}
$isBtnBackgroundColorHoverExist = property_exists($addonSettings, 'btn_background_color_hover');
$isButtonBackgroundColorHoverExist = property_exists($addonSettings, 'button_background_color_hover');
if (!$isButtonBackgroundColorHoverExist && $isBtnBackgroundColorHoverExist) {
$addonSettings->button_background_color_hover = $addonSettings->btn_background_color_hover;
}
$isBtnBackgroundGradientExist = property_exists($addonSettings, 'btn_background_gradient');
$isButtonBackgroundGradientExist = property_exists($addonSettings, 'button_background_gradient');
if (!$isButtonBackgroundGradientExist && $isBtnBackgroundGradientExist) {
$addonSettings->button_background_gradient = $addonSettings->btn_background_gradient;
}
$isBtnBackgroundGradientHoverExist = property_exists($addonSettings, 'btn_background_gradient_hover');
$isButtonBackgroundGradientHoverExist = property_exists($addonSettings, 'button_background_gradient_hover');
if (!$isButtonBackgroundGradientHoverExist && $isBtnBackgroundGradientHoverExist) {
$addonSettings->button_background_gradient_hover = $addonSettings->btn_background_gradient_hover;
}
}
/** Migrate the slideshow items. */
if (isset($addon->name) && $addon->name === 'js_slideshow') {
if (!empty($addon->settings->slideshow_items)) {
foreach ($addon->settings->slideshow_items as $x => &$slideshowItem) {
if (isset($slideshowItem->slider_overlay_options) && $slideshowItem->slider_overlay_options === 'gradient_overaly') {
$slideshowItem->slider_overlay_options = 'gradient_overlay';
}
if (isset($slideshowItem->slider_bg_gradient_overlay) && !isset($slideshowItem->slider_bg_gradient_overlay->type)) {
$slideshowItem->slider_bg_gradient_overlay->type = 'linear';
}
$slideshowItem = self::shiftResponsiveSettings($slideshowItem);
if (!empty($slideshowItem->slideshow_inner_items)) {
foreach ($slideshowItem->slideshow_inner_items as $y => &$innerItem) {
$innerItem = self::shiftResponsiveSettings($innerItem);
}
unset($innerItem);
}
}
unset($slideshowItem);
}
}
/** Migrate the responsive settings for the repeatable items. */
if (isset($addon->name) && \in_array($addon->name, ['accordion', 'tab'])) {
$repeatableKey = 'sp_' . $addon->name . '_item';
if (!empty($addon->settings->$repeatableKey)) {
foreach ($addon->settings->$repeatableKey as &$itemSetting) {
$itemSetting = self::shiftResponsiveSettings($itemSetting);
}
unset($itemSetting);
}
}
if (isset($addon->name) && \in_array($addon->name, ['accordion', 'tab'])) {
list($outerRows, $_addon) = self::migrateDeepAddon($addon, 'sp_' . $addon->name . '_item', $row, $column);
$addon = $_addon;
array_push($rows, ...$outerRows);
}
if (isset($addon->name) && $addon->name === 'table_advanced') {
$nodeId = self::generateUUID();
if (isset($addon->settings->sp_table_advanced_item)) {
foreach ($addon->settings->sp_table_advanced_item as $th => $thead) {
if (isset($thead->content) && !\is_array($thead->content)) {
$thead = ['id' => $nodeId++, 'name' => 'text_block', 'visibility' => true, 'reference_id' => $addon->id, 'settings' => ['text' => $thead->content]];
$thead = \json_decode(\json_encode($thead));
$addon
->settings
->sp_table_advanced_item[$th]
->content = [];
$addon
->settings
->sp_table_advanced_item[$th]
->content[] = $thead;
} elseif (isset($thead->content) && \is_array($thead->content)) {
$contents = [];
foreach ($thead->content as $content) {
$content->reference_id = $addon->id;
$contents[] = $content;
}
$addon
->settings
->sp_table_advanced_item[$th]
->content = $contents;
}
}
}
foreach ($addon->settings->table_advanced_item as $r => $tRow) {
if (isset($tRow->table_advanced_item)) {
foreach ($tRow->table_advanced_item as $c => $tCell) {
if (isset($tCell->content) && !\is_array($tCell->content)) {
$td = ['id' => $nodeId++, 'name' => 'text_block', 'visibility' => true, 'reference_id' => $addon->id, 'settings' => ['text' => $tCell->content]];
$td = \json_decode(\json_encode($td));
$addon
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content = [];
$addon
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content[] = $td;
} elseif (isset($tCell->content) && \is_array($tCell->content)) {
$contents = [];
foreach ($tCell->content as &$content) {
$content->reference_id = $addon->id;
$contents[] = $content;
}
$addon
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content = $contents;
unset($content);
}
}
}
}
}
if (isset($addon->type) && $addon->type === 'inner_row') {
$addon->id = self::nanoid();
$nestedRowAddon = new \stdClass;
$nestedRowAddon->type = 'nested_row';
$nestedRowAddon->name = 'row';
$nestedRowAddon->id = $addon->id;
$addon->parent = new \stdClass;
$addon->parent->rowId = $row->id;
$addon->parent->columnId = $column->id;
$rows[] = $addon;
$addon = $nestedRowAddon;
}
}
unset($addon);
}
}
unset($column);
}
}
/**
* sanitize import json for making the old data valid for the data structure.
*
* @param string $text The json text of the page builder data.
*
* @return string The sanitized text.
*
* @since 4.0.0
*/
public static function sanitizeImportJSON(string $text): string
{
$rows = json_decode($text);
if (is_string($rows)) {
$rows = json_decode($rows);
}
if (!empty($rows)) {
foreach ($rows as $key => &$row) {
self::parseRow($rows, $row);
}
unset($row);
} else {
return $text;
}
return json_encode($rows);
}
private static $defaultValueWithUnit = ['value' => '', 'unit' => 'px'];
private static function getDefaultTypographyData()
{
$deviceData = [
'xl' => self::$defaultValueWithUnit,
'lg' => self::$defaultValueWithUnit,
'md' => self::$defaultValueWithUnit,
'sm' => self::$defaultValueWithUnit,
'xs' => self::$defaultValueWithUnit,
];
return (object) [
'font' => '',
'size' => $deviceData,
'line_height' => $deviceData,
'letter_spacing' => $deviceData,
'uppercase' => false,
'italic' => false,
'underline' => false,
'weight' => '',
'type' => 'google',
];
}
private static function isUnitValue($data)
{
return isset($data->value) && isset($data->unit);
}
private static function handleDeviceValues($data, $fieldKey)
{
$deviceData = [
'xl' => self::$defaultValueWithUnit,
'lg' => self::$defaultValueWithUnit,
'md' => self::$defaultValueWithUnit,
'sm' => self::$defaultValueWithUnit,
'xs' => self::$defaultValueWithUnit,
];
$responsiveKeys = ['size', 'line_height', 'letter_spacing'];
$pattern = "@px|rem|em|%@i";
if (in_array($fieldKey, $responsiveKeys)) {
if (\is_object($data)) {
$finalValue = self::$defaultValueWithUnit;
foreach ($data as $device => $value) {
if (self::isUnitValue($value)) {
$finalValue = (array) $value;
$finalValue['value'] = preg_match($pattern, $finalValue['value']) ? (float) $finalValue['value'] : $finalValue['value'];
$finalValue['value'] = (string) $finalValue['value'];
} else {
$finalValue['value'] = $value ?? '';
$finalValue['value'] = preg_match($pattern, $finalValue['value']) ? (float) $finalValue['value'] : $finalValue['value'];
$finalValue['value'] = (string) $finalValue['value'];
}
$deviceData[$device] = $finalValue;
}
} else {
$deviceData['xl']['value'] = preg_match($pattern, $data) ? (float) $data : $data;
$deviceData['xl']['value'] = (string) $deviceData['xl']['value'];
}
if (!empty($deviceData['md']['value']) && empty($deviceData['xl']['value'])) {
$deviceData['xl'] = $deviceData['md'];
}
return (object) $deviceData;
}
return $data;
}
private static function getFieldsWithFallbacks($settings)
{
$fieldArray = [];
if (empty($settings)) {
return $fieldArray;
}
foreach ($settings as $setting) {
if (!empty($setting['fields'])) {
foreach ($setting['fields'] as $fieldName => &$field) {
if (isset($field['type']) && $field['type'] === 'repeatable' && !empty($field['attr'])) {
$field['attr'] = self::getFieldsWithFallbacks($field['attr'] ?? []);
if (!empty($field['attr'])) {
$fieldArray[$fieldName] = $field;
}
}
if (!empty($field['fallbacks'])) {
$fieldArray[$fieldName] = $field;
}
}
unset($field);
}
}
return $fieldArray;
}
private static function getFieldStructureForTypography()
{
$fallbackFields = [];
foreach (self::$addonFieldStructures as &$addon) {
$addonName = $addon['addon_name'];
$fallbackFields[$addonName] = self::getFieldsWithFallbacks($addon['settings'] ?? []);
}
unset($addon);
return $fallbackFields;
}
private static function retrieveFieldTypesFromSettings($settings)
{
$types = [];
foreach ($settings as $group) {
if (!empty($group['fields'])) {
foreach ($group['fields'] as $key => $field) {
$fieldtype = $field['type'] ?? '';
if ($fieldtype === 'repeatable') {
$types[$key] = [
'type' => 'repeatable',
'fields' => self::retrieveFieldTypesFromSettings($field['attr']),
];
} else {
$types[$key] = $fieldtype;
}
}
}
}
return $types;
}
private static function processFieldTypes($type)
{
switch ($type) {
case 'section':
self::$sectionFieldTypes = self::retrieveFieldTypesFromSettings(self::$sectionFieldStructures);
break;
case 'column':
self::$columnFieldTypes = self::retrieveFieldTypesFromSettings(self::$columnFieldStructures);
break;
case 'addon':
foreach (self::$addonFieldStructures as $addon) {
$addonName = $addon['addon_name'];
$addonFieldTypes[$addonName] = self::retrieveFieldTypesFromSettings($addon['settings']);
}
self::$addonFieldTypes = $addonFieldTypes;
break;
}
}
private static function parseResponsiveTypography($data)
{
if (!is_object($data)) {
return $data;
}
$keys = ['letter_spacing', 'size', 'line_height'];
foreach ($keys as $key) {
$typographyItem = $data->$key ?? null;
if (!$typographyItem) {
continue;
}
if (!empty($typographyItem->md->value) && empty($typographyItem->xl->value)) {
$data->$key->xl = clone $typographyItem->md;
}
}
return $data;
}
private static function getFallbackValues($settings, string $fieldName, $field)
{
$fallbacks = $field['fallbacks'] ?? [];
if (!isset($settings->$fieldName)) {
$settings->$fieldName = new stdClass;
$isTypographyField = isset($field['type']) && $field['type'] === 'typography';
if ($isTypographyField) {
$settings->$fieldName = self::getDefaultTypographyData();
}
foreach ($fallbacks as $fieldKey => $referenceKey) {
$fallbackParts = explode('.', $referenceKey, 2);
$masterKey = $fallbackParts[0] ?? null;
$slaveKey = $fallbackParts[1] ?? null;
if (!empty($masterKey) && !empty($slaveKey)) {
$fallbackValue = isset($settings->$masterKey->$slaveKey) ? $settings->$masterKey->$slaveKey : '';
} elseif (!empty($masterKey) && empty($slaveKey)) {
$fallbackValue = isset($settings->$masterKey) ? $settings->$masterKey : '';
}
if ($isTypographyField) {
$settings->$fieldName->$fieldKey = self::handleDeviceValues($fallbackValue, $fieldKey);
} else {
$settings->$fieldName->$fieldKey = $fallbackValue;
}
}
} else {
$settings->$fieldName = self::parseResponsiveTypography($settings->$fieldName);
}
return $settings;
}
/**
* Read the fallback values of the typography fields.
*
* @param stdClass $settings
* @param string $addonName
*
* @return stdClass The modified settings value.
* @since 5.0.0
*/
private static function getTypographyFromFallbacks($settings, $addonName)
{
$fieldStructures = self::getFieldStructureForTypography();
$fieldStructureByAddon = $fieldStructures[$addonName] ?? null;
if (empty($fieldStructureByAddon)) {
return $settings;
}
foreach ($settings as $key => &$setting) {
$field = !empty($fieldStructureByAddon[$key]) ? $fieldStructureByAddon[$key] : [];
if (!empty($field['type']) && $field['type'] === 'repeatable' && !empty($field['attr'])) {
$attributes = $field['attr'];
foreach ($attributes as $fieldName => $attribute) {
$fallbacks = $attribute['fallbacks'] ?? [];
if (is_array($setting) && !empty($setting)) {
foreach ($setting as &$value) {
$value = self::getFallbackValues($value, $fieldName, $attribute);
}
unset($value);
}
}
}
}
unset($setting);
foreach ($fieldStructureByAddon as $fieldName => $field) {
$fallbacks = $field['fallbacks'] ?? [];
if (!empty($fallbacks)) {
$settings = self::getFallbackValues($settings, $fieldName, $field);
}
}
return $settings;
}
private static function reshapeSpacingValues($spacing, $forceModern = false)
{
$isLegacy = self::$isLegacyData && !$forceModern;
$reshapedValue = $isLegacy ? ['', '', '', ''] : ['0px', '0px', '0px', '0px'];
$spacing = \ctype_space((string) $spacing) || $spacing === '' ? [] : explode(' ', $spacing);
$spacing = array_map(function ($value) use ($isLegacy) {
if (!$isLegacy && $value === '') {
return '0px';
}
return $value;
}, $spacing);
$spacing = array_filter($spacing, function ($value) {
return isset($value) && $value !== '';
});
$spacing = array_values($spacing);
$newSpacing = [];
switch (count($spacing)) {
case 0:
$newSpacing = [''];
break;
case 1:
$newSpacing = $isLegacy
? array_fill(0, 4, $spacing[0])
: array_replace($reshapedValue, $spacing);
break;
case 2:
$newSpacing = $isLegacy
? [$spacing[0], $spacing[1], $spacing[0], $spacing[1]]
: array_replace($reshapedValue, $spacing);
break;
case 3:
$newSpacing = $isLegacy
? [$spacing[0], $spacing[1], $spacing[2], $spacing[1]]
: array_replace($reshapedValue, $spacing);
break;
case 4:
$newSpacing = $spacing;
break;
}
return implode(" ", $newSpacing);
}
private static function transformSpacingValues($value, $forceModern = false)
{
if (self::hasMultiDeviceSettings($value)) {
foreach ($value as $device => $deviceData) {
$value->$device = !empty($deviceData) ? self::reshapeSpacingValues($deviceData, $forceModern) : $deviceData;
}
} elseif (is_string($value)) {
$value = self::reshapeSpacingValues($value, $forceModern);
}
return $value;
}
private static function traverseSettingsToFixSpacingAnomalies($settings, $fieldTypes, $forceModern = false)
{
if ($fieldTypes === null) {
return $settings;
}
if (!empty($settings)) {
foreach ($settings as $key => &$value) {
$fieldType = $fieldTypes[$key] ?? null;
if ($fieldType === null || (is_string($fieldType) && !in_array($fieldType, ['padding', 'margin']))) {
continue;
}
if (is_array($fieldType)) {
$repeatableTypes = $fieldType['fields'];
if (is_array($value)) {
foreach ($value as &$repeatableValue) {
$repeatableValue = self::traverseSettingsToFixSpacingAnomalies($repeatableValue, $repeatableTypes, false);
}
}
} else {
$value = self::transformSpacingValues($value, $forceModern);
}
}
unset($value);
}
return $settings;
}
private static function parsingSpacingValues($settings, $type, $addonName = '')
{
if ($type === 'addon' && (empty($addonName) || !isset(self::$addonFieldTypes[$addonName]))) {
return $settings;
}
switch ($type) {
case 'section':
$fieldTypes = self::$sectionFieldTypes;
break;
case 'column':
$fieldTypes = self::$columnFieldTypes;
break;
case 'addon':
$fieldTypes = self::$addonFieldTypes[$addonName];
break;
}
return self::traverseSettingsToFixSpacingAnomalies($settings, $fieldTypes, in_array($type, ['section', 'column']));
}
private static function hasLegacyDataInsideSettings($settings)
{
if (!empty($settings)) {
foreach ($settings as $setting) {
if (self::hasMultiDeviceSettings($setting) && isset($setting->xl)) {
return false;
}
}
}
return true;
}
private static function isLegacyDataStructure($content)
{
foreach ($content as $row) {
$settings = $row->settings;
if (!self::hasLegacyDataInsideSettings($settings)) {
return false;
}
}
return true;
}
public static function prepareSpacingData($text)
{
self::prepareSectionFieldStructures();
self::prepareColumnFieldStructures();
self::prepareAddonFieldStructures();
self::processFieldTypes('section');
self::processFieldTypes('column');
self::processFieldTypes('addon');
$content = is_string($text) ? json_decode($text) : $text;
self::$isLegacyData = self::isLegacyDataStructure($content);
if (!empty($content)) {
foreach ($content as &$section) {
$section->settings = self::parsingSpacingValues($section->settings, 'section');
if (!empty($section->columns)) {
foreach ($section->columns as &$column) {
$column->settings = self::parsingSpacingValues($column->settings, 'column');
if (!empty($column->addons)) {
foreach ($column->addons as &$addon) {
if (!empty($addon->settings)) {
$addon->settings = self::parsingSpacingValues($addon->settings, 'addon', $addon->name ?? '');
}
}
unset($addon);
}
}
unset($column);
}
}
unset($section);
}
return json_encode($content);
}
/**
* sanitize contents for making the old data valid for the data structure.
*
* @param string $text The json text of the page builder data.
*
* @return string The sanitized text.
*
* @since 4.0.0
*/
public static function sanitize(string $text): string
{
if (empty(self::$addonFieldStructures)) {
self::prepareAddonFieldStructures();
}
$rows = json_decode($text);
if (!empty($rows) && $rows !== "[]") {
foreach ($rows as $key => &$row) {
if (isset($rows[$key]->settings)) {
$rows[$key]->settings = self::shiftResponsiveSettings($row->settings);
$rows[$key]->settings = self::fixRowSettings($row->settings);
}
if (!empty($row->columns)) {
if (!isset($row->settings->fit_columns)) {
$row->settings->fit_columns = self::predictColumnFillStyle($row->columns);
}
foreach ($row->columns as $i => &$column) {
/** Predict the width from the column class name for the old layouts. */
if (!isset($column->width)) {
$width = self::getColumnWidth($column);
$column->width = $width;
}
if (\is_array($column->settings)) {
$column->settings = (object) $column->settings;
}
if (!isset($column->settings->width)) {
$width = !empty($column->width) ? $column->width : self::getColumnWidth($column);
$column->settings->width = $width;
if (isset($column->settings->width->unit)) {
unset($column->settings->width->unit);
}
}
$column->settings->width = self::purifyColumnWidth($column->settings->width);
if (isset($rows[$key]->columns[$i]->settings)) {
$rows[$key]
->columns[$i]
->settings = self::shiftResponsiveSettings($rows[$key]->columns[$i]->settings);
}
if (!empty($column->addons)) {
foreach ($column->addons as $j => &$addon) {
if (isset($rows[$key]->columns[$i]->addons[$j]->settings)) {
$rows[$key]
->columns[$i]
->addons[$j]
->settings = self::shiftResponsiveSettings($rows[$key]->columns[$i]->addons[$j]->settings);
if (isset($addon->name) && $addon->name === 'image_layouts') {
$addonSettings = $addon->settings;
$isBtnUrlExist = property_exists($addonSettings, 'btn_url');
$isButtonUrlExist = property_exists($addonSettings, 'button_url');
$isBtnTargetExist = property_exists($addonSettings, 'btn_target');
if (!$isButtonUrlExist && $isBtnUrlExist) {
$addonSettings->button_url = [
'type' => 'url',
'url' => $addonSettings->btn_url,
'new_tab' => $isBtnTargetExist ? $addonSettings->btn_target : false,
];
}
$isBtnTextExist = property_exists($addonSettings, 'btn_text');
$isButtonTextExist = property_exists($addonSettings, 'button_text');
if (!$isButtonTextExist && $isBtnTextExist) {
$addonSettings->button_text = $addonSettings->btn_text;
}
$isBtnTypeExist = property_exists($addonSettings, 'btn_type');
$isButtonTypeExist = property_exists($addonSettings, 'button_type');
if (!$isButtonTypeExist && $isBtnTypeExist) {
$addonSettings->button_type = $addonSettings->btn_type;
}
$isBtnShapeExist = property_exists($addonSettings, 'btn_shape');
$isButtonShapeExist = property_exists($addonSettings, 'button_shape');
if (!$isButtonShapeExist && $isBtnShapeExist) {
$addonSettings->button_shape = $addonSettings->btn_shape;
}
$isBtnSizeExist = property_exists($addonSettings, 'btn_size');
$isButtonSizeExist = property_exists($addonSettings, 'button_size');
if (!$isButtonSizeExist && $isBtnSizeExist) {
$addonSettings->button_size = $addonSettings->btn_size;
}
$isBtnColorExist = property_exists($addonSettings, 'btn_color');
$isButtonColorExist = property_exists($addonSettings, 'button_color');
if (!$isButtonColorExist && $isBtnColorExist) {
$addonSettings->button_color = $addonSettings->btn_color;
}
$isBtnColorHoverExist = property_exists($addonSettings, 'btn_color_hover');
$isButtonColorHoverExist = property_exists($addonSettings, 'button_color_hover');
if (!$isButtonColorHoverExist && $isBtnColorHoverExist) {
$addonSettings->button_color_hover = $addonSettings->btn_color_hover;
}
$isBtnAppearanceExist = property_exists($addonSettings, 'btn_appearance');
$isButtonAppearanceExist = property_exists($addonSettings, 'button_appearance');
if (!$isButtonAppearanceExist && $isBtnAppearanceExist) {
$addonSettings->button_appearance = $addonSettings->btn_appearance;
}
$isBtnBackgroundColorExist = property_exists($addonSettings, 'btn_background_color');
$isButtonBackgroundColorExist = property_exists($addonSettings, 'button_background_color');
if (!$isButtonBackgroundColorExist && $isBtnBackgroundColorExist) {
$addonSettings->button_background_color = $addonSettings->btn_background_color;
}
$isBtnBackgroundColorHoverExist = property_exists($addonSettings, 'btn_background_color_hover');
$isButtonBackgroundColorHoverExist = property_exists($addonSettings, 'button_background_color_hover');
if (!$isButtonBackgroundColorHoverExist && $isBtnBackgroundColorHoverExist) {
$addonSettings->button_background_color_hover = $addonSettings->btn_background_color_hover;
}
$isBtnBackgroundGradientExist = property_exists($addonSettings, 'btn_background_gradient');
$isButtonBackgroundGradientExist = property_exists($addonSettings, 'button_background_gradient');
if (!$isButtonBackgroundGradientExist && $isBtnBackgroundGradientExist) {
$addonSettings->button_background_gradient = $addonSettings->btn_background_gradient;
}
$isBtnBackgroundGradientHoverExist = property_exists($addonSettings, 'btn_background_gradient_hover');
$isButtonBackgroundGradientHoverExist = property_exists($addonSettings, 'button_background_gradient_hover');
if (!$isButtonBackgroundGradientHoverExist && $isBtnBackgroundGradientHoverExist) {
$addonSettings->button_background_gradient_hover = $addonSettings->btn_background_gradient_hover;
}
}
}
if (isset($addon->name) && isset($addon->settings)) {
$addon->settings = self::getTypographyFromFallbacks($addon->settings, $addon->name);
}
/** Migrate the slideshow items. */
if (isset($addon->name) && $addon->name === 'js_slideshow') {
if (!empty($addon->settings->slideshow_items)) {
foreach ($addon->settings->slideshow_items as $x => &$slideshowItem) {
if (isset($slideshowItem->slider_overlay_options) && $slideshowItem->slider_overlay_options === 'gradient_overaly') {
$slideshowItem->slider_overlay_options = 'gradient_overlay';
}
if (isset($slideshowItem->slider_bg_gradient_overlay) && !isset($slideshowItem->slider_bg_gradient_overlay->type)) {
$slideshowItem->slider_bg_gradient_overlay->type = 'linear';
}
$slideshowItem = self::shiftResponsiveSettings($slideshowItem);
if (!empty($slideshowItem->slideshow_inner_items)) {
foreach ($slideshowItem->slideshow_inner_items as $y => &$innerItem) {
$innerItem = self::shiftResponsiveSettings($innerItem);
}
unset($innerItem);
}
}
unset($slideshowItem);
}
}
/** Migrate the responsive settings for the repeatable items. */
if (isset($addon->name) && \in_array($addon->name, ['accordion', 'tab'])) {
$repeatableKey = 'sp_' . $addon->name . '_item';
if (!empty($addon->settings->$repeatableKey)) {
foreach ($rows[$key]->columns[$i]->addons[$j]->settings->$repeatableKey as &$itemSetting) {
$itemSetting = self::shiftResponsiveSettings($itemSetting);
}
unset($itemSetting);
}
}
if (isset($addon->name) && \in_array($addon->name, ['accordion', 'tab'])) {
list($outerRows, $addon) = self::migrateDeepAddon($addon, 'sp_' . $addon->name . '_item', $row, $column);
$rows[$key]->columns[$i]->addons[$j] = $addon;
array_push($rows, ...$outerRows);
}
if (isset($addon->name) && $addon->name === 'table_advanced') {
$nodeId = self::generateUUID();
if (isset($addon->settings->sp_table_advanced_item)) {
foreach ($addon->settings->sp_table_advanced_item as $th => $thead) {
if (isset($thead->content) && !\is_array($thead->content)) {
$thead = ['id' => $nodeId++, 'name' => 'text_block', 'visibility' => true, 'reference_id' => $addon->id, 'settings' => ['text' => $thead->content]];
$thead = \json_decode(\json_encode($thead));
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->sp_table_advanced_item[$th]
->content = [];
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->sp_table_advanced_item[$th]
->content[] = $thead;
} elseif (isset($thead->content) && \is_array($thead->content)) {
$contents = [];
foreach ($thead->content as $content) {
$content->reference_id = $addon->id;
$contents[] = $content;
}
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->sp_table_advanced_item[$th]
->content = $contents;
}
}
}
foreach ($addon->settings->table_advanced_item as $r => $tRow) {
if (isset($tRow->table_advanced_item)) {
foreach ($tRow->table_advanced_item as $c => $tCell) {
if (isset($tCell->content) && !\is_array($tCell->content)) {
$td = ['id' => $nodeId++, 'name' => 'text_block', 'visibility' => true, 'reference_id' => $addon->id, 'settings' => ['text' => $tCell->content]];
$td = \json_decode(\json_encode($td));
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content = [];
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content[] = $td;
} elseif (isset($tCell->content) && \is_array($tCell->content)) {
$contents = [];
foreach ($tCell->content as &$content) {
$content->reference_id = $addon->id;
$contents[] = $content;
}
$rows[$key]
->columns[$i]
->addons[$j]
->settings
->table_advanced_item[$r]
->table_advanced_item[$c]
->content = $contents;
unset($content);
}
}
}
}
}
if (isset($addon->type) && $addon->type === 'inner_row') {
$nestedRowAddon = new \stdClass;
$nestedRowAddon->type = 'nested_row';
$nestedRowAddon->name = 'row';
$nestedRowAddon->id = $addon->id;
$addon->parent = new \stdClass;
$addon->parent->rowId = $row->id;
$addon->parent->columnId = $column->id;
unset($addon->type);
$rows[] = $addon;
$rows[$key]->columns[$i]->addons[$j] = $nestedRowAddon;
}
}
unset($addon);
}
}
unset($column);
}
}
unset($row);
} else {
return $text;
}
return json_encode($rows);
}
public static function fixRowSettings($settings)
{
if (isset($settings->background_type)) {
return $settings;
}
$settings->background_type = 'none';
$keyMap = [
'background_image' => 'image',
'background_color' => 'color',
'background_gradient' => 'gradient',
'background_video' => 'video',
'background_video_mp4' => 'video',
'background_video_ogv' => 'video',
'background_external_video' => 'video',
];
foreach ($keyMap as $key => $value) {
if (!empty($settings->$key)) {
$settings->background_type = $value;
break;
}
}
return $settings;
}
/**
* Migrate the accordion addon to the current structure.
*
* @param \stdClass $addon The accordion addon object.
*
* @return array
* @since 4.0.0
*/
private static function migrateDeepAddon(\stdClass $addon, $key, $row, $column): array
{
$addon = json_decode(json_encode($addon));
$addonCollection = [];
$outerRows = [];
if (!isset($addon->parent) || (isset($addon->parent) && !$addon->parent)) {
$addon->id = self::nanoid();
}
if (isset($addon->settings->$key)) {
foreach ($addon->settings->$key as $itemIndex => $item) {
$addonCollection = [];
if (isset($item->content) && \is_array($item->content)) {
foreach ($item->content as $deepAddon) {
if (isset($deepAddon->type) && $deepAddon->type === 'nested_row') {
continue;
}
$addonCollection[] = $deepAddon;
}
if (\count($addonCollection) > 0) {
$_parent = ['rowId' => $row->id, 'columnId' => $column->id];
$_parent = (object) $_parent;
$row = self::createRow('12', $addonCollection, $_parent);
$row->parent_addon = $addon->id;
$outerRows[] = $row;
$nestedRow = ['type' => 'nested_row', 'id' => $row->id, 'name' => 'row'];
$nestedRow = (object) $nestedRow;
$addon->settings->$key[$itemIndex]->content = [];
$addon->settings->$key[$itemIndex]->content[] = $nestedRow;
}
} else if (isset($item->content) && \is_string($item->content)) {
$textAddon = ['id' => self::nanoid(), 'name' => 'text_block', 'settings' => ['text' => $item->content]];
$addonCollection[] = $textAddon;
$_parent = ['rowId' => $row->id, 'columnId' => $column->id];
$_parent = (object) $_parent;
$row = self::createRow('12', $addonCollection, $_parent);
$row->parent_addon = $addon->id;
$outerRows[] = $row;
$nestedRow = ['type' => 'nested_row', 'id' => $row->id, 'name' => 'row'];
$nestedRow = (object) $nestedRow;
$addon->settings->$key[$itemIndex]->content = [];
$addon->settings->$key[$itemIndex]->content[] = $nestedRow;
}
}
}
return [$outerRows, $addon];
}
/**
* Create Row function
*
* @param string $layout Default layout size
* @param array $addons Addons
* @param mixed $parent Parent row.
*
* @return object
*
* @since 4.0.0
*/
public static function createRow(string $layout = '12', array $addons = [], $parent = null)
{
$rowId = self::nanoid();
$layouts = explode('+', $layout);
$rowDefaultValues = EditorUtils::getSectionSettingsDefaultValues();
$columnDefaultValues = EditorUtils::getColumnSettingsDefaultValues();
$rowDefaultValues = json_decode(json_encode($rowDefaultValues));
$columnDefaultValues = json_decode(json_encode($columnDefaultValues));
$columns = array_map(function ($col) use ($columnDefaultValues, $addons) {
$width = (float) ((100 / (12 / (int) $col))) . '%';
$widthObject = ['xl' => $width, 'lg' => $width, 'md' => $width, 'sm' => '100%', 'xs' => '100%'];
$widthObject = (object) $widthObject;
$columnObject = [
'id' => self::nanoid(),
'class_name' => 'row-column',
'visibility' => true,
'settings' => $columnDefaultValues,
'addons' => $addons,
'width' => $widthObject,
];
return (object) $columnObject;
}, $layouts);
$rowDefaultValues->padding = '5px 0px 5px 0px';
$rowDefaultValues->margin = '0px 0px 0px 0px';
$rowObject = [
'id' => $rowId,
'visibility' => true,
'collapse' => false,
'settings' => $rowDefaultValues,
'layout' => $layout,
'columns' => $columns,
'parent' => $parent ? $parent : false,
];
return (object) $rowObject;
}
/**
* Generate a unique ID by using microtime.
*
* @return integer
* @since 4.0.0
*/
public static function generateUUID(): int
{
return (int) (microtime(true) * 1000);
}
/**
* Shift responsive device settings for with the new device structure.
*
* @param \stdClass $settings The settings value.
*
* @return \stdClass | null
* @since 4.0.0
*/
public static function shiftResponsiveSettings($settings)
{
if (!empty($settings)) {
foreach ($settings as $key => $setting) {
if (\is_object($setting) && isset($setting->md) && !isset($setting->xl)) {
$tmp = (object) ['xl' => '', 'lg' => '', 'md' => '', 'sm' => '', 'xs' => ''];
if (isset($setting->md)) {
$tmp->xl = $setting->md;
}
if (isset($setting->sm)) {
$tmp->lg = $setting->sm;
$tmp->md = $setting->sm;
}
if (isset($setting->xs)) {
$tmp->sm = $setting->xs;
$tmp->xs = $setting->xs;
}
if (isset($setting->unit)) {
$tmp->unit = $setting->unit;
}
$settings->$key = $tmp;
}
}
if (isset($settings->hidden_md) && !isset($settings->hidden_xl)) {
if (isset($settings->hidden_md)) {
$settings->hidden_xl = $settings->hidden_md;
}
if (isset($settings->hidden_sm)) {
$settings->hidden_lg = $settings->hidden_sm;
$settings->hidden_md = $settings->hidden_sm;
}
if (isset($settings->hidden_xs)) {
$settings->hidden_sm = $settings->hidden_xs;
$settings->hidden_xs = $settings->hidden_xs;
}
}
}
return $settings;
}
/**
* Remove sp_ from the addon name
*
* @return void
* @since 4.0.0
*/
public static function sanitize_addon_name($addon_name)
{
$from = '/' . preg_quote('sp_', '/') . '/';
return preg_replace($from, '', $addon_name, 1);
}
/**
* Load Language File
*
* @param boolean $forceLoad
* @return void
*/
public static function loadLanguage($forceLoad = false)
{
$lang = Factory::getLanguage();
/** @var CMSApplication */
$app = Factory::getApplication();
$template = $app->getTemplate();
if ($app->isClient('administrator')) {
$template = self::getTemplate();
}
$com_option = $app->input->get('option', '', 'STR');
$com_view = $app->input->get('view', '', 'STR');
$com_id = $app->input->get('id', 0, 'INT');
if (($com_option == 'com_sppagebuilder' && $com_view == 'form' && $com_id) || $forceLoad) {
$lang->load('com_sppagebuilder', JPATH_ADMINISTRATOR, null, true);
}
// Load template language file
$lang->load('tpl_' . $template, JPATH_SITE, null, true);
self::setPluginsAddonsLanguage();
if (ApplicationHelper::isEasyStoreInstalled() && ApplicationHelper::isProVersion()) {
$lang->load('com_easystore', JPATH_BASE, null, true);
$lang->load('com_easystore', JPATH_ADMINISTRATOR, null, true);
}
if (($com_option === 'com_sppagebuilder' && $com_view !== 'page')) {
require_once JPATH_ROOT . '/administrator/components/com_sppagebuilder/helpers/language.php';
}
}
private static function getTemplate()
{
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select('template')
->from($db->quoteName('#__template_styles'))
->where($db->quoteName('client_id') . ' = 0')
->where($db->quoteName('home') . ' = 1');
$db->setQuery($query);
return $db->loadResult();
}
/**
* Load Plugin addons language files.
*
* @return void
*/
private static function setPluginsAddonsLanguage()
{
$path = JPATH_PLUGINS . '/sppagebuilder';
if (!Folder::exists($path)) {
return;
}
$plugins = Folder::folders($path);
if (!count((array) $plugins)) {
return;
}
foreach ($plugins as $plugin) {
if (PluginHelper::isEnabled('sppagebuilder', $plugin)) {
$lang = Factory::getLanguage();
$lang->load('plg_' . $plugin, JPATH_ADMINISTRATOR, null, true);
}
}
}
/**
* Convert Padding Margin Value.
*
* @param string $main_value CSS value
* @param string $type CSS property
*
* @return string
*
* @since 4.0.0
*/
public static function getPaddingMargin($main_value, $type): string
{
$css = '';
$pos = array('top', 'right', 'bottom', 'left');
if (is_string($main_value) && trim($main_value) != "") {
$values = explode(' ', $main_value);
foreach ($values as $key => $value) {
$value = preg_replace('@/s@', '', $value);
if ($value !== "") {
$css .= $type . '-' . $pos[$key] . ': ' . $value . ';';
}
}
}
return $css;
}
public static function getSvgShapes()
{
$shape_path = JPATH_ROOT . '/components/com_sppagebuilder/assets/shapes';
$shapes = Folder::files($shape_path, '.svg');
$shapeArray = array();
if (count((array) $shapes)) {
foreach ($shapes as $shape) {
$shapeArray[str_replace('.svg', '', $shape)] = base64_encode(file_get_contents($shape_path . '/' . $shape));
}
}
return $shapeArray;
}
public static function getSvgShapeCode($shapeName, $invert)
{
if ($invert) {
$shape_path = JPATH_ROOT . '/components/com_sppagebuilder/assets/shapes/' . $shapeName . '-invert.svg';
} else {
$shape_path = JPATH_ROOT . '/components/com_sppagebuilder/assets/shapes/' . $shapeName . '.svg';
}
$shapeCode = '';
if (file_exists($shape_path)) {
$shapeCode = file_get_contents($shape_path);
}
return is_string($shapeCode) ? $shapeCode : '';
}
// Convert json code to plain text
public static function getPrettyText($sections)
{
if (!class_exists('AddonParser')) {
require_once JPATH_ROOT . '/components/com_sppagebuilder/parser/addon-parser.php';
}
if (!class_exists('SpPageBuilderAddonHelper')) {
require_once JPATH_ROOT . '/components/com_sppagebuilder/builder/classes/addon.php';
}
$content = ApplicationHelper::sanitizePageText($sections);
$htmlContent = AddonParser::viewAddons($content, 0, 'none', 1, true, [], true);
$htmlContent = str_replace('><', '> <', $htmlContent);
return trim(strip_tags($htmlContent));
}
public static function addScript($script, $client = 'site', $version = true)
{
$doc = Factory::getDocument();
$script_url = Uri::base(true) . ($client == 'admin' ? '/administrator' : '') . '/components/com_sppagebuilder/assets/js/' . $script;
if ($version) {
$script_url .= '?' . self::getVersion(true);
}
$doc->addScript($script_url);
}
public static function addStylesheet($stylesheet, $client = 'site', $version = true)
{
$doc = Factory::getDocument();
$stylesheet_url = Uri::base(true) . ($client == 'admin' ? '/administrator' : '') . '/components/com_sppagebuilder/assets/css/' . $stylesheet;
if ($version) {
$stylesheet_url .= '?' . self::getVersion(true);
}
$doc->addStylesheet($stylesheet_url);
}
public static function addContainerMaxWidth()
{
$doc = Factory::getDocument();
$params = ComponentHelper::getParams('com_sppagebuilder');
$containerMaxWidth = $params->get('container_max_width', 1320);
$doc->addStyleDeclaration("@media(min-width: 1400px) {.sppb-row-container { max-width: " . $containerMaxWidth . "px; }}");
}
public static function getVersion($md5 = false)
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('e.manifest_cache')
->select($db->quoteName('e.manifest_cache'))
->from($db->quoteName('#__extensions', 'e'))
->where($db->quoteName('e.element') . ' = ' . $db->quote('com_sppagebuilder'));
$db->setQuery($query);
$manifest_cache = json_decode($db->loadResult());
if (isset($manifest_cache->version) && $manifest_cache->version) {
if ($md5) {
return md5($manifest_cache->version);
}
return $manifest_cache->version;
}
return '1.0';
}
/**
* Load Assets form database table.
*
* @return void
*/
public static function loadAssets()
{
$doc = Factory::getDocument();
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('a.name', 'a.css_path')))
->from($db->quoteName('#__sppagebuilder_assets', 'a'))
->where($db->quoteName('a.published') . ' = 1');
$db->setQuery($query);
$assets = $db->loadObjectList();
if (!empty($assets)) {
foreach ($assets as $asset) {
$asset_url = Uri::base(true) . '/' . $asset->css_path . '?' . self::getVersion(true);
$doc->addStylesheet($asset_url);
}
}
}
/**
* Get the current template name form database.
*
* @return void
*/
public static function getTemplateName()
{
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(['template']))
->from($db->quoteName('#__template_styles'))
->where($db->quoteName('client_id') . ' = 0')
->where($db->quoteName('home') . ' = 1');
$db->setQuery($query);
return $db->loadObject()->template;
}
/**
* Get installed google fonts from database.
*
* @return array
*/
public static function getInstalledGoogleFonts()
{
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select('family_name')
->from($db->quoteName('#__sppagebuilder_fonts'))
->where($db->quoteName('type') . ' = ' . $db->quote('google'));
$db->setQuery($query);
try
{
return $db->loadColumn() ?? [];
} catch (Exception $e) {
return [];
}
}
/**
* Checking multi device settings
*
* @param mixed $value
* @return boolean
*
* @since 5.0.0
*/
public static function hasMultiDeviceSettings($value): bool
{
return isset($value->xl)
|| isset($value->lg)
|| isset($value->md)
|| isset($value->sm)
|| isset($value->xs);
}
/**
* Checking media item
*
* @param mixed $value
* @return boolean
*
* @since 5.0.0
*/
public static function isMediaItemData($value): bool
{
return isset($value->src);
}
/**
* Clean media path
*
* @param string $path
* @return string
*
* @since 5.0.3
*/
public static function cleanPath($path): string
{
$cleanedPath = Path::clean($path);
$cleanedPath = str_replace("/\\", "\\", $cleanedPath);
$cleanedPath = str_replace("\\", "/", $cleanedPath);
return $cleanedPath;
}
public static function classes(array $classNames): string
{
$filteredClassNames = array_filter($classNames, function ($value) {
return (bool) trim(strval($value));
});
return implode(" ", $filteredClassNames);
}
/**
* Initialize the basic settings for the page builder page view
*
* @param $data object
* @return object
*/
public static function initView($data)
{
/** @var CMSApplication */
$app = Factory::getApplication();
$doc = $app->getDocument();
$params = ComponentHelper::getParams('com_sppagebuilder');
if ($params->get('fontawesome', 1)) {SppagebuilderHelperSite::addStylesheet('font-awesome-6.min.css');
SppagebuilderHelperSite::addStylesheet('font-awesome-v4-shims.css');}
if (!$params->get('disableanimatecss', 0)) {
SppagebuilderHelperSite::addStylesheet('animate.min.css');
}
if (!$params->get('disablecss', 0)) {
SppagebuilderHelperSite::addStylesheet('sppagebuilder.css');
SppagebuilderHelperSite::addStylesheet('animate.min.css');
SppagebuilderHelperSite::addContainerMaxWidth();
}
// load font assets form database
SppagebuilderHelperSite::loadAssets();
HTMLHelper::_('jquery.framework');
HTMLHelper::_('script', 'components/com_sppagebuilder/assets/js/jquery.parallax.js', ['version' => SppagebuilderHelperSite::getVersion(true)]);
HTMLHelper::_('script', 'components/com_sppagebuilder/assets/js/es5_interaction.js', ['version' => SppagebuilderHelperSite::getVersion(true)], ['defer' => true]);
HTMLHelper::_('script', 'components/com_sppagebuilder/assets/js/sppagebuilder.js', ['version' => SppagebuilderHelperSite::getVersion(true)], ['defer' => true]);
require_once JPATH_ROOT . '/components/com_sppagebuilder/parser/addon-parser.php';
require_once JPATH_ROOT . '/components/com_sppagebuilder/builder/classes/addon.php';
// Add page css
if (isset($data->css) && $data->css) {
$doc->addStyledeclaration($data->css);
}
$content = $data->content;
return is_string($content) ? json_decode($content) : $content;
}
}