<?php /** * @package SP Page Builder * @author JoomShaper http://www.joomshaper.com * @copyright Copyright (c) 2010 - 2023 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\Uri\Uri; use Joomla\CMS\Filesystem\Folder; use Joomla\CMS\Filesystem\Path; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Plugin\PluginHelper; 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-5.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; } }