@N0STR4 Datawise 1.0.9.1 surum icinde theme.php dosyasını cözdüm ama diyer modul cözdüm ama biraz ugraşın diye paylaşmıyorum tama calıştırmak icin FonPageBuilder icinde lisans mekanizması var theme icinde lisans mekanızması yok @Graves şifreli 3 dosyayı sana yolladım zaten istersen paylaş kırabilen varsa kırsın
PHP:
<?php
class Datawise_Theme
{
public $name = 'Datawise';
public $error = null;
public $db_prefix = null;
public $lang = null;
public $language = null;
public $languages = null;
public array $config = [];
private array $assets = [];
private array $styles = [];
private array $scripts = [];
private array $headerCodes = [];
private static $builderConfig = [];
private static $lcpHandled = false;
public function __construct()
{
if (!$this->languages) {
$this->languages = View::$init->theme_language_loader($this->name);
}
if (!$this->language) {
$this->language = View::$init->theme_lang(Language::selected(), $this->languages);
}
if (!$this->lang) {
$this->lang = Language::selected();
}
$this->db_prefix = (Config::get('database/prefix') ? Config::get('database/prefix') . '_' : '');
$this->config = include __DIR__ . DS . 'theme-config.php';
self::$builderConfig = Modules::Config('Addons', 'FonPageBuilder');
$this->checkAndUpdateVersion();
if (DEMO_MODE) {
$headerType = Cookie::get('fon_header_type');
if (isset($_GET['setHeaderType'])) {
$setHeaderType = $_GET['setHeaderType'];
Cookie::set('fon_header_type', $setHeaderType ?: 'header');
$headerType = $setHeaderType;
}
Config::set('theme', ['header-type' => $headerType ?: 'header']);
$headerStyle = Cookie::get('fon_header_style');
if (isset($_GET['setHeaderStyle'])) {
$setHeaderStyle = $_GET['setHeaderStyle'];
Cookie::set('fon_header_style', $setHeaderStyle ?: 'header_compact');
$headerStyle = $setHeaderStyle;
}
Config::set('theme', ['header_style' => $headerStyle ?: 'header_compact']);
$primaryColor = Cookie::get('fon_primary_color');
if (isset($_GET['setPrimaryColor'])) {
$setPrimaryColor = $_GET['setPrimaryColor'];
Cookie::set('fon_primary_color', $setPrimaryColor ?: Config::get('theme/color1'));
$primaryColor = $setPrimaryColor;
}
Config::set('theme', ['color1' => ltrim($primaryColor, '#') ?: Config::get('theme/color1')]);
}
}
public function router(array $params = []): mixed
{
$raw = implode('/', $params);
$page = Filter::folder((isset($params[0]) ? $params[0] : ''));
if (($params[0] ?? false) && $params[1] ?? false && file_exists(__DIR__ . DS . 'pages' . DS . Filter::folder($params[0] ?? false) . DS . Filter::folder($params[1] ?? false) . '.php')) {
return ['include_file' => __DIR__ . DS . 'pages' . DS . Filter::folder($params[0] ?? false) . DS . Filter::folder($params[1] ?? false) . '.php'];
}
else if ($page && file_exists(__DIR__ . DS . 'pages' . DS . $page . '.php')) {
return ['include_file' => __DIR__ . DS . 'pages' . DS . $page . '.php'];
}
return false;
}
public function change_settings(): array
{
$settings = (isset($this->config['settings']) ? $this->config['settings'] : []);
$languages = Bootstrap::$lang->rank_list('active');
$header_type = Filter::init('POST/header_type', 'hclear');
$clientArea_type = (int) Filter::init('POST/clientArea_type', 'numbers');
$color1 = ltrim(Filter::init('POST/color1'), '#');
$color2 = ltrim(Filter::init('POST/color2'), '#');
$text_color = ltrim(Filter::init('POST/text-color'), '#');
$link_color = ltrim(Filter::init('POST/link_color'), '#');
$link_color_hover = ltrim(Filter::init('POST/link_color_hover'), '#');
$link_color_active = ltrim(Filter::init('POST/link_color_active'), '#');
$articles_style = (int) Filter::init('POST/articles_style', 'numbers');
$news_style = (int) Filter::init('POST/news_style', 'numbers');
$references_style = (int) Filter::init('POST/references_style', 'numbers');
$software_style = (int) Filter::init('POST/software_style', 'numbers');
$image_sizes = Filter::init('POST/image_sizes', 'array');
$sticky_header = (bool) Filter::init('POST/sticky_header', 'numbers');
$cache_pages = (bool) Filter::init('POST/cache_pages', 'numbers');
$show_preloader = (bool) Filter::init('POST/show_preloader', 'numbers');
$preloader = Filter::init('POST/site_preloader', 'hclear');
$preloader_bg = ltrim(Filter::init('POST/site_preloader_bg'), '#');
$show_totop = (bool) Filter::init('POST/show_totop', 'numbers');
$show_contact_info = (bool) Filter::init('POST/show_contact_info', 'numbers');
$top_notify_show = (bool) Filter::init('POST/top_notify_show', 'numbers');
$top_notify_text = Filter::init('POST/top_notify_text', 'array');
$top_notify_show_link = (bool) Filter::init('POST/top_notify_show_link', 'numbers');
$top_notify_link = Filter::init('POST/top_notify_link', 'array');
$top_notify_link_text = Filter::init('POST/top_notify_link_text', 'array');
$top_notify_show_countdown = (bool) Filter::init('POST/top_notify_show_countdown', 'numbers');
$top_notify_countdown_date = Filter::init('POST/top_notify_countdown_date', 'hclear');
$top_notify_countdown_time = Filter::init('POST/top_notify_countdown_time', 'hclear');
$top_notify_show_close = (bool) Filter::init('POST/top_notify_show_close', 'numbers');
$popup_notify_show = (bool) Filter::init('POST/popup_notify_show', 'numbers');
$popup_notify_image = Filter::init('POST/popup_notify_image', 'array');
$popup_notify_show_link = (bool) Filter::init('POST/popup_notify_show_link', 'numbers');
$popup_notify_link = Filter::init('POST/popup_notify_link', 'array');
$popup_notify_link_text = Filter::init('POST/popup_notify_link_text', 'array');
$popup_notify_show_countdown = (bool) Filter::init('POST/popup_notify_show_countdown', 'numbers');
$popup_notify_countdown_date = Filter::init('POST/popup_notify_countdown_date', 'hclear');
$popup_notify_countdown_time = Filter::init('POST/popup_notify_countdown_time', 'hclear');
$popup_notify_display = Filter::init('POST/popup_notify_display', 'hclear');
$popup_notify_display_when = Filter::init('POST/popup_notify_display_when', 'hclear');
$right_click = (bool) Filter::init('POST/right_click', 'numbers');
$header_style = Filter::init('POST/header_style', 'hclear');
$header_style_align = Filter::init('POST/header_style_align', 'hclear');
$header_search = (bool) Filter::init('POST/header_search', 'numbers');
$header_phone = (bool) Filter::init('POST/header_phone', 'numbers');
$header_email = (bool) Filter::init('POST/header_email', 'numbers');
$header_social = (bool) Filter::init('POST/header_social', 'numbers');
$header_lang = (bool) Filter::init('POST/header_lang', 'numbers');
$header_currency = (bool) Filter::init('POST/header_currency', 'numbers');
$header_ticket = (bool) Filter::init('POST/header_ticket', 'numbers');
$header_seperated_sign = (bool) Filter::init('POST/header_seperated_sign', 'numbers');
$show_whatsapp = (bool) Filter::init('POST/show_whatsapp', 'numbers');
$whatsapp_number = Filter::init('POST/whatsapp_number', 'hclear');
$show_phone = (bool) Filter::init('POST/show_phone', 'numbers');
$seo_gsd_show = (bool) Filter::init('POST/seo_gsd_show', 'numbers');
$seo_site_name = Filter::init('POST/seo_site_name', 'array');
$seo_organisation_name = Filter::init('POST/seo_organisation_name', 'array');
$seo_organisation_country = Filter::init('POST/seo_organisation_country', 'hclear');
$seo_organisation_city = Filter::init('POST/seo_organisation_city', 'hclear');
$seo_organisation_region = Filter::init('POST/seo_organisation_region', 'hclear');
$seo_organisation_address = Filter::init('POST/seo_organisation_address', 'hclear');
$seo_organisation_postal_code = Filter::init('POST/seo_organisation_postal_code', 'hclear');
$seo_organisation_price_min = (int) Filter::init('POST/seo_organisation_price_min', 'numbers');
$seo_organisation_price_max = (int) Filter::init('POST/seo_organisation_price_max', 'numbers');
$seo_organisation_price_currency = (int) Filter::init('POST/seo_organisation_price_currency', 'numbers');
$seo_organisation_rating_value = Filter::init('POST/seo_organisation_rating_value', 'hclear');
$seo_organisation_rating_count = (int) Filter::init('POST/seo_organisation_rating_count', 'numbers');
$fonts = Filter::init('POST/fonts', 'array');
$external_login = (bool) Filter::init('POST/external_login', 'numbers');
$use_cdn = (bool) Filter::init('POST/use_cdn', 'numbers');
$package_style = (int) Filter::init('POST/package_style', 'numbers');
$order_steps_monthly_price = (int) Filter::init('POST/order_steps_monthly_price', 'numbers');
$footer_bg_image = Filter::init('POST/footer_bg_image', 'hclear');
$show_footer_home_newsletter = (bool) Filter::init('POST/show_footer_home_newsletter', 'numbers');
$show_footer_social = (bool) Filter::init('POST/show_footer_social', 'numbers');
$show_secure_and_payment_icons = (bool) Filter::init('POST/show_secure_and_payment_icons', 'numbers');
$footer_copyright_text = Filter::init('POST/footer_copyright_text', 'array');
$enable_lazy_loading = (bool) Filter::init('POST/enable_lazy_loading', 'numbers');
$google_analytics_id = Filter::init('POST/google_analytics_id', 'hclear');
$google_ads_id = Filter::init('POST/google_ads_id', 'hclear');
$google_conversion_id = Filter::init('POST/google_conversion_id', 'hclear');
$facebook_pixel_id = Filter::init('POST/facebook_pixel_id', 'hclear');
$google_tm_id = Filter::init('POST/google_tm_id', 'hclear');
$fb_pixel_via_gtm = (bool) Filter::init('POST/fb_pixel_via_gtm', 'numbers');
if ($header_type != $settings['header-type']) {
$settings['header-type'] = $header_type;
}
if ($header_search != $settings['header_search']) {
$settings['header_search'] = $header_search;
}
if ($header_phone != $settings['header_phone']) {
$settings['header_phone'] = $header_phone;
}
if ($header_email != $settings['header_email']) {
$settings['header_email'] = $header_email;
}
if ($header_social != $settings['header_social']) {
$settings['header_social'] = $header_social;
}
if ($header_lang != $settings['header_lang']) {
$settings['header_lang'] = $header_lang;
}
if ($header_currency != $settings['header_currency']) {
$settings['header_currency'] = $header_currency;
}
if ($header_ticket != $settings['header_ticket']) {
$settings['header_ticket'] = $header_ticket;
}
if ($header_seperated_sign != $settings['header_seperated_sign']) {
$settings['header_seperated_sign'] = $header_seperated_sign;
}
if ($footer_bg_image != $settings['footer_bg_image']) {
$settings['footer_bg_image'] = $footer_bg_image;
}
if ($show_footer_home_newsletter != $settings['show_footer_home_newsletter']) {
$settings['show_footer_home_newsletter'] = $show_footer_home_newsletter;
}
if ($show_footer_social != $settings['show_footer_social']) {
$settings['show_footer_social'] = $show_footer_social;
}
if ($show_secure_and_payment_icons != $settings['show_secure_and_payment_icons']) {
$settings['show_secure_and_payment_icons'] = $show_secure_and_payment_icons;
}
if ($clientArea_type != $settings['clientArea-type']) {
$settings['clientArea-type'] = $clientArea_type;
}
if ($color1 != $settings['color1']) {
$settings['color1'] = $color1;
$settings['meta-color'] = '#' . $color1;
}
if ($color2 != $settings['color2']) {
$settings['color2'] = $color2;
}
if ($text_color != $settings['text-color']) {
$settings['text-color'] = $text_color;
}
if ($link_color != $settings['link_color']) {
$settings['link_color'] = $link_color;
}
if ($link_color_hover != $settings['link_color_hover']) {
$settings['link_color_hover'] = $link_color_hover;
}
if ($link_color_active != $settings['link_color_active']) {
$settings['link_color_active'] = $link_color_active;
}
if ($articles_style != $settings['articles_style']) {
$settings['articles_style'] = $articles_style;
}
if ($news_style != $settings['news_style']) {
$settings['news_style'] = $news_style;
}
if ($references_style != $settings['references_style']) {
$settings['references_style'] = $references_style;
}
if ($software_style != $settings['software_style']) {
$settings['software_style'] = $software_style;
}
if ($sticky_header != $settings['sticky_header']) {
$settings['sticky_header'] = $sticky_header;
}
if ($cache_pages != $settings['cache_pages']) {
$settings['cache_pages'] = $cache_pages;
}
if ($show_preloader != $settings['show_preloader']) {
$settings['show_preloader'] = $show_preloader;
}
if ($preloader != $settings['site_preloader']) {
$settings['site_preloader'] = $preloader;
}
if ($preloader_bg != $settings['site_preloader_bg']) {
$settings['site_preloader_bg'] = $preloader_bg;
}
if ($show_totop != $settings['show_totop']) {
$settings['show_totop'] = $show_totop;
}
if ($show_contact_info != $settings['show_contact_info']) {
$settings['show_contact_info'] = $show_contact_info;
}
if ($external_login != $settings['external_login']) {
$settings['external_login'] = $external_login;
}
if ($use_cdn != $settings['use_cdn']) {
$settings['use_cdn'] = $use_cdn;
}
if ($package_style != $settings['package_style']) {
$settings['package_style'] = $package_style;
}
if ($enable_lazy_loading != $settings['enable_lazy_loading']) {
$settings['enable_lazy_loading'] = $enable_lazy_loading;
}
if ($top_notify_show != $settings['top_notify_show']) {
$settings['top_notify_show'] = $top_notify_show;
}
if ($top_notify_show_link != $settings['top_notify_show_link']) {
$settings['top_notify_show_link'] = $top_notify_show_link;
}
if ($top_notify_show_countdown != $settings['top_notify_show_countdown']) {
$settings['top_notify_show_countdown'] = $top_notify_show_countdown;
}
if ($top_notify_countdown_date != $settings['top_notify_countdown_date']) {
$settings['top_notify_countdown_date'] = $top_notify_countdown_date;
}
if ($top_notify_countdown_time != $settings['top_notify_countdown_time']) {
$settings['top_notify_countdown_time'] = $top_notify_countdown_time;
}
if ($top_notify_show_close != $settings['top_notify_show_close']) {
$settings['top_notify_show_close'] = $top_notify_show_close;
}
if ($popup_notify_show != $settings['popup_notify_show']) {
$settings['popup_notify_show'] = $popup_notify_show;
}
if ($popup_notify_show_link != $settings['popup_notify_show_link']) {
$settings['popup_notify_show_link'] = $popup_notify_show_link;
}
if ($popup_notify_show_countdown != $settings['popup_notify_show_countdown']) {
$settings['popup_notify_show_countdown'] = $popup_notify_show_countdown;
}
if ($popup_notify_countdown_date != $settings['popup_notify_countdown_date']) {
$settings['popup_notify_countdown_date'] = $popup_notify_countdown_date;
}
if ($popup_notify_countdown_time != $settings['popup_notify_countdown_time']) {
$settings['popup_notify_countdown_time'] = $popup_notify_countdown_time;
}
if ($popup_notify_display != $settings['popup_notify_display']) {
$settings['popup_notify_display'] = $popup_notify_display;
}
if ($popup_notify_display_when != $settings['popup_notify_display_when']) {
$settings['popup_notify_display_when'] = $popup_notify_display_when;
}
if ($right_click != $settings['right_click']) {
$settings['right_click'] = $right_click;
}
if ($header_style != $settings['header_style']) {
$settings['header_style'] = $header_style;
}
if ($header_style_align != $settings['header_style_align']) {
$settings['header_style_align'] = $header_style_align;
}
if ($show_whatsapp != $settings['show_whatsapp']) {
$settings['show_whatsapp'] = $show_whatsapp;
}
if ($whatsapp_number != $settings['whatsapp_number']) {
$settings['whatsapp_number'] = $whatsapp_number;
}
if ($show_phone != $settings['show_phone']) {
$settings['show_phone'] = $show_phone;
}
if ($seo_gsd_show != $settings['seo_gsd_show']) {
$settings['seo_gsd_show'] = $seo_gsd_show;
}
if ($seo_organisation_country != $settings['seo_organisation_country']) {
$settings['seo_organisation_country'] = $seo_organisation_country;
}
if ($seo_organisation_city != $settings['seo_organisation_city']) {
$settings['seo_organisation_city'] = $seo_organisation_city;
}
if ($seo_organisation_region != $settings['seo_organisation_region']) {
$settings['seo_organisation_region'] = $seo_organisation_region;
}
if ($seo_organisation_address != $settings['seo_organisation_address']) {
$settings['seo_organisation_address'] = $seo_organisation_address;
}
if ($seo_organisation_postal_code != $settings['seo_organisation_postal_code']) {
$settings['seo_organisation_postal_code'] = $seo_organisation_postal_code;
}
if ($seo_organisation_price_min != $settings['seo_organisation_price_min']) {
$settings['seo_organisation_price_min'] = $seo_organisation_price_min;
}
if ($seo_organisation_price_max != $settings['seo_organisation_price_max']) {
$settings['seo_organisation_price_max'] = $seo_organisation_price_max;
}
if ($seo_organisation_price_currency != $settings['seo_organisation_price_currency']) {
$settings['seo_organisation_price_currency'] = $seo_organisation_price_currency;
}
if ($seo_organisation_rating_value != $settings['seo_organisation_rating_value']) {
$settings['seo_organisation_rating_value'] = $seo_organisation_rating_value;
}
if ($seo_organisation_rating_count != $settings['seo_organisation_rating_count']) {
$settings['seo_organisation_rating_count'] = $seo_organisation_rating_count;
}
if ($order_steps_monthly_price != $settings['order_steps_monthly_price']) {
$settings['order_steps_monthly_price'] = $order_steps_monthly_price;
}
if ($google_analytics_id != $settings['google_analytics_id']) {
$settings['google_analytics_id'] = $google_analytics_id;
}
if ($google_ads_id != $settings['google_ads_id']) {
$settings['google_ads_id'] = $google_ads_id;
}
if ($google_conversion_id != $settings['google_conversion_id']) {
$settings['google_conversion_id'] = $google_conversion_id;
}
if ($facebook_pixel_id != $settings['facebook_pixel_id']) {
$settings['facebook_pixel_id'] = $facebook_pixel_id;
}
if ($google_tm_id != $settings['google_tm_id']) {
$settings['google_tm_id'] = $google_tm_id;
}
if ($fb_pixel_via_gtm != $settings['fb_pixel_via_gtm']) {
$settings['fb_pixel_via_gtm'] = $fb_pixel_via_gtm;
}
foreach ($languages as $language) {
if ($top_notify_text[$language['key']] != $settings['top_notify_text'][$language['key']]) {
$settings['top_notify_text'][$language['key']] = $top_notify_text[$language['key']];
}
if ($top_notify_link[$language['key']] != $settings['top_notify_link'][$language['key']]) {
$settings['top_notify_link'][$language['key']] = $top_notify_link[$language['key']];
}
if ($top_notify_link_text[$language['key']] != $settings['top_notify_link_text'][$language['key']]) {
$settings['top_notify_link_text'][$language['key']] = $top_notify_link_text[$language['key']];
}
if ($popup_notify_image[$language['key']] != $settings['popup_notify_image'][$language['key']]) {
$settings['popup_notify_image'][$language['key']] = $popup_notify_image[$language['key']];
}
if ($popup_notify_link[$language['key']] != $settings['popup_notify_link'][$language['key']]) {
$settings['popup_notify_link'][$language['key']] = $popup_notify_link[$language['key']];
}
if ($popup_notify_link_text[$language['key']] != $settings['popup_notify_link_text'][$language['key']]) {
$settings['popup_notify_link_text'][$language['key']] = $popup_notify_link_text[$language['key']];
}
if ($seo_site_name[$language['key']] != $settings['seo_site_name'][$language['key']]) {
$settings['seo_site_name'][$language['key']] = $seo_site_name[$language['key']];
}
if ($seo_organisation_name[$language['key']] != $settings['seo_organisation_name'][$language['key']]) {
$settings['seo_organisation_name'][$language['key']] = $seo_organisation_name[$language['key']];
}
if ($footer_copyright_text[$language['key']] != $settings['footer_copyright_text'][$language['key']]) {
$settings['footer_copyright_text'][$language['key']] = $footer_copyright_text[$language['key']];
}
}
if (!isset($settings['fonts'])) {
$settings['fonts'] = [];
}
foreach ($fonts as $key => $value) {
if (!isset($settings['fonts'][$key])) {
$settings['fonts'][$key] = $value;
}
else if (!is_array($value)) {
if ($value != $settings['fonts'][$key]) {
$settings['fonts'][$key] = $value;
}
}
else {
foreach ($value as $subKey => $subValue) {
if (!isset($settings['fonts'][$key][$subKey]) || $subValue !== $settings['fonts'][$key][$subKey]) {
$settings['fonts'][$key][$subKey] = $subValue;
}
}
}
}
$options = [];
if ($image_sizes && is_array($image_sizes)) {
foreach ($image_sizes as $page => $image_size) {
if ($page == 'page-news') {
$pageSettings = Config::get('pictures/page-news');
}
else if ($page == 'page-articles') {
$pageSettings = Config::get('pictures/page-articles');
}
else if ($page == 'page-references') {
$pageSettings = Config::get('pictures/page-references');
$pageSettings['mockup']['sizing']['width'] = $image_size['sizing'];
$pageSettings['mockup']['sizing']['height'] = false;
$pageSettings['mockup']['thumb']['width'] = $image_size['thumb'];
$pageSettings['mockup']['thumb']['height'] = false;
}
else if ($page == 'software') {
$pageSettings = Config::get('pictures/software');
$pageSettings['mockup']['sizing']['width'] = $image_size['sizing'];
$pageSettings['mockup']['sizing']['height'] = false;
}
$pageSettings['list']['sizing']['width'] = ($page == 'software' ? $image_size['thumb'] : $image_size['sizing']);
$pageSettings['list']['sizing']['height'] = false;
if ($page != 'software') {
$pageSettings['list']['thumb']['width'] = $image_size['thumb'];
$pageSettings['list']['thumb']['height'] = false;
}
$options[$page] = $pageSettings;
}
}
$export = Utility::array_export(Config::set('pictures', $options), ['pwith' => true]);
FileManager::file_write(CONFIG_DIR . 'pictures.php', $export);
return $settings;
}
private function _fonFastCache(string $key, mixed $data = NULL, int $finalMtime = 0, string $filePrefix = ''): mixed
{
$baseDir = (defined('CACHE_DIR') ? CACHE_DIR : (defined('ROOT_DIR') ? ROOT_DIR . 'cache/' : $_SERVER['DOCUMENT_ROOT'] . '/cache/'));
$dir = $baseDir . 'fonbuilder/';
if (!is_dir($dir)) {
@mkdir($dir, 493, true);
@file_put_contents($dir . 'index.php', '<?php // Silence is golden');
}
$prefixPart = ($filePrefix ? $filePrefix . '_' : '');
$file = $dir . $prefixPart . md5($key) . '.json';
if ($data !== null) {
if (isset($data['html']) && !empty($data['html'])) {
$data['html'] = $this->sanitizeOutputUrls($data['html']);
}
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return @file_put_contents($file, $json, LOCK_EX) !== false;
}
else {
if (!file_exists($file)) {
return false;
}
if ((0 < $finalMtime) && filemtime($file) < $finalMtime) {
return false;
}
$content = @file_get_contents($file);
if (!$content) {
return false;
}
$decoded = json_decode($content, true);
return (is_null($decoded) ? false : $decoded);
}
}
private function _injectFreshData(string $html): string
{
$currentTime = Crypt::encode(time(), Config::get('crypt/system'));
$html = preg_replace('/(<input[^>]+name="form_loaded_at"[^>]+value=["\'])([^"\']*)(["\'])/i', '${1}' . $currentTime . '${3}', $html);
$html = preg_replace('/(<input[^>]+name="g-recaptcha-response"[^>]+value=["\'])([^"\']*)(["\'])/i', '${1}${3}', $html);
if (preg_match('/name="(formbuilder_[a-f0-9]{32})"/i', $html, $matches)) {
$honeypotName = $matches[1];
if (class_exists('Session')) {
Session::set('formbuilder_honeypot_name', $honeypotName, true);
}
}
if (preg_match('/name="(formbuilder_[a-f0-9]{32})"/i', $html, $matches)) {
$honeypotName = $matches[1];
if (class_exists('Session')) {
Session::set('formbuilder_honeypot_name', $honeypotName, true);
}
}
if (class_exists('Validation')) {
$targetForms = [
'domain-check' => ['selector' => 'id=["\']checkForm["\']'],
'cfeedback' => ['selector' => 'class=["\'][^"\']*cFeedBackForm[^"\']*["\']'],
'formbuilder_form' => ['selector' => 'class=["\'][^"\']*fon-formbuilder-form[^"\']*["\']']
];
foreach ($targetForms as $tokenKey => $rule) {
$freshTokenTag = Validation::get_csrf_token($tokenKey);
$freshTokenValue = '';
if (preg_match('/value=["\'](.*?)["\']/', $freshTokenTag, $matches)) {
$freshTokenValue = $matches[1];
}
if ($freshTokenValue) {
$pattern = '/(' . $rule['selector'] . '.*?<input[^>]+name=["\'](?:token|csrf_token|_token)["\'][^>]+value=["\'])([^"\']*)(["\'])/is';
$html = preg_replace_callback($pattern, function($m) use($freshTokenValue) {
return $m[1] . $freshTokenValue . $m[3];
}, $html);
}
}
}
return $html;
}
private function _clearFonBuilderCache(): void
{
$baseDir = (defined('CACHE_DIR') ? CACHE_DIR : (defined('ROOT_DIR') ? ROOT_DIR . 'cache/' : $_SERVER['DOCUMENT_ROOT'] . '/cache/'));
$dir = $baseDir . 'fonbuilder/';
if (is_dir($dir)) {
$files = glob($dir . '*.json');
foreach ($files as $file) {
if (is_file($file)) {
@unlink($file);
}
}
}
}
private function sanitizeOutputUrls(string $html_content): string
{
$currentHost = $_SERVER['HTTP_HOST'] ?? '';
if (empty($currentHost)) {
return $html_content;
}
$nakedHost = preg_replace('/^www\\./i', '', $currentHost);
$domains_to_remove = ['https://' . $nakedHost, 'https://www.' . $nakedHost, 'http://' . $nakedHost, 'http://www.' . $nakedHost];
if (defined('APP_URI')) {
$domains_to_remove[] = rtrim(APP_URI, '/');
}
$domains_to_remove = array_unique($domains_to_remove);
$clean_html = str_replace($domains_to_remove, '', $html_content);
return $clean_html;
}
public function builderRow(array $pageContent = [], array $pageData = []): string
{
$currentCurrency = $pageData['selected_currency'] ?? Config::get('general/currency');
$currentLang = Language::selected();
$cacheEnabled = Config::get('theme/cache_pages');
$pageID = (isset($pageData['builder_id']) ? $pageData['builder_id'] : md5(json_encode($pageContent)));
$cacheKey = $pageData['page'] . '_' . $pageID . '_' . $currentLang . '_' . $currentCurrency;
$dbMtime = 0;
if (isset($pageData['builder_mtime'])) {
$dbMtime = (is_numeric($pageData['builder_mtime']) ? $pageData['builder_mtime'] : strtotime($pageData['builder_mtime']));
}
$currencyMtime = Config::get('cronjobs/tasks/auto-currency-rates/last-run-time');
$currencyMtime = strtotime($currencyMtime);
$finalMtime = max($dbMtime, $currencyMtime);
$filePrefix = 'page_' . $pageID;
$cachedData = $this->_fonFastCache($cacheKey, NULL, $finalMtime, $filePrefix);
if ($cachedData !== false && $cacheEnabled) {
if (isset($cachedData['headerCodes']) && !empty($cachedData['headerCodes'])) {
foreach ($cachedData['headerCodes'] as $pPage => $pCode) {
$this->headerCodes = array_merge($this->headerCodes, $cachedData['headerCodes']);
}
}
if (isset($cachedData['styles']) && !empty($cachedData['styles'])) {
$this->styles = array_merge($this->styles, $cachedData['styles']);
}
if (isset($cachedData['scripts']) && !empty($cachedData['scripts'])) {
$this->scripts = array_merge($this->scripts, $cachedData['scripts']);
}
if (isset($cachedData['assets']) && !empty($cachedData['assets'])) {
$this->assets = array_unique(array_merge($this->assets, $cachedData['assets']));
}
$finalHtml = $cachedData['html'];
$finalHtml = $this->_injectFreshData($finalHtml);
return $finalHtml;
}
$output = '';
self::$lcpHandled = false;
if ($pageContent) {
foreach ($pageContent as $row_key => $row) {
if (isset($row->row_hide) && $row->row_hide == '1') {
continue;
}
$rowBg = (isset($row->background_type) && $row->background_type == 2 && isset($row->bg_image) ? $row->bg_image : '');
$rowBgPattern = '';
$rowPatternStyle = '';
$colPatternStyle = [];
$rowClasses = ($row->row_section ? $row->row_section_class . ' ' . $row->text_class_id : $row->text_class);
$rowPatternStyle = $this->handlePatternImages($rowClasses, $pageData['page'], $pageData['tadress'], self::$lcpHandled === false);
if (self::$lcpHandled === false) {
if (!empty($rowBg)) {
$this->addPreloadLink($rowBg, $pageData['page']);
}
}
if ($rowBg) {
$rowBgPattern = 'background-image: url(' . self::assetLinkDetermine($rowBg) . ');';
}
if (isset($row->cols) && is_array($row->cols)) {
foreach ($row->cols as $col_key => $col) {
$colClasses = $col->text_class;
$colPatternStyle[$col->text_class_id] = $this->handlePatternImages($colClasses, $pageData['page'], $pageData['tadress'], self::$lcpHandled === false);
if (self::$lcpHandled === false) {
$colBg = (isset($col->background_type) && $col->background_type == 2 && isset($col->bg_image) ? $col->bg_image : '');
if (!empty($colBg)) {
$this->addPreloadLink($colBg, $pageData['page']);
}
}
}
}
$output .= '<section id="' . ($row->row_section && $row->row_section_id ? $row->row_section_id : $row->text_class_id) . '" class="fon-main-section clearfix ' . ($row->row_section ? $row->row_section_class . ' ' . $row->text_class_id : $row->text_class) . ' ' . ((($row->background_type == 2) || $row->background_type == 3) && $row->overlay_type != '' ? 'overflow-hidden' : '') . ' ' . (($row->background_type == 3) && $row->video_type == 'youtube' ? 'fon-external-video-bg' : '') . '" style="' . $rowPatternStyle . ' ' . $rowBgPattern . '">';
if ($row->background_type == 3) {
if ($row->video_type == 'youtube') {
$output .= '<div class="fon-background-youtube d-none">' . "\n" . ' <iframe class="fon-bg-youtube" src="//www.youtube-nocookie.com/embed/' . $row->video_youtube . '?playlist=' . $row->video_youtube . '&iv_load_policy=3&enablejsapi=1&disablekb=1&autoplay=1&controls=0&showinfo=0&rel=0&loop=1&wmode=transparent&widgetid=1&mute=1" frameborder="0" allowfullscreen></iframe>' . "\n" . ' </div>';
}
else {
$output .= '<div class="fon-background-video">' . "\n" . ' <video class="fon-bg-video" autoplay muted playsinline loop ' . ($row->video_poster ? 'poster="' . static::assetLinkDetermine($row->video_poster) . '"' : '') . '>' . "\n" . ' <source src="' . static::assetLinkDetermine($row->video_local) . '" type="video/mp4">' . "\n" . ' </video>' . "\n" . ' </div>';
}
}
if (($row->background_type == 2) || $row->background_type == 3) {
if ($row->overlay_type != '') {
$output .= '<div class="fon-background-overlay"></div>';
}
}
$output .= '<div class="' . ($row->row_container_fluid == 1 ? 'container-fluid' : 'container') . ' ' . ($row->row_remove_gutter ? ' g-0' : '') . '">';
$rowSectionTitle = (isset($row->row_section_title->{$this->lang}) && $row->row_section_title->{$this->lang} ? $row->row_section_title->{$this->lang} : array_values((array) $row->row_section_title)[0] ?? '');
$rowSectionDesc = (isset($row->row_section_desc->{$this->lang}) && $row->row_section_desc->{$this->lang} ? $row->row_section_desc->{$this->lang} : array_values((array) $row->row_section_desc)[0] ?? '');
if (isset($row->row_section_title_show) && $row->row_section_title_show && $rowSectionTitle || $rowSectionDesc) {
$output .= '<div class="fon-section-title">';
if ($rowSectionTitle) {
$output .= '<h2 class="fon-section-title-heading">' . self::getPriceHolders($rowSectionTitle) . '</h2>';
}
if ($rowSectionDesc) {
$output .= '<p class="fon-section-title-subheading">' . strip_tags(self::getPriceHolders($rowSectionDesc)) . '</p>';
}
$output .= '</div>';
}
$row_animation = '';
if ($row->row_animation_effect) {
$row_animation .= 'data-aos="' . $row->row_animation_effect . '" ';
if ($row->row_animation_offset) {
$row_animation .= 'data-aos-offset="' . $row->row_animation_offset . '" ';
}
if ($row->row_animation_delay) {
$row_animation .= 'data-aos-delay="' . $row->row_animation_delay . '" ';
}
if ($row->row_animation_duration) {
$row_animation .= 'data-aos-duration="' . $row->row_animation_duration . '" ';
}
if ($row->row_animation_transition) {
$row_animation .= 'data-aos-easing="' . $row->row_animation_transition . '" ';
}
if ($row->row_animation_position) {
$row_animation .= 'data-aos-anchor-placement="' . $row->row_animation_position . '" ';
}
}
$output .= '<div class="row ' . $row->text_class . ($row->row_remove_gutter ? ' g-0' : '') . ' ' . (isset($row->row_column_align) && $row->row_column_align ? 'align-items-' . $row->row_column_align : '') . '" ' . $row_animation . '>';
foreach ($row->cols as $col_key => $col) {
$col_animation = '';
if ($col->col_animation_effect) {
$col_animation .= 'data-aos="' . $col->col_animation_effect . '" ';
if ($col->col_animation_offset) {
$col_animation .= 'data-aos-offset="' . $col->col_animation_offset . '" ';
}
if ($col->col_animation_delay) {
$col_animation .= 'data-aos-delay="' . $col->col_animation_delay . '" ';
}
if ($col->col_animation_duration) {
$col_animation .= 'data-aos-duration="' . $col->col_animation_duration . '" ';
}
if ($col->col_animation_transition) {
$col_animation .= 'data-aos-easing="' . $col->col_animation_transition . '" ';
}
if ($col->col_animation_position) {
$col_animation .= 'data-aos-anchor-placement="' . $col->col_animation_position . '" ';
}
}
$columnDisplayClasses = self::generateColumnDisplayClassess($col);
$thisColStyle = (isset($colPatternStyle[$col->text_class_id]) ? $colPatternStyle[$col->text_class_id] : '');
$output .= '<div id="' . $col->text_class_id . '" class="col-' . $col->xs_col . ' col-sm-' . $col->sm_col . ' col-md-' . $col->md_col . ' col-lg-' . $col->lg_col . ' col-xl-' . $col->xl_col . ' ' . ($col->text_class != '' ? $col->text_class : '') . ' ' . (($col->background_type == 2) || $col->background_type == 3 ? 'position-relative' : '') . ' ' . (($col->background_type == 3) && $col->video_type == 'youtube' ? 'fon-external-video-bg' : '') . ' ' . $columnDisplayClasses . '" ' . $col_animation . ' style="' . $thisColStyle . '">';
if ($col->background_type == 3) {
if ($col->video_type == 'youtube') {
$output .= '<div class="fon-background-youtube d-none">' . "\n" . ' <iframe class="fon-bg-youtube" src="//www.youtube-nocookie.com/embed/' . $col->video_youtube . '?playlist=' . $col->video_youtube . '&iv_load_policy=3&enablejsapi=1&disablekb=1&autoplay=1&controls=0&showinfo=0&rel=0&loop=1&wmode=transparent&widgetid=1&mute=1" frameborder="0" allowfullscreen></iframe>' . "\n" . ' </div>';
}
else {
$output .= '<div class="fon-background-video">' . "\n" . ' <video class="fon-bg-video" autoplay muted playsinline loop ' . ($col->video_poster ? 'poster="' . static::assetLinkDetermine($col->video_poster) . '"' : '') . '>' . "\n" . ' <source src="' . static::assetLinkDetermine($col->video_local) . '" type="video/mp4">' . "\n" . ' </video>' . "\n" . ' </div>';
}
}
if (($col->background_type == 2) || $col->background_type == 3) {
if ($col->overlay_type != '') {
$output .= '<div class="fon-background-overlay"></div>';
}
}
$colSectionTitle = (isset($col->col_section_title->{$this->lang}) && $col->col_section_title->{$this->lang} ? $col->col_section_title->{$this->lang} : array_values((array) $col->col_section_title)[0] ?? '');
$colSectionDesc = (isset($col->col_section_desc->{$this->lang}) && $col->col_section_desc->{$this->lang} ? $col->col_section_desc->{$this->lang} : array_values((array) $col->col_section_desc)[0] ?? '');
if (isset($col->col_section_title_show) && $col->col_section_title_show && $colSectionTitle || $colSectionDesc) {
$output .= '<div class="fon-column-title">';
if ($colSectionTitle) {
$output .= '<h3 class="fon-column-title-heading">' . $colSectionTitle . '</h3>';
}
if ($colSectionDesc) {
$output .= '<p class="fon-column-title-subheading">' . strip_tags($colSectionDesc) . '</p>';
}
$output .= '</div>';
}
if ($col->widgets) {
foreach ($col->widgets as $widget) {
if ($widget->content) {
$isWidgetLCP = self::$lcpHandled === false;
$output .= $this->callWidget($pageData, $widget, $row, $isWidgetLCP);
}
}
}
if (isset($col->rows) && $col->rows) {
$row_childs = $col->rows;
$output .= $this->builderChildRow($row_childs, $pageData);
}
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
$output .= '</section>';
self::$lcpHandled = true;
}
}
if (!empty($output) && $cacheEnabled) {
$dataToStore = ['html' => $output, 'headerCodes' => $this->headerCodes, 'styles' => $this->styles, 'assets' => $this->assets, 'scripts' => $this->scripts];
$this->_fonFastCache($cacheKey, $dataToStore, $finalMtime, $filePrefix);
}
else if (!empty($output)) {
$output = $this->sanitizeOutputUrls($output);
}
return $output;
}
public function builderChildRow(mixed $row_childs, array $pageData = []): string
{
$output = '';
if ($row_childs) {
foreach ($row_childs as $rc_row_key => $row_child) {
if (isset($row_child->row_hide) && $row_child->row_hide == '1') {
continue;
}
$row_child_animation = '';
if ($row_child->row_animation_effect) {
$row_child_animation .= 'data-aos="' . $row_child->row_animation_effect . '" ';
if ($row_child->row_animation_offset) {
$row_child_animation .= 'data-aos-offset="' . $row_child->row_animation_offset . '" ';
}
if ($row_child->row_animation_delay) {
$row_child_animation .= 'data-aos-delay="' . $row_child->row_animation_delay . '" ';
}
if ($row_child->row_animation_duration) {
$row_child_animation .= 'data-aos-duration="' . $row_child->row_animation_duration . '" ';
}
if ($row_child->row_animation_transition) {
$row_child_animation .= 'data-aos-easing="' . $row_child->row_animation_transition . '" ';
}
if ($row_child->row_animation_position) {
$row_child_animation .= 'data-aos-anchor-placement="' . $row_child->row_animation_position . '" ';
}
}
$output .= '<div id="' . $row_child->text_class_id . '" class="row ' . ($row_child->row_remove_gutter ? 'g-0' : '') . ' ' . ($row_child->text_class ?? $row_child->text_class) . ' ' . (($row_child->background_type == 2) || $row_child->background_type == 3 ? 'position-relative' : '') . ' ' . (($row_child->background_type == 3) && $row_child->video_type == 'youtube' ? 'fon-external-video-bg' : '') . ' ' . (isset($row_child->row_column_align) && $row_child->row_column_align ? 'align-items-' . $row_child->row_column_align : '') . '" ' . $row_child_animation . '>';
if ($row_child->background_type == 3) {
if ($row_child->video_type == 'youtube') {
$output .= '<div class="fon-background-youtube d-none">' . "\n" . ' <iframe class="fon-bg-youtube" src="//www.youtube-nocookie.com/embed/' . $row_child->video_youtube . '?playlist=' . $row_child->video_youtube . '&iv_load_policy=3&enablejsapi=1&disablekb=1&autoplay=1&controls=0&showinfo=0&rel=0&loop=1&wmode=transparent&widgetid=1&mute=1" frameborder="0" allowfullscreen></iframe>' . "\n" . ' </div>';
}
else {
$output .= '<div class="fon-background-video">' . "\n" . ' <video class="fon-bg-video" autoplay muted playsinline loop ' . ($row_child->video_poster ? 'poster="' . static::assetLinkDetermine($row_child->video_poster) . '"' : '') . '>' . "\n" . ' <source src="' . static::assetLinkDetermine($row_child->video_local) . '" type="video/mp4">' . "\n" . ' </video>' . "\n" . ' </div>';
}
}
if (($row_child->background_type == 2) || $row_child->background_type == 3) {
if ($row_child->overlay_type != '') {
$output .= '<div class="fon-background-overlay"></div>';
}
}
foreach ($row_child->cols as $rc_col_key => $col_child) {
$col_child_animation = '';
if ($col_child->col_animation_effect) {
$col_child_animation .= 'data-aos="' . $col_child->col_animation_effect . '" ';
if ($col_child->col_animation_offset) {
$col_child_animation .= 'data-aos-offset="' . $col_child->col_animation_offset . '" ';
}
if ($col_child->col_animation_delay) {
$col_child_animation .= 'data-aos-delay="' . $col_child->col_animation_delay . '" ';
}
if ($col_child->col_animation_duration) {
$col_child_animation .= 'data-aos-duration="' . $col_child->col_animation_duration . '" ';
}
if ($col_child->col_animation_transition) {
$col_child_animation .= 'data-aos-easing="' . $col_child->col_animation_transition . '" ';
}
if ($col_child->col_animation_position) {
$col_child_animation .= 'data-aos-anchor-placement="' . $col_child->col_animation_position . '" ';
}
}
$colChildDisplayClasses = self::generateColumnDisplayClassess($col_child);
$output .= '<div id="' . $col_child->text_class_id . '" class="col-' . $col_child->xs_col . ' col-sm-' . $col_child->sm_col . ' col-md-' . $col_child->md_col . ' col-lg-' . $col_child->lg_col . ' col-xl-' . $col_child->xl_col . ' ' . ($col_child->text_class != '' ? $col_child->text_class : '') . ' ' . (($col_child->background_type == 2) || $col_child->background_type == 3 ? 'position-relative' : '') . ' ' . (($col_child->background_type == 3) && $col_child->video_type == 'youtube' ? 'fon-external-video-bg' : '') . ' ' . $colChildDisplayClasses . '" ' . $col_child_animation . '>';
if ($col_child->background_type == 3) {
if ($col_child->video_type == 'youtube') {
$output .= '<div class="fon-background-youtube d-none">' . "\n" . ' <iframe class="fon-bg-youtube" src="//www.youtube-nocookie.com/embed/' . $col_child->video_youtube . '?playlist=' . $col_child->video_youtube . '&iv_load_policy=3&enablejsapi=1&disablekb=1&autoplay=1&controls=0&showinfo=0&rel=0&loop=1&wmode=transparent&widgetid=1&mute=1" frameborder="0" allowfullscreen></iframe>' . "\n" . ' </div>';
}
else {
$output .= '<div class="fon-background-video">' . "\n" . ' <video class="fon-bg-video" autoplay muted playsinline loop ' . ($col_child->video_poster ? 'poster="' . static::assetLinkDetermine($col_child->video_poster) . '"' : '') . '>' . "\n" . ' <source src="' . static::assetLinkDetermine($col_child->video_local) . '" type="video/mp4">' . "\n" . ' </video>' . "\n" . ' </div>';
}
}
if (($col_child->background_type == 2) || $col_child->background_type == 3) {
if ($col_child->overlay_type != '') {
$output .= '<div class="fon-background-overlay"></div>';
}
}
$colChildSectionTitle = (isset($col_child->col_section_title->{$this->lang}) && $col_child->col_section_title->{$this->lang} ? $col_child->col_section_title->{$this->lang} : array_values((array) $col_child->col_section_title)[0] ?? '');
$colChildSectionDesc = (isset($col_child->col_section_desc->{$this->lang}) && $col_child->col_section_desc->{$this->lang} ? $col_child->col_section_desc->{$this->lang} : array_values((array) $col_child->col_section_desc)[0] ?? '');
if (isset($col_child->col_section_title_show) && $col_child->col_section_title_show && $colChildSectionTitle || $colChildSectionDesc) {
$output .= '<div class="fon-column-title">';
if ($colChildSectionTitle) {
$output .= '<h3 class="fon-column-title-heading">' . $colChildSectionTitle . '</h3>';
}
if ($colChildSectionDesc) {
$output .= '<p class="fon-column-title-subheading">' . strip_tags($colChildSectionDesc) . '</p>';
}
$output .= '</div>';
}
if ($col_child->widgets) {
foreach ($col_child->widgets as $child_widget) {
if ($child_widget->content) {
$output .= $this->callWidget($pageData, $child_widget, $row_child);
}
}
}
if (isset($col_child->rows) && $col_child->rows) {
$row_childs = $col_child->rows;
$output .= $this->builderChildRow($row_childs, $pageData);
}
$output .= '</div>';
}
$output .= '</div>';
}
}
return $output;
}
public function callWidget(array $pageData, object $widget, object $row, bool $isLCPCandidate = false): string
{
$content = $widget->content;
$funcWidget = $widget->widget . '_widget';
if (method_exists($this, $funcWidget)) {
return $this->{$funcWidget}($content, $widget->module, $pageData, $row, $isLCPCandidate);
}
return $this->callCustomWidgetRenderer($widget, $content, $pageData);
}
private function callCustomWidgetRenderer(object $widget, mixed $content, array $pageData): string
{
$moduleId = (string) ($widget->module ?? '');
$page = (is_array($pageData) && isset($pageData['page']) && is_string($pageData['page']) ? trim($pageData['page']) : '');
if (!isset($widget->widget) || !is_string($widget->widget) || $widget->widget === '') {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => '', 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'widget_name_empty'], '');
return '';
}
$safeWidget = $this->sanitizeCustomWidgetName($widget->widget);
if ($safeWidget === '') {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $widget->widget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'widget_name_invalid'], '');
return '';
}
$rendererFile = $this->resolveCustomWidgetRendererFile($safeWidget);
if ($rendererFile === '') {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_file_not_found'], '');
return '';
}
if (!$this->isCustomWidgetRendererSafe($rendererFile)) {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_security_check_failed'], '');
return '';
}
require_once $rendererFile;
$rendererClass = 'FonCustomWidgetRenderer_' . $safeWidget;
if (!class_exists($rendererClass)) {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_class_not_found'], '');
return '';
}
try {
$renderMethod = new ReflectionMethod($rendererClass, 'render');
if (!$renderMethod->isPublic() || !$renderMethod->isStatic()) {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_method_invalid'], '');
return '';
}
}
catch (ReflectionException $e) {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_reflection_exception'], ['error_message' => $e->getMessage(), 'error_type' => get_class($e)]);
return '';
}
try {
$html = (string) $rendererClass::render($this, $content, $moduleId, (is_array($pageData) ? $pageData : []));
return $html;
}
catch (Throwable $e) {
Modules::save_log('Addons', 'FonPageBuilder', 'WidgetRender', ['widget' => $safeWidget, 'module_id' => $moduleId, 'page' => $page, 'status' => 'error'], ['reason' => 'renderer_exception'], ['renderer_class' => $rendererClass, 'error_message' => $e->getMessage(), 'error_code' => $e->getCode(), 'error_type' => get_class($e), 'error_file' => $e->getFile(), 'error_line' => $e->getLine()]);
return '';
}
}
private function resolveCustomWidgetRendererFile(string $safeWidget): string
{
$basePath = realpath(__DIR__ . DS . 'builder' . DS . 'custom-widgets');
if ($basePath === false) {
return '';
}
$rendererPath = $basePath . DS . $safeWidget . DS . 'renderer.php';
if (!is_file($rendererPath)) {
return '';
}
$rendererRealPath = realpath($rendererPath);
if ($rendererRealPath === false) {
return '';
}
return ($this->isPathInsideDirectory($basePath, $rendererRealPath) ? $rendererRealPath : '');
}
private function isPathInsideDirectory(string $baseDir, string $path): bool
{
$normalizedBase = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $baseDir), DIRECTORY_SEPARATOR);
$normalizedPath = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR);
if (($normalizedBase === '') || $normalizedPath === '') {
return false;
}
if ($normalizedPath === $normalizedBase) {
return true;
}
return strpos($normalizedPath, $normalizedBase . DIRECTORY_SEPARATOR) === 0;
}
private function isCustomWidgetRendererSafe(string $rendererFile): bool
{
static $securityCheckCache = [];
if (isset($securityCheckCache[$rendererFile])) {
return $securityCheckCache[$rendererFile];
}
$code = @file_get_contents($rendererFile);
if ($code === false) {
$securityCheckCache[$rendererFile] = false;
return false;
}
$securityCheckCache[$rendererFile] = !$this->hasForbiddenRendererTokens($code);
return $securityCheckCache[$rendererFile];
}
private function hasForbiddenRendererTokens(string $phpCode): bool
{
$tokens = token_get_all($phpCode);
$forbiddenFunctions = ['eval', 'assert', 'shell_exec', 'exec', 'system', 'passthru', 'proc_open', 'popen'];
$tokenCount = count($tokens);
for ($i = 0; $i < $tokenCount; ++$i) {
$token = $tokens[$i];
if ($token === '`') {
return true;
}
if (!is_array($token)) {
}
else {
if ($token[0] === T_EVAL) {
return true;
}
if (($token[0] === T_STRING) && $this->isForbiddenFunctionCall($tokens, $i, $forbiddenFunctions)) {
return true;
}
}
}
return false;
}
private function isForbiddenFunctionCall(array $tokens, int $index, array $forbiddenFunctions): bool
{
if (!isset($tokens[$index]) || !is_array($tokens[$index])) {
return false;
}
$tokenName = strtolower((string) $tokens[$index][1]);
if (!in_array($tokenName, $forbiddenFunctions, true)) {
return false;
}
$tokenCount = count($tokens);
for ($i = $index + 1; $i < $tokenCount; ++$i) {
$nextToken = $tokens[$i];
if (is_array($nextToken) && in_array($nextToken[0], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], true)) {
}
else {
return $nextToken === '(';
}
}
return false;
}
private function sanitizeCustomWidgetName(mixed $widgetName): string
{
if (!is_string($widgetName)) {
return '';
}
$name = strtolower(trim($widgetName));
if ($name === '') {
return '';
}
return (preg_match('/^[a-z][a-z0-9_]*$/', $name) ? $name : '');
}
private function accordion_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-accordion-widget ' . ($content->dark_container == 'yes' ? 'dark-container' : '') . ' style-' . $content->widget_style . ' ' . $content->fon_class . '">';
if (isset($content->items) && is_array($content->items)) {
$output .= '<div class="accordion" id="accordion-' . $widgetId . '">';
foreach ($content->items as $key => $item) {
$output .= '<div class="accordion-item ' . (($content->show_icon == 'yes') && $item->accordion_icon ? 'with-icon' : 'no-icon') . '">';
$output .= '<div class="accordion-header">';
$output .= '<a class="accordion-button ' . (($key == 0) && $content->first_open == 'yes' ? '' : 'collapsed') . '" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-' . $widgetId . '-' . $key . '" aria-expanded="' . ($key == 0 ? 'true' : 'false') . '" aria-controls="collapse-' . $widgetId . '-' . $key . '">';
if (($content->show_icon == 'yes') && $item->accordion_icon) {
$output .= '<span class="accordion-icon me-1"><i class="' . $item->accordion_icon . '"></i></span>';
}
$accordionTitle = self::getFieldMultilingualText($item->accordion_title ?? NULL, $this->lang, '');
$output .= $accordionTitle;
$output .= '</a>';
$output .= '</div>';
$output .= '<div id="collapse-' . $widgetId . '-' . $key . '" class="accordion-collapse collapse ' . (($key == 0) && $content->first_open == 'yes' ? 'show' : '') . '" data-bs-parent="#accordion-' . $widgetId . '">';
$output .= '<div class="accordion-body">';
$accordionContent = self::getFieldMultilingualText($item->accordion_content ?? NULL, $this->lang, '');
$output .= $accordionContent;
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
private function alert_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (($content->name_widget_status == 'yes') && isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang}) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
if ($content->title_color && $content->alert_type == 'light') {
$style .= 'color: ' . $content->title_color . ';';
}
if ($content->title_margin->top) {
$style .= 'margin-top: ' . $content->title_margin->top . 'px;';
}
if ($content->title_margin->bottom) {
$style .= 'margin-bottom: ' . $content->title_margin->bottom . 'px;';
}
if ($content->title_font) {
$style .= self::parseFontProperties($content->title_font);
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-alert-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$output .= '<div class="alert alert-' . $content->alert_type . ' ' . ($content->show_close ? 'alert-dismissible fade show' : '') . ' ' . ($content->show_icon == 'yes' ? 'd-flex align-items-center' : '') . '" role="alert">';
if (isset($content->show_icon) && $content->show_icon == 'yes') {
$output .= '<div class="alert-icon me-3"><i class="' . $content->icon . ' fa-2x"></i></div>';
$output .= '<div class="alert-content">';
}
if (isset($content->name_widget_status) && $content->name_widget_status == 'yes' && isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang}) {
$output .= '<' . $content->heading_selector . ' class="fon-widget-title alert-heading">';
$output .= $content->name_widget->{$this->lang};
$output .= '</' . $content->heading_selector . '>';
}
if (isset($content->content->{$this->lang}) && $content->content->{$this->lang}) {
$output .= $content->content->{$this->lang};
}
if (isset($content->show_close) && $content->show_close == 'yes') {
$output .= '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="' . $this->language['text_close'] . '"></button>';
}
if (isset($content->show_icon) && $content->show_icon == 'yes') {
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function animated_heading_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$heading_type = (isset($content->heading_type) && $content->heading_type ? $content->heading_type : 'animation');
$heading_layout = (isset($content->heading_layout) && $content->heading_layout ? $content->heading_layout : 'inline');
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$heading_font = (isset($content->heading_font) && $content->heading_font ? $content->heading_font : '');
$heading_color = (isset($content->heading_color) && $content->heading_color ? $content->heading_color : '#000000');
$heading_margin = (isset($content->heading_margin) && $content->heading_margin ? $content->heading_margin : '');
$heading_padding = (isset($content->heading_padding) && $content->heading_padding ? $content->heading_padding : '');
$heading_align = (isset($content->heading_align) && $content->heading_align ? $content->heading_align : (object) ['xl' => 'left', 'lg' => 'left', 'md' => 'left', 'sm' => 'left', 'xs' => 'left']);
$heading_align_class = $this->_parseResponsiveBootstrapFlexAligns($heading_align);
$animated_text_color = (isset($content->animated_text_color) && $content->animated_text_color ? $content->animated_text_color : '#3366FF');
$animated_text_font = (isset($content->animated_text_font) && $content->animated_text_font ? $content->animated_text_font : '');
$animation_effect = (isset($content->animation_effect) && $content->animation_effect ? $content->animation_effect : 'blinds');
$highlight_shape = (isset($content->highlight_shape) && $content->highlight_shape ? $content->highlight_shape : 'circle');
$shape_color = (isset($content->shape_color) && $content->shape_color ? $content->shape_color : '#3366FF');
$shape_width = (isset($content->shape_width) && $content->shape_width ? $content->shape_width : '');
$shape_rounded_edge = (isset($content->shape_rounded_edge) && $content->shape_rounded_edge == 'yes' ? true : false);
$animation_duration = (isset($content->animation_duration) && $content->animation_duration ? (string) $content->animation_duration : '10');
$iteration_count = (isset($content->iteration_count) && $content->iteration_count ? (string) $content->iteration_count : '2');
$heading_before = '';
if (is_object($content->heading_before)) {
$heading_before = (isset($content->heading_before->{$this->lang}) && $content->heading_before->{$this->lang} ? $content->heading_before->{$this->lang} : array_values((array) $content->heading_before)[0] ?? '');
}
else if (is_string($content->heading_before)) {
$heading_before = $content->heading_before;
}
$name_widget = '';
if (is_object($content->name_widget)) {
$name_widget = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
}
else if (is_string($content->name_widget)) {
$name_widget = $content->name_widget;
}
$heading_after = '';
if (is_object($content->heading_after)) {
$heading_after = (isset($content->heading_after->{$this->lang}) && $content->heading_after->{$this->lang} ? $content->heading_after->{$this->lang} : array_values((array) $content->heading_after)[0] ?? '');
}
else if (is_string($content->heading_after)) {
$heading_after = $content->heading_after;
}
$animated_text = '';
if (is_object($content->animated_text)) {
$animated_text = (isset($content->animated_text->{$this->lang}) && $content->animated_text->{$this->lang} ? $content->animated_text->{$this->lang} : array_values((array) $content->animated_text)[0] ?? '');
}
else if (is_string($content->animated_text)) {
$animated_text = $content->animated_text;
}
if ($animated_text) {
if (str_contains($animated_text, ',')) {
$animated_text = explode(',', $animated_text);
}
else {
$animated_text = [$animated_text];
}
}
else {
$animated_text = [];
}
$highlight_text = '';
if (is_object($content->highlight_text)) {
$highlight_text = (isset($content->highlight_text->{$this->lang}) && $content->highlight_text->{$this->lang} ? $content->highlight_text->{$this->lang} : array_values((array) $content->highlight_text)[0] ?? '');
}
else if (is_string($content->highlight_text)) {
$highlight_text = $content->highlight_text;
}
$style = '';
if ($heading_color || $heading_font) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
if ($heading_font) {
$style .= self::parseFontProperties($heading_font);
}
if ($heading_color) {
$style .= 'color: ' . $heading_color . ';';
}
$style .= '}';
}
if ($heading_margin) {
$responsiveItems = [
'.fon-widget-title' => [
['type' => 'margin', 'unit' => '', 'value' => $heading_margin]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
if ($heading_padding) {
$responsiveItems = [
'.fon-widget-title' => [
['type' => 'padding', 'unit' => '', 'value' => $heading_padding]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
if ($animated_text_color || $animated_text_font) {
$style .= '#' . $widgetId . ' .animated-text, #' . $widgetId . ' .animated-head-highlighted-text{';
if ($animated_text_font) {
$style .= self::parseFontProperties($animated_text_font);
}
if ($animated_text_color) {
$style .= 'color: ' . $animated_text_color . ';';
}
$style .= '}';
}
if (($heading_type == 'highlight') && $shape_color || $shape_width || $shape_rounded_edge) {
$style .= '#' . $widgetId . ' .animated-head-highlighted-wrap svg path{';
if ($shape_width) {
$style .= 'stroke-width: ' . $shape_width . 'px;';
}
if ($shape_rounded_edge) {
$style .= 'stroke-linecap: round;';
$style .= 'stroke-linejoin: round;';
}
if ($shape_color) {
$style .= 'stroke: ' . $shape_color . ';';
}
if ($animation_duration) {
$style .= '-webkit-animation-duration: ' . $animation_duration . 's;';
$style .= 'animation-duration: ' . $animation_duration . 's;';
}
if ($iteration_count) {
$style .= '-webkit-animation-iteration-count: ' . $iteration_count . ';';
$style .= 'animation-iteration-count: ' . $iteration_count . ';';
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isHaveAnimatedText = ($heading_type == 'animation') && $animated_text;
if ($isHaveAnimatedText) {
$animated_text_class = 'animated-head-text ';
if ($animation_effect) {
switch ($animation_effect) {
case 'blinds':
$animated_text_class .= 'letters animation-blinds';
break;
case 'typing':
$animated_text_class .= 'letters type';
break;
case 'flip':
$animated_text_class .= 'text-animation-flip';
break;
case 'fade':
$animated_text_class .= 'zoom';
break;
case 'loading':
$animated_text_class .= 'loading-bar';
break;
case 'scale':
$animated_text_class .= 'letters scale';
break;
case 'slide':
$animated_text_class .= 'slide';
break;
case 'push':
$animated_text_class .= 'push';
break;
case 'wave':
$animated_text_class .= 'letters animation-wave';
break;
case 'clip':
$animated_text_class .= 'text-clip is-full-width';
break;
default:
$animated_text_class .= 'letters type';
break;
}
}
}
$isHaveHighlightText = ($heading_type == 'highlight') && $highlight_text;
if ($isHaveHighlightText) {
$highlight_shape_content = '';
if ($highlight_shape) {
switch ($highlight_shape) {
case 'cross':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none" style="z-index: 2">' . "\n" . ' <path d="M497.4,23.9C301.6,40,155.9,80.6,4,144.4"></path>' . "\n" . ' <path d="M14.1,27.6c204.5,20.3,393.8,74,467.3,111.7"></path>' . "\n" . ' </svg>';
break;
case 'circle':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M325,18C228.7-8.3,118.5,8.3,78,21C22.4,38.4,4.6,54.6,5.6,77.6c1.4,32.4,52.2,54,142.6,63.7 c66.2,7.1,212.2,7.5,273.5-8.3c64.4-16.6,104.3-57.6,33.8-98.2C386.7-4.9,179.4-1.4,126.3,20.7">' . "\n\t\t\t\t\t\t" . '</path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'bg-fill':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n" . ' <path fill="none" stroke="#020202" stroke-width="150" stroke-miterlimit="10" d="M0 75h500"/>' . "\n" . ' </svg>';
break;
case 'square':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t" . '<path d="M44.22 0c2.46 51.77-2.05 99.72-13.51 143.84 50.37-7.64 316.96-30.55 469.29-5.09-16.41-40.58-21.99-71.11-23.34-127.29C378.38 22.92 97.06 34.37 0 22.92"/>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'scribble-underline':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M9.3,127.3c49.3-3,150.7-7.6,199.7-7.4c121.9,0.4,189.9,0.4,282.3,7.2C380.1,129.6,181.2,130.6,70,139 c82.6-2.9,254.2-1,335.9,1.3c-56,1.4-137.2-0.3-197.1,9"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'diagonal':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none" style="z-index: 2">' . "\n\t\t\t\t\t\t" . '<path d="M13.5,15.5c131,13.7,289.3,55.5,475,125.5"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'top-bottom-line':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M8.4,143.1c14.2-8,97.6-8.8,200.6-9.2c122.3-0.4,287.5,7.2,287.5,7.2"></path>' . "\n\t\t\t\t\t\t" . '<path d="M8,19.4c72.3-5.3,162-7.8,216-7.8c54,0,136.2,0,267,7.8"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'strikethrough':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none" style="z-index: 2">' . "\n\t\t\t\t\t\t" . '<path d="M3,75h493.5"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'underline':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M7.7,145.6C109,125,299.9,116.2,401,121.3c42.1,2.2,87.6,11.8,87.3,25.7"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'duble-underline':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M5,125.4c30.5-3.8,137.9-7.6,177.3-7.6c117.2,0,252.2,4.7,312.7,7.6"></path>' . "\n\t\t\t\t\t\t" . '<path d="M26.9,143.8c55.1-6.1,126-6.3,162.2-6.1c46.5,0.2,203.9,3.2,268.9,6.4"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'zigzag-underline':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t" . '<path d="M.23 139.83l28.27-19.78 25.43 19.79 28.27-19.77 22.6 19.79 29.68-19.78 25.44 19.79 25.44-19.78 28.27 19.79 26.85-19.77 26.84 19.8 24.04-19.79 24.01 19.8 22.62-19.78 22.61 19.8 22.61-19.78 24.02 19.79 24.03-19.78 24.02 19.8 22.62-19.79 21.19 19.79"/>' . "\n\t\t\t\t\t" . '</svg>';
break;
case 'wave':
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M3,146.1c17.1-8.8,33.5-17.8,51.4-17.8c15.6,0,17.1,18.1,30.2,18.1c22.9,0,36-18.6,53.9-18.6 c17.1,0,21.3,18.5,37.5,18.5c21.3,0,31.8-18.6,49-18.6c22.1,0,18.8,18.8,36.8,18.8c18.8,0,37.5-18.6,49-18.6c20.4,0,17.1,19,36.8,19 c22.9,0,36.8-20.6,54.7-18.6c17.7,1.4,7.1,19.5,33.5,18.8c17.1,0,47.2-6.5,61.1-15.6"></path>' . "\n\t\t\t\t\t" . '</svg>';
break;
default:
$highlight_shape_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 150" preserveAspectRatio="none">' . "\n\t\t\t\t\t\t" . '<path d="M325,18C228.7-8.3,118.5,8.3,78,21C22.4,38.4,4.6,54.6,5.6,77.6c1.4,32.4,52.2,54,142.6,63.7 c66.2,7.1,212.2,7.5,273.5-8.3c64.4-16.6,104.3-57.6,33.8-98.2C386.7-4.9,179.4-1.4,126.3,20.7">' . "\n\t\t\t\t\t\t" . '</path>' . "\n\t\t\t\t\t" . '</svg>';
break;
}
}
}
$this->addAsset('fon-animated-head');
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-animated-heading-widget ' . ($content->fon_class ?? '') . '">';
if (DEMO_MODE) {
$output .= '<h3 class="fs-6 border-bottom py-3 mb-3">' . $name_widget . '</h3>';
}
$output .= '<div class="fon-widget-animated-head">';
$output .= '<' . $heading_selector . ' class="fon-widget-title layout-' . $heading_layout . ' align-items-start align-items-md-center ' . ($isHaveAnimatedText ? $animated_text_class : 'highlighted-text') . ' ' . $heading_align_class . '">';
$output .= '<span class="animated-head-before-part">' . $heading_before . '</span>';
if ($isHaveAnimatedText) {
$output .= '<span class="animated-text-words-wrapper">';
foreach ($animated_text as $key => $text) {
$output .= '<span class="animated-text ' . ($key == 0 ? 'is-visible' : '') . '">' . $text . '</span>';
}
$output .= '</span>';
}
if ($isHaveHighlightText) {
$output .= '<span class="animated-head-highlighted-wrap">';
$output .= '<span class="animated-head-highlighted-text shape-' . $highlight_shape . '">' . $highlight_text . '</span>';
$output .= $highlight_shape_content;
$output .= '</span>';
}
$output .= '<span class="animated-head-after-part">' . $heading_after . '</span>';
$output .= '</' . $heading_selector . '>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function animated_number_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$title = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
$desc = (isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : array_values((array) $content->content)[0] ?? '');
$style = '';
$style .= '#' . $widgetId . ' .animated-number .number{';
if (isset($content->number_size) && $content->number_size) {
$style .= 'font-size:' . $content->number_size . 'px;';
}
if (isset($content->number_weight) && $content->number_weight) {
$style .= 'font-weight:' . $content->number_weight . ';';
}
if (isset($content->number_color) && $content->number_color) {
$style .= 'color:' . $content->number_color . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .animated-number .number:' . $content->number_prefix_position . '{';
$style .= 'content: "' . $content->number_prefix . '";';
$style .= '}';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$attributes = '';
$counterClass = '';
$counterData = '';
$counterContent = '';
$icon_class = (isset($content->icon_class) && $content->icon_class ? $content->icon_class : '');
if ($content->number_counter_type == 'counter') {
$counterClass = 'counter counter-number';
$counterData = 'data-speed="' . ($content->number_animation_speed ?? '7000') . '" data-to="' . $content->number . '"';
$counterData .= (is_float($content->number) ? ' data-decimal="1"' : '');
}
else if ($content->number_counter_type == 'vertical') {
$counterClass = 'vertical-counter appear ';
$counterData = 'data-to="' . $content->number . '"';
$counterNumbers = str_split($content->number);
foreach ($counterNumbers as $number) {
$counterContent .= '<span class="vertical-counter-number" data-to="' . $number . '" ><ul class="list-unstyled"><li class="vcn">0</li><li class="vcn">1</li><li class="vcn">2</li><li class="vcn">3</li><li class="vcn">4</li><li class="vcn">5</li><li class="vcn">6</li><li class="vcn">7</li><li class="vcn">8</li><li class="vcn">9</li></ul></span>';
}
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-animated-number-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'animated_number' . DS . 'style_' . $content->widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function articles_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetPages($content, $moduleId, $pageData, 'articles');
}
private function banner_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : '1');
$image = '';
if (is_object($content->image)) {
$image = (isset($content->image->{$this->lang}) && $content->image->{$this->lang} ? $content->image->{$this->lang} : array_values((array) $content->image)[0] ?? '');
}
else if (is_string($content->image)) {
$image = $content->image;
}
$image_src = ($image ? static::assetLinkDetermine($image) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($image_src, $pageData['badress']);
$overlay_type = (isset($content->overlay_type) && $content->overlay_type ? $content->overlay_type : 'none');
$image_overlay = ($overlay_type != 'none' ? true : false);
$title = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$description = (isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : array_values((array) $content->content)[0] ?? '');
$tag = (isset($content->tag->{$this->lang}) && $content->tag->{$this->lang} ? $content->tag->{$this->lang} : array_values((array) $content->tag)[0] ?? '');
$icon = (isset($content->icon) && $content->icon ? $content->icon : '');
$link = (isset($content->link) && $content->link ? $content->link : '');
$link_target = (isset($content->link_target) && $content->link_target ? $content->link_target : '_blank');
$link_rel = (isset($content->link_rel) && $content->link_rel ? $content->link_rel : []);
$link_rel = ($link_rel ? ' rel="' . implode(' ', $link_rel) . '" ' : '');
$show_button = (isset($content->show_button) && $content->show_button == 'yes' ? true : false);
$button_text = (isset($content->button_text->{$this->lang}) && $content->button_text->{$this->lang} ? $content->button_text->{$this->lang} : array_values((array) $content->button_text)[0] ?? '');
$show_button_icon = (isset($content->show_button_icon) && $content->show_button_icon == 'yes' ? true : false);
$button_icon = (isset($content->button_icon) && $content->button_icon ? $content->button_icon : '');
$button_icon_position = (isset($content->button_icon_position) && $content->button_icon_position ? $content->button_icon_position : 'right');
$image_alt = (isset($content->image_alt->{$this->lang}) && $content->image_alt->{$this->lang} ? $content->image_alt->{$this->lang} : (isset($content->image_alt) ? array_values((array) $content->image_alt)[0] ?? '' : ''));
$image_title = (isset($content->image_title->{$this->lang}) && $content->image_title->{$this->lang} ? $content->image_title->{$this->lang} : (isset($content->image_title) ? array_values((array) $content->image_title)[0] ?? '' : ''));
if (empty($image_alt)) {
if (!empty($title)) {
$image_alt = $title;
}
else if (!empty($image_title)) {
$image_alt = $image_title;
}
else {
$image_alt = basename($image_src);
}
}
if (empty($image_title)) {
if (!empty($title)) {
$image_title = $title;
}
else if (!empty($image_alt)) {
$image_title = $image_alt;
}
else {
$image_title = basename($image_src);
}
}
$style = '';
if ($image_overlay) {
$style .= '#' . $widgetId . '.fon-banner-widget{';
if ($overlay_type == 'color') {
$style .= (isset($content->color_overlay->normal) && $content->color_overlay->normal ? '--bs-bg-overlay-color:' . $content->color_overlay->normal . ';' : '');
$style .= (isset($content->color_overlay->hover) && $content->color_overlay->hover ? '--bs-bg-overlay-hover-color:' . $content->color_overlay->hover . ';' : '');
}
if ($overlay_type == 'gradient') {
$style .= (isset($content->gradient_overlay->normal) && $content->gradient_overlay->normal ? self::parseGradient($content->gradient_overlay->normal, 'bg-overlay') : '');
$style .= (isset($content->gradient_overlay->hover) && $content->gradient_overlay->hover ? self::parseGradient($content->gradient_overlay->hover, 'bg-overlay-hover') : '');
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-banner-widget style-' . $widget_style . ' overlay-' . $overlay_type . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'banner' . DS . 'style_' . $content->widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function bank_account_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$class = (isset($content->fon_class) && $content->fon_class ? $content->fon_class : '');
$show_title = (isset($content->show_name) && $content->show_name == 'yes' ? true : false);
$show_logo = (isset($content->show_logo) && $content->show_logo == 'yes' ? true : false);
$title = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
$owner = (isset($content->owner) && $content->owner ? $content->owner : '');
$iban = (isset($content->iban) && $content->iban ? $content->iban : '');
$swift = (isset($content->swift) && $content->swift ? $content->swift : '');
$number = (isset($content->number) && $content->number ? $content->number : '');
$branch = (isset($content->branch) && $content->branch ? $content->branch : '');
$widget_style = (isset($content->style) && $content->style ? $content->style : 'horizontal');
$logo = (isset($content->logo) && $content->logo ? $content->logo : '');
$logo_src = ($logo ? static::assetLinkDetermine($logo) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($logo_src, $pageData['badress']);
$moduleLang = Modules::Lang('Payment', 'BankTransfer', Language::selected());
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="card fon-bank-account rounded-4 bg-theme-light border-0 mb-4 ' . $class . '">';
$output .= '<div class="row g-0 align-items-center justify-content-center">';
if ($show_logo && $logo) {
$output .= '<div class="col-md-' . ($widget_style == 'horizontal' ? '4' : '12') . '">';
$output .= '<div class="h-100 rounded-4 d-flex flex-column justify-content-center align-items-center">';
if ($enableLazyLoading) {
$output .= '<img class="card-image img-fluid" loading="lazy" decoding="async" src="' . $logo_src . '" alt="' . $title . '" style="' . ($widget_style == 'horizontal' ? 'max-width:80%' : 'max-height:150px') . '" ' . $imageDimensions . '/>';
}
else {
$output .= '<img class="card-image img-fluid" src="' . $logo_src . '" alt="' . $title . '" style="' . ($widget_style == 'horizontal' ? 'max-width:80%' : 'max-height:150px') . '" ' . $imageDimensions . '/>';
}
$output .= '</div>';
$output .= '</div>';
}
$output .= '<div class="col-md-' . (($widget_style == 'horizontal') && $show_logo && $logo ? '8' : '12') . '">';
$output .= '<div class="card-body">';
if ($show_title && $title) {
$output .= '<h5 class="card-title">' . $title . '</h5>';
}
$output .= '<ul class="list-group rounded-4 list-group-flush">';
$output .= '<li class="list-group-item d-flex flex-column flex-sm-row align-items-start align-items-sm-center justify-content-between">';
$output .= '<strong class="text-start flex-shrink-0 d-flex">' . $moduleLang['account-buyer-name'] . ' :</strong>';
$output .= '<span class="text-start text-sm-end d-flex flex-grow-1 align-items-center justify-content-between justify-content-sm-end w-100">' . $owner . ' <button type="button" data-text="' . $owner . '" data-bs-toggle="tooltip" data-bs-title="' . ___('needs/copy') . '" class="btn btn-link btn-copy p-0 ms-2 shadow-none"><i class="fa-regular fa-copy"></i></button></span>';
$output .= '</li>';
$output .= '<li class="list-group-item d-flex flex-column flex-sm-row align-items-start align-items-sm-center justify-content-between">';
$output .= '<strong class="text-start flex-shrink-0 d-flex">' . $moduleLang['account-iban'] . ' :</strong>';
$output .= '<span class="text-start text-sm-end d-flex flex-grow-1 align-items-center justify-content-between justify-content-sm-end w-100">' . $iban . ' <button type="button" data-text="' . $iban . '" data-bs-toggle="tooltip" data-bs-title="' . ___('needs/copy') . '" class="btn btn-link btn-copy p-0 ms-2 shadow-none"><i class="fa-regular fa-copy"></i></button></span>';
$output .= '</li>';
if ($swift) {
$output .= '<li class="list-group-item d-flex flex-column flex-sm-row align-items-start align-items-sm-center justify-content-between">';
$output .= '<strong class="text-start flex-shrink-0 d-flex">' . $moduleLang['account-swift'] . ' :</strong>';
$output .= '<span class="text-start text-sm-end d-flex flex-grow-1 align-items-center justify-content-between justify-content-sm-end w-100">' . $swift . ' <button type="button" data-text="' . $swift . '" data-bs-toggle="tooltip" data-bs-title="' . ___('needs/copy') . '" class="btn btn-link btn-copy p-0 ms-2 shadow-none"><i class="fa-regular fa-copy"></i></button></span>';
$output .= '</li>';
}
if ($number) {
$output .= '<li class="list-group-item d-flex flex-column flex-sm-row align-items-start align-items-sm-center justify-content-between">';
$output .= '<strong class="text-start flex-shrink-0 d-flex">' . $moduleLang['account-number'] . ' :</strong>';
$output .= '<span class="text-start text-sm-end d-flex flex-grow-1 align-items-center justify-content-between justify-content-sm-end w-100">' . $number . ' <button type="button" data-text="' . $number . '" data-bs-toggle="tooltip" data-bs-title="' . ___('needs/copy') . '" class="btn btn-link btn-copy p-0 ms-2 shadow-none"><i class="fa-regular fa-copy"></i></button></span>';
$output .= '</li>';
}
if ($branch) {
$output .= '<li class="list-group-item d-flex flex-column flex-sm-row align-items-start align-items-sm-center justify-content-between">';
$output .= '<strong class="text-start flex-shrink-0 d-flex">' . $moduleLang['account-branch-nc'] . ' :</strong>';
$output .= '<span class="text-start text-sm-end d-flex flex-grow-1 align-items-center justify-content-between justify-content-sm-end w-100">' . $branch . ' <button type="button" data-text="' . $branch . '" data-bs-toggle="tooltip" data-bs-title="' . ___('needs/copy') . '" class="btn btn-link btn-copy p-0 ms-2 shadow-none"><i class="fa-regular fa-copy"></i></button></span>';
$output .= '</li>';
}
$output .= '</ul>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function button_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
$aligns = (isset($content->align) && $content->align ? $content->align : NULL);
foreach ($aligns as $k => $v) {
if ($v == 'left') {
$aligns->{$k} = 'start';
}
else if ($v == 'right') {
$aligns->{$k} = 'end';
}
}
$output = '';
if (isset($content->items) && is_array($content->items)) {
$buttonCount = count($content->items);
if (1 < $buttonCount) {
if (isset($content->gap) && $content->gap) {
$style .= '#' . $widgetId . ' .fon-widget-button-group .btn{';
$style .= 'margin: ' . $content->gap . 'px';
$style .= '}';
}
}
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-button-widget ' . $content->fon_class . '">';
$output .= $this->parseButtons($content->items, $moduleId, $pageData, $aligns);
$output .= '</div>';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
return $output;
}
private function calltoaction_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceHolder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$bg_type = (isset($content->bg_type) && $content->bg_type ? $content->bg_type : 'none');
$bg_image = '';
if (is_object($content->bg_image)) {
$bg_image = (isset($content->bg_image->{$this->lang}) && $content->bg_image->{$this->lang} ? $content->bg_image->{$this->lang} : array_values((array) $content->bg_image)[0] ?? '');
}
else if (is_string($content->bg_image)) {
$bg_image = $content->bg_image;
}
$bg_image_src = ($bg_image ? static::assetLinkDetermine($bg_image) : $lazyPlaceHolder);
$overlay_type = (isset($content->overlay_type) && $content->overlay_type ? $content->overlay_type : 'none');
$bg_overlay = ($overlay_type != 'none' ? true : false);
$bg_color = (isset($content->bg_color) && $content->bg_color ? $content->bg_color : '');
$bg_color_overlay = (isset($content->color_overlay) && $content->color_overlay ? $content->color_overlay : '');
$bg_gradient = (isset($content->bg_gradient) && $content->bg_gradient ? $content->bg_gradient : '');
$bg_gradient_overlay = (isset($content->gradient_overlay) && $content->gradient_overlay ? $content->gradient_overlay : '');
$button_position = (isset($content->button_position) && $content->button_position ? $content->button_position : 'right');
$align = (isset($content->align) && $content->align ? $content->align : '');
$padding = (isset($content->padding) && $content->padding ? $content->padding : '');
$use_border = (isset($content->use_border) && $content->use_border == 'yes' ? true : false);
$border = (isset($content->border) && $content->border ? $content->border : '');
$border_radius = (isset($content->border_radius) && $content->border_radius ? $content->border_radius : '');
$shadow = (isset($content->shadow) && $content->shadow ? $content->shadow : '');
$title = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$title_font = (isset($content->title_font) && $content->title_font ? $content->title_font : '');
$title_color = (isset($content->title_color) && $content->title_color ? $content->title_color : '');
$description = (isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : array_values((array) $content->content)[0] ?? '');
$description_font = (isset($content->content_font) && $content->content_font ? $content->content_font : '');
$description_color = (isset($content->content_color) && $content->content_color ? $content->content_color : '');
$show_icon = (isset($content->show_icon) && $content->show_icon == 'yes' ? true : false);
$icon = (isset($content->icon) && $content->icon ? $content->icon : '');
$icon_size = (isset($content->icon_size) && $content->icon_size ? $content->icon_size : '');
$icon_color = (isset($content->icon_color) && $content->icon_color ? $content->icon_color : '');
$style = '';
$style .= '#' . $widgetId . '{';
if ($bg_type != 'none') {
if (($bg_type == 'color') && $bg_color) {
$style .= 'background-color: ' . $bg_color . ';';
}
else if (($bg_type == 'gradient') && $bg_gradient) {
$style .= 'background-image: ' . self::parseGradient($bg_gradient) . ';';
}
else if (($bg_type == 'image') && $bg_image) {
$style .= 'background-image: url(' . $bg_image_src . ');';
}
}
if ($padding) {
$style .= 'padding: ' . $padding . 'px;';
}
if ($use_border && $border) {
$style .= 'border: ' . $border . ';';
}
if ($border_radius) {
$style .= 'border-radius: ' . $border_radius . 'px;';
}
if ($shadow) {
$style .= 'box-shadow: ' . $shadow . ';';
}
$style .= '}';
if (($button_position == 'bottom') && $align != 'center') {
$responsiveItems = [
'.fon-widget-content' => [
['type' => 'width', 'unit' => '%', 'value' => $content->width]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
if (($bg_type == 'image') && $bg_overlay && $bg_color_overlay || $bg_gradient_overlay) {
$style .= '#' . $widgetId . ' .fon-calltoaction-overlay{';
$style .= (($overlay_type == 'color') && $bg_color_overlay ? 'background-color:' . $bg_color_overlay . ';' : '');
$style .= (($overlay_type == 'gradient') && $bg_gradient_overlay ? self::parseGradient($bg_gradient_overlay) : '');
if ($border_radius) {
$style .= 'border-radius: ' . $border_radius . 'px;';
}
$style .= '}';
}
$style .= '#' . $widgetId . ' .fon-calltoaction-title{';
$style .= ($title_font ? self::parseFontProperties($title_font) : '');
$style .= ($title_color ? 'color: ' . $title_color . ';' : '');
$style .= '}';
$style .= '#' . $widgetId . ' .fon-calltoaction-description{';
$style .= ($description_font ? self::parseFontProperties($description_font) : '');
$style .= ($description_color ? 'color: ' . $description_color . ';' : '');
$style .= '}';
if ($show_icon && $icon) {
$style .= '#' . $widgetId . ' .fon-calltoaction-icon i{';
$style .= ($icon_color ? 'color: ' . $icon_color . ';' : '');
$style .= ($icon_size ? 'font-size: ' . $icon_size . 'px;' : '');
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
if (!is_object($align) && $align != '') {
$align = new stdClass();
$textAlign = '';
switch ($align) {
case 'left':
$textAlign = 'start';
break;
case 'center':
$textAlign = 'center';
break;
case 'right':
$textAlign = 'end';
break;
}
$align->xs = $align->sm = $align->md = $align->lg = $align->xl = $textAlign;
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-calltoaction-widget bg-cover buttons-' . $button_position . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-calltoaction-overlay position-absolute w-100 h-100 top-0 start-0"></div>';
$output .= '<div class="fon-widget-content position-relative ' . ($button_position == 'right' ? 'row g-0 align-items-center ' : '') . '">';
if ($show_icon && $icon) {
$output .= '<div class="fon-calltoaction-icon ' . ($button_position == 'right' ? 'col-12 col-md-1 text-center align-self-start' : 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl) . '">';
$output .= '<i class="' . $icon . ' ' . ($button_position == 'right' ? 'm-2 ' : 'my-2') . '"></i>';
$output .= '</div>';
}
if ($title || $description) {
$output .= '<div class="fon-calltoaction-inner-content ' . ($button_position == 'right' ? 'col-12 col-md-8' : 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl) . '">';
if ($title) {
$output .= '<' . $heading_selector . ' class="fon-calltoaction-title ' . ($button_position == 'right' ? 'text-center text-md-start' : 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl) . '">' . strip_tags($title) . '</' . $heading_selector . '>';
}
if ($description) {
$output .= '<p class="fon-calltoaction-description ' . ($button_position == 'right' ? 'text-center text-md-start' : 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl) . '">' . strip_tags($description) . '</p>';
}
$output .= '</div>';
}
if (isset($content->buttons) && is_array($content->buttons) && $content->buttons) {
$output .= '<div class="fon-calltoaction-buttons ' . ($button_position == 'right' ? 'col-12 col-md-' . ($show_icon && $icon ? '3' : '4') . ' text-center text-md-end' : 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl) . '">';
$output .= $this->parseButtons($content->buttons, $moduleId, $pageData, $align);
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function campaign_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$mediaType = (isset($content->media_type) && $content->media_type ? $content->media_type : 'icon');
$useCoupon = (isset($content->use_coupon) && $content->use_coupon == 'yes' ? true : false);
$useCountdown = (isset($content->use_countdown) && $content->use_countdown == 'yes' ? true : false);
if (isset($content->campaign_message)) {
$campaign_message = (isset($content->campaign_message->{$this->lang}) && $content->campaign_message->{$this->lang} ? $content->campaign_message->{$this->lang} : array_values((array) $content->campaign_message)[0] ?? '');
}
else {
$campaign_message = '';
}
$dateLangs = ['day' => ___('date/day'), 'hour' => ___('date/hour'), 'minute' => ___('date/minute'), 'second' => ___('date/second')];
$carouselData = '';
$columns = [];
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel campaign-carousel';
}
else {
$columns = $content->column;
$containerClass = (1 < count($content->items) ? 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl . ' g-3' : '');
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-campaign-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content ' . $containerClass . '" ' . $carouselData . '>';
if (isset($content->items) && is_array($content->items)) {
foreach ($content->items as $ikey => $item) {
if ($mediaType == 'image') {
if ($item->campaign_image) {
$item->campaign_image = static::assetLinkDetermine($item->campaign_image);
}
else {
$item->campaign_image = $lazyPlaceholder;
}
$imageDimensions = static::getImageDimensions($item->campaign_image, $pageData['badress']);
}
$campaign_name = (isset($item->campaign_name->{$this->lang}) && $item->campaign_name->{$this->lang} ? $item->campaign_name->{$this->lang} : array_values((array) $item->campaign_name)[0] ?? '');
$campaign_link = (isset($item->campaign_link->{$this->lang}) && $item->campaign_link->{$this->lang} ? $item->campaign_link->{$this->lang} : array_values((array) $item->campaign_link)[0] ?? '');
$campaign_tag = (isset($item->campaign_tag->{$this->lang}) && $item->campaign_tag->{$this->lang} ? $item->campaign_tag->{$this->lang} : array_values((array) $item->campaign_tag)[0] ?? '');
if (isset($item->campaign_desc)) {
$campaign_desc = (isset($item->campaign_desc->{$this->lang}) && $item->campaign_desc->{$this->lang} ? $item->campaign_desc->{$this->lang} : array_values((array) $item->campaign_desc)[0] ?? '');
}
else {
$campaign_desc = '';
}
$campaignRate = '';
if (($content->show_campaign_rate == 'yes') && $item->campaign_amount_old_price && $item->campaign_amount_new_price) {
$campaignRate = round((($item->campaign_amount_old_price - $item->campaign_amount_new_price) / $item->campaign_amount_old_price) * 100);
$campaignRate = sprintf(__('theme/package_discount_save'), $campaignRate);
}
$dateString = (isset($item->campaign_date) && $item->campaign_date ? $item->campaign_date : date('Y-m-d H:i:s', strtotime('+1 month')));
$isExpired = $dateString <= date('Y-m-d H:i:s');
$dateString = date('Y/m/d H:i:s', strtotime($dateString));
if (!$isCarousel) {
$output .= '<div class="col">';
}
$isFeatured = isset($item->campaign_featured) && $item->campaign_featured == 'yes';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'campaign' . DS . 'style_' . $content->widget_style . '.php';
if (!$isCarousel) {
$output .= '</div>';
}
}
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function carouselslider_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$content_vertical_center = (isset($content->content_vertical_center) && $content->content_vertical_center == 'yes' ? true : false);
$height = (isset($content->height) && $content->height ? $content->height : 'auto');
$custom_height = (isset($content->custom_height) && $content->custom_height ? $content->custom_height : (object) ['xl' => 900, 'lg' => 700, 'md' => 600, 'sm' => 500, 'xs' => 400]);
$animation_style = (isset($content->animation_style) && $content->animation_style ? $content->animation_style : 'slide');
$autoplay = (isset($content->autoplay) && $content->autoplay == 'yes' ? true : false);
$interval = (isset($content->interval) && $content->interval ? $content->interval : 3000);
$disable_touch_swipe = (isset($content->disable_touch_swipe) && $content->disable_touch_swipe == 'yes' ? true : false);
$arrow_controllers = (isset($content->arrow_controllers) && $content->arrow_controllers == 'yes' ? true : false);
$dot_controllers = (isset($content->dot_controllers) && $content->dot_controllers == 'yes' ? true : false);
$dot_controllers_thumb = (isset($content->dot_controllers_thumb) && $content->dot_controllers_thumb == 'yes' ? true : false);
$slide_items = (isset($content->items) && $content->items ? $content->items : []);
if (!$arrow_controllers && !$dot_controllers) {
$autoplay = true;
}
$carouselAttributes = '';
$carouselAttributes .= ($autoplay ? ' data-bs-ride="carousel" ' : '');
$carouselAttributes .= ($disable_touch_swipe ? ' data-bs-touch="false" ' : '');
$style = '';
if ($height != 'auto') {
$responsiveItems = [
'.carousel-item' => [
['type' => 'height', 'unit' => 'px', 'value' => $custom_height]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-carouselslider-widget ' . ($content_vertical_center ? 'vertical-center' : '') . ' ' . $content->fon_class . '">';
$output .= '<div id="carousel_' . $moduleId . '" class="carousel slide ' . ($animation_style == 'fade' ? 'carousel-fade' : '') . '" ' . $carouselAttributes . '>';
if ($slide_items) {
if ($dot_controllers) {
$output .= '<div class="carousel-indicators ' . ($dot_controllers_thumb ? 'carousel-thumb' : '') . '">';
foreach ($slide_items as $sk => $si) {
$thumb_image = '';
if (is_object($si->image)) {
$thumb_image = (isset($si->slide_image->{$this->lang}) && $si->slide_image->{$this->lang} ? $si->slide_image->{$this->lang} : array_values((array) $si->slide_image)[0] ?? '');
}
else if (is_string($si->slide_image)) {
$thumb_image = $si->slide_image;
}
$output .= '<button' . "\n" . ' type="button"' . "\n" . ' data-bs-target="#carousel_' . $moduleId . '"' . "\n" . ' data-bs-slide-to="' . $sk . '"' . "\n" . ' class="' . ($sk == 0 ? 'active' : '') . '" ' . ($sk == 0 ? 'aria-current="true"' : '') . "\n" . ' aria-label="Slide ' . ($sk + 1) . '"' . "\n" . ' style="' . ($dot_controllers_thumb ? 'background-image:url(' . $thumb_image . ');' : '') . '"></button>';
}
$output .= '</div>';
}
$output .= '<div class="carousel-inner">';
foreach ($slide_items as $slide_key => $slide_item) {
$image = '';
if (is_object($slide_item->slide_image)) {
$image = (isset($slide_item->slide_image->{$this->lang}) && $slide_item->slide_image->{$this->lang} ? $slide_item->slide_image->{$this->lang} : array_values((array) $slide_item->slide_image)[0] ?? '');
}
else if (is_string($slide_item->slide_image)) {
$image = $slide_item->slide_image;
}
$image_src = ($image ? static::assetLinkDetermine($image) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($image_src, $pageData['badress']);
$mobile_image = '';
if (is_object($slide_item->slide_mobile_image)) {
$mobile_image = (isset($slide_item->slide_mobile_image->{$this->lang}) && $slide_item->slide_mobile_image->{$this->lang} ? $slide_item->slide_mobile_image->{$this->lang} : array_values((array) $slide_item->slide_mobile_image)[0] ?? '');
}
else if (is_string($slide_item->slide_mobile_image)) {
$mobile_image = $slide_item->slide_mobile_image;
}
$mobile_image_src = ($mobile_image ? static::assetLinkDetermine($mobile_image) : $lazyPlaceholder);
$mobileDimensions = static::getImageDimensions($mobile_image_src, $pageData['badress']);
$show_info = (isset($slide_item->slide_show_info) && $slide_item->slide_show_info == 'yes' ? true : false);
$link = (isset($slide_item->button_link->{$this->lang}) && $slide_item->button_link->{$this->lang} ? $slide_item->button_link->{$this->lang} : array_values((array) $slide_item->button_link)[0] ?? '');
$target = (isset($slide_item->button_target) && $slide_item->button_target ? $slide_item->button_target : '_self');
if ($show_info) {
$title = (isset($slide_item->slide_title->{$this->lang}) && $slide_item->slide_title->{$this->lang} ? $slide_item->slide_title->{$this->lang} : array_values((array) $slide_item->slide_title)[0] ?? '');
$title_color = (isset($slide_item->slide_title_color) && $slide_item->slide_title_color ? $slide_item->slide_title_color : '#ffffff');
$description = (isset($slide_item->slide_description->{$this->lang}) && $slide_item->slide_description->{$this->lang} ? $slide_item->slide_description->{$this->lang} : array_values((array) $slide_item->slide_description)[0] ?? '');
$description_color = (isset($slide_item->slide_description_color) && $slide_item->slide_description_color ? $slide_item->slide_description_color : '#ffffff');
$content_bg = (isset($slide_item->slide_content_bg) && $slide_item->slide_content_bg ? $slide_item->slide_content_bg : 'rgba(0,0,0,0.1)');
$content_align = (isset($slide_item->slide_content_align) && $slide_item->slide_content_align ? (array) $slide_item->slide_content_align : ['xl' => 'center', 'lg' => 'center', 'md' => 'center', 'sm' => 'center', 'xs' => 'center']);
$content_align = (object) array_map(function($val) {
return ($val === 'left' ? 'start' : ($val === 'right' ? 'end' : $val));
}, $content_align);
$alignClass = 'text-' . $content_align->xs . ' text-sm-' . $content_align->sm . ' text-md-' . $content_align->md . ' text-lg-' . $content_align->lg . ' text-xl-' . $content_align->xl;
}
$output .= '<div class="carousel-item ' . ($slide_key == 0 ? 'active' : '') . ' ' . ($height != 'auto' ? 'custom-height' : '') . '" data-bs-interval="' . $interval . '">';
if (!$show_info && $link) {
$output .= '<a href="' . $link . '" target="' . $target . '" class="d-block h-100">';
}
if ($mobile_image && $mobile_image != $image && $height == 'auto') {
if ($enableLazyLoading) {
$output .= '<img loading="lazy" decoding="async" src="' . $image_src . '" class="d-none d-lg-block w-100 h-auto" alt="' . ($title ?? ('Slide ' . $slide_key)) . '" ' . $imageDimensions . '>';
$output .= '<img loading="lazy" decoding="async" src="' . $mobile_image_src . '" class="d-block d-lg-none w-100 h-auto" alt="' . ($title ?? ('Slide ' . $slide_key)) . '" ' . $imageDimensions . '>';
}
else {
$output .= '<img src="' . $image_src . '" class="d-none d-lg-block w-100 h-auto" alt="' . ($title ?? ('Slide ' . $slide_key)) . '" ' . $mobileDimensions . '>';
$output .= '<img src="' . $mobile_image_src . '" class="d-block d-lg-none w-100 h-auto" alt="' . ($title ?? ('Slide ' . $slide_key)) . '" ' . $imageDimensions . '>';
}
}
else if ($enableLazyLoading) {
$output .= '<img loading="lazy" decoding="async" src="' . $image_src . '" class="d-block w-100" alt="' . ($title ?? ('Slide ' . $slide_key)) . '">';
}
else {
$output .= '<img src="' . $image_src . '" class="d-block w-100" alt="' . ($title ?? ('Slide ' . $slide_key)) . '">';
}
if (!$show_info && $link) {
$output .= '</a>';
}
if ($show_info && $title || $description || $link) {
$output .= '<div class="carousel-caption d-none d-md-block ' . $alignClass . '">';
$output .= '<div class="carousel-caption-inner p-3 rounded" style="background-color:' . $content_bg . ';">';
if ($title) {
$output .= '<h2 ' . ($title_color ? 'style="color:' . $title_color . '"' : '') . '>' . $title . '</h2>';
}
if ($description) {
$output .= '<p ' . ($description_color ? 'style="color:' . $description_color . '"' : '') . '>' . $description . '</p>';
}
if ($link) {
$output .= self::parseButton($slide_item, $moduleId, $pageData);
}
$output .= '</div>';
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '</div>';
if ($arrow_controllers) {
$output .= '<button class="carousel-control-prev" type="button" data-bs-target="#carousel_' . $moduleId . '" data-bs-slide="prev">';
$output .= '<span class="fa-solid fa-circle-chevron-left fs-2" aria-hidden="true"></span>';
$output .= '<span class="visually-hidden">Previous</span>';
$output .= '</button>';
$output .= '<button class="carousel-control-next" type="button" data-bs-target="#carousel_' . $moduleId . '" data-bs-slide="next">';
$output .= '<span class="fa-solid fa-circle-chevron-right fs-2" aria-hidden="true"></span>';
$output .= '<span class="visually-hidden">Next</span>';
$output .= '</button>';
}
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function client_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$use_border = (isset($content->use_border) && $content->use_border == 'yes' ? true : false);
$show_title = (isset($content->show_title) && $content->show_title == 'yes' ? true : false);
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$center = (isset($content->center) && $content->center == 'yes' ? true : false);
$remove_hover = (isset($content->remove_hover) && $content->remove_hover == 'yes' ? true : false);
$background = (isset($content->background) && $content->background ? $content->background : (object) ['normal' => '#ffffff', 'hover' => '#ffffff']);
$image_filter = (isset($content->image_filter) && $content->image_filter ? $content->image_filter : 'none');
$border = (isset($content->border) && $content->border ? $content->border : '');
$radius = (isset($content->radius) && $content->radius ? $content->radius : '');
$shadow = (isset($content->shadow) && $content->shadow ? $content->shadow : '');
$title_font = (isset($content->title_font) && $content->title_font ? $content->title_font : []);
$blur_value = (isset($content->blur_value) && $content->blur_value ? $content->blur_value : 0);
$grayscale_value = (isset($content->grayscale_value) && $content->grayscale_value ? $content->grayscale_value : 0);
$opacity_value = (isset($content->opacity_value) && $content->opacity_value ? $content->opacity_value : 1);
$scale_value = (isset($content->scale_value) && $content->scale_value ? $content->scale_value : 1);
$hover_effect = (isset($content->hover_effect) && $content->hover_effect ? $content->hover_effect : 'none');
$max_height = (isset($content->max_height) && $content->max_height ? $content->max_height : '');
$padding = (isset($content->padding) && $content->padding ? $content->padding : '');
$link_target = (isset($content->link_target) && $content->link_target ? $content->link_target : '_self');
$style = '';
$style .= '#' . $widgetId . ' .client{';
if ($use_border && $border) {
$style .= 'border: ' . $border . ';';
if ($radius) {
$style .= 'border-radius: ' . $radius . 'px;';
}
if ($padding) {
$style .= 'padding: ' . $padding . ';';
}
}
if (isset($background->normal) && $background->normal) {
$style .= 'background-color: ' . $background->normal . ';';
}
if ($shadow) {
$style .= 'box-shadow: ' . $shadow . ';';
}
$style .= '}';
if (isset($background->hover) && $background->hover) {
$style .= '#' . $widgetId . ' .client:hover{';
$style .= 'background-color: ' . $background->hover . ';';
$style .= '}';
}
if ($show_title && $title_font) {
$style .= '#' . $widgetId . ' .client .client-title{';
$style .= self::parseFontProperties($title_font);
$style .= '}';
}
if ($image_filter == 'blur') {
$style .= '#' . $widgetId . '.filter-blur .fon-widget-content:hover .client{';
$style .= 'filter: blur(' . $blur_value . 'px);';
$style .= 'opacity:0.6;';
$style .= '}';
$style .= '#' . $widgetId . '.filter-blur .fon-widget-content:hover .client:hover{';
$style .= 'filter: blur(0);';
$style .= 'opacity:1;';
$style .= '}';
}
else {
$style .= '#' . $widgetId . ' .client .client-image{';
if ($max_height) {
$style .= 'max-height: ' . $max_height . 'px;';
}
if ($image_filter != 'none') {
if ($image_filter == 'grayscale') {
$style .= 'filter: grayscale(' . $grayscale_value . '%);';
}
else if ($image_filter == 'opacity') {
$style .= 'filter: opacity(' . $opacity_value . '%);';
}
}
if ($hover_effect != 'none') {
if ($hover_effect == 'scale') {
$style .= 'transform: scale(1);';
}
else if ($hover_effect == 'move') {
$style .= 'transform: translateY(0);';
}
}
$style .= '}';
$style .= '#' . $widgetId . ' .client:hover .client-image{';
if (($image_filter != 'none') && $remove_hover) {
if ($image_filter == 'grayscale') {
$style .= 'filter: grayscale(0);';
}
else if ($image_filter == 'opacity') {
$style .= 'filter: opacity(100);';
}
}
if ($hover_effect != 'none') {
if ($hover_effect == 'scale') {
$style .= 'transform: scale(' . $scale_value . ');';
}
else if ($content->hover_effect == 'move') {
$style .= 'transform: translateY(-' . $scale_value . 'px);';
}
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$carouselData = '';
$columns = (object) ['xl' => '', 'lg' => '', 'md' => '', 'sm' => '', 'xs' => ''];
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel client-carousel';
}
else {
$columns = $content->column;
$containerClass = (1 < count($content->items) ? 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl . ' g-3' : '');
if ($center) {
$containerClass .= ' justify-content-center';
}
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-client-widget ' . ($content->use_border == 'yes' ? 'with-border' : '') . ' filter-' . $content->image_filter . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content ' . $containerClass . '" ' . $carouselData . '>';
if (isset($content->items) && is_array($content->items)) {
$i = 1;
foreach ($content->items as $item) {
$client_title = (isset($item->client_title) && $item->client_title ? $item->client_title : '');
$client_alt = (isset($item->client_alt) && $item->client_alt ? $item->client_alt : '');
$client_link = (isset($item->client_link) && $item->client_link ? $item->client_link : '');
$link_target = (isset($item->link_target) && $item->link_target ? $item->link_target : '_self');
$link_rel = (isset($item->link_rel) && $item->link_rel ? $item->link_rel : []);
$link_rel = ($link_rel ? ' rel="' . implode(' ', $link_rel) . '" ' : '');
if ($item->client_image) {
$item->client_image = static::assetLinkDetermine($item->client_image);
}
else {
$item->client_image = $lazyPlaceholder;
}
if (empty($client_alt)) {
if (!empty($client_title)) {
$client_alt = $client_title;
}
else {
$client_alt = basename($item->client_image);
}
}
if (empty($client_title)) {
if (!empty($client_alt)) {
$client_title = $client_alt;
}
else {
$client_title = basename($item->client_image);
}
}
$imageDimensions = static::getImageDimensions($item->client_image, $pageData['badress']);
$lastClass = [];
if (6 < $i) {
$i = 1;
}
if ($i == $columns->xs) {
$lastClass[] = 'last-xs';
}
else if ($i == $columns->sm) {
$lastClass[] = 'last-sm';
}
else if ($i == $columns->md) {
$lastClass[] = 'last-md';
}
else if ($i == $columns->lg) {
$lastClass[] = 'last-lg';
}
else if ($i == $columns->xl) {
$lastClass[] = 'last-xl';
}
if (!$isCarousel) {
$output .= '<div class="col ' . implode(' ', $lastClass) . ' ">';
}
$output .= '<div class="client transition-default">';
if ($client_link) {
$output .= '<a class="d-block" href="' . $client_link . '" target="' . $link_target . '" ' . $link_rel . ' title="' . $client_title . '">';
}
if ($enableLazyLoading) {
$output .= '<img class="client-image h-auto" loading="lazy" decoding="async" src="' . $item->client_image . '" alt="' . $client_alt . '" title="' . $client_title . '" ' . $imageDimensions . '/>';
}
else {
$output .= '<img class="client-image h-auto" src="' . $item->client_image . '" alt="' . $client_alt . '" title="' . $client_title . '" ' . $imageDimensions . '/>';
}
if ($show_title) {
$output .= '<h5 class="client-title">' . $client_title . '</h5>';
}
if ($client_link) {
$output .= '</a>';
}
$output .= '</div>';
if (!$isCarousel) {
$output .= '</div>';
}
++$i;
}
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function comparison_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$pageType = $pageData['page'] ?? ($content['page_type'] ?? 'custom');
$show_free_label = !isset($content->show_free_label) || $content->show_free_label == 'yes';
$free_label_text = self::getFieldMultilingualText($content->free_label_text ?? NULL, $this->lang, __('theme/is_free'));
if ($show_free_label && empty($free_label_text)) {
$free_label_text = __('theme/is_free');
}
$card_button_action_on_free = (isset($content->card_button_action_on_free) && $content->card_button_action_on_free ? $content->card_button_action_on_free : 'default');
$enable_custom_card_button_label = isset($content->enable_custom_card_button_label) && $content->enable_custom_card_button_label == 'yes';
$custom_card_button_label = self::getFieldMultilingualText($content->custom_card_button_label ?? NULL, $this->lang, __('website/index/add-basket-button'));
$isProductPage = in_array($pageType, ['hosting' => true, 'server' => true, 'sms' => true, 'special' => true]);
$show_price_type = (isset($content->show_price_type) && $content->show_price_type ? $content->show_price_type : 'default');
if ($show_price_type == 'yes') {
$show_price_type = 'month_year';
}
$price_calc = (isset($content->price_calc) && $content->price_calc ? $content->price_calc : 'default');
$source = (isset($content->source) && $content->source ? $content->source : 'category');
$source_category = (isset($content->category) && $content->category ? $content->category : '');
$source_package = (isset($content->package) && $content->package ? $content->package : '');
$name_widget = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
$desc_widget = (isset($content->desc_widget->{$this->lang}) && $content->desc_widget->{$this->lang} ? $content->desc_widget->{$this->lang} : array_values((array) $content->desc_widget)[0] ?? '');
$catType = '';
$currency_symbols = self::getCurrencySymbols();
if ($isProductPage && isset($pageData['items'])) {
$category = $pageData['items']['showCategory'] ?? [];
$catType = $category['kind'] ?? '';
if (!$category) {
return '';
}
$list = $pageData['functions']['get_list']($category['id'], $category['kind']);
if (!$list) {
$categories = $pageData['functions']['get_categories']($category['id'], $category['kind']);
if ($categories) {
$list = $pageData['functions']['get_list']($categories[0]['id'], $category['kind']);
}
}
}
else if (($source == 'category') && $source_category) {
list($categoryType, $categoryId) = explode(':', $source_category);
$catType = $categoryType ?? '';
if ($categoryId == 'none') {
$result = $this->getWidgetItems('products', $categoryId, $categoryType);
if ($result) {
$category = ['kind' => $categoryType, 'title' => $name_widget];
$list = $result['items'];
}
else {
$category = [];
$list = [];
}
if (!$category) {
return '';
}
}
else {
$result = $this->getWidgetItems('products', 'cats: ' . $categoryId, $categoryType);
if ($result) {
$category = $result['cats'][$categoryId];
$list = $result['items'][$categoryId];
}
else {
$category = [];
$list = [];
}
if (!$category) {
return '';
}
}
}
else if (($source == 'package') && $source_package) {
list($packageType, $packageIds) = explode(':', $source_package);
$catType = $packageType ?? '';
$result = $this->getWidgetItems('products', 'items: ' . $packageIds, $packageType);
if ($result) {
$category = ['kind' => $packageType, 'title' => $name_widget];
$list = $result['items'];
}
else {
$category = [];
$list = [];
}
if (!$category) {
return '';
}
}
else {
return '';
}
$widgetStyle = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'default');
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$showCoupon = (isset($content->show_coupon) && $content->show_coupon == 'yes' ? true : false);
$carouselDataBody = '';
$carouselDataHeader = '';
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="no" data-autoplay="no" data-pause="yes" data-loop="no" data-row="no" data-rows="' . htmlspecialchars(Utility::jencode(['xl' => 1, 'lg' => 1, 'md' => 1, 'sm' => 1, 'xs' => 1]), ENT_QUOTES, 'UTF-8') . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" data-asnavfor="#ctHeaderSlide' . $widgetId . ',#ctBodySlide' . $widgetId . '"';
$carouselDataBody = $carouselData . ' data-arrows="no"';
$carouselDataHeader = $carouselData . ' data-arrows="' . $content->arrows . '"';
}
if (isset($category['kind']) && $category['kind'] == 'special') {
$categortKind = $this->getCategory($category['id'], 'products', 'special');
$categoryKindId = $categortKind['kind_id'] ?? ($categortKind['kind_id'] ?? 0);
if ($categoryKindId) {
$categoryCoupon = $this->couponCheck('category', $category['kind'], [$categoryKindId . '/' . $category['id']]);
}
else {
$categoryCoupon = $this->couponCheck('category', $category['kind'], [$category['id']]);
}
}
else {
$categoryCoupon = $this->couponCheck('category', $category['kind'], [$category['id']]);
}
$productCoupons = [];
$output = '';
if (isset($list) && $list) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-comparison-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$allFeatures = [];
$features = [];
$periods = [];
foreach ($list as $key => $product) {
foreach ($product['prices'] as $spkey => $spprice) {
$periods[$spkey] = $spprice['time'] . ' ' . ___('date/period-' . $spprice['period']);
}
$featuresJson = true;
if (isset($category['kind']) && $category['kind'] == 'special') {
$productCoupon = $this->couponCheck('product', $product['type'], [$categoryKindId, $product['id']]);
}
else {
$productCoupon = $this->couponCheck('product', $product['type'], [$category['id'], $product['id']]);
}
if ($productCoupon) {
$productCoupons[$product['id']] = $productCoupon;
}
$productFeatures = (self::isJSON($product['features']) ? Utility::jdecode($product['features'], true) : $product['features']);
if (!is_array($productFeatures) && $productFeatures) {
$featuresJson = false;
$productFeatures = preg_split('/\\r\\n|\\r|\\n/', $productFeatures);
}
if (isset($productFeatures['features'])) {
if (count($features) < count($productFeatures['features'])) {
$features = $productFeatures['features'];
}
$allFeatures[$product['id']] = $productFeatures;
if (($catType == 'server') && $product['options']) {
$arrayFeature = [];
foreach (['processor', 'ram', 'disk-space', 'bandwidth', 'raid'] as $key) {
if (isset($product['options'][$key])) {
$arrayFeature[$key] = ['name' => match ($key) {
processor => __('website/products/server-list-processor'),
ram => __('website/products/server-list-ram'),
disk-space => __('website/products/server-list-disk'),
bandwidth => __('website/products/server-list-bandwidth'),
raid => __('website/products/server-list-raid')
}, 'desc' => '', 'icon' => match ($key) {
processor => 'fa-solid fa-microchip',
ram => 'fa-solid fa-memory',
disk-space => 'fa-solid fa-hard-drive',
bandwidth => 'fa-solid fa-gauge-high',
raid => 'fa-solid fa-server'
}, 'type' => 'text', 'text' => $product['options'][$key], 'exist' => true];
}
}
if (isset($product['options_lang']['location'])) {
$country = '-';
$code = NULL;
if ($product['options_lang']['location'] != '') {
if (strpos($product['options_lang']['location'], '-') !== false) {
$parts = explode('-', $product['options_lang']['location']);
$country = $parts[0];
$code = end($parts);
}
else {
$country = $product['options_lang']['location'];
$code = NULL;
}
}
$arrayFeature['location'] = ['name' => __('website/products/server-list-location'), 'desc' => '', 'icon' => 'fa-solid fa-location-dot', 'type' => 'text', 'text' => ($code ? '<i class="flag flag-xs rounded-1 flag-country-' . strtolower($code) . ' me-1"></i>' . $country : $country), 'exist' => true];
}
if ($arrayFeature) {
$allFeatures[$product['id']]['features'] = array_merge($arrayFeature, $allFeatures[$product['id']]['features']);
$features = array_merge($arrayFeature, $features);
}
}
}
else if (is_array($productFeatures) && $catType == 'special' && isset($category['options_lang']['columns']) && $category['options_lang']['columns']) {
$features = [];
foreach ($category['options_lang']['columns'] as $column) {
$columnVal = $productFeatures[$column['id']] ?? NULL;
$columnFeature = ['name' => $column['name'], 'desc' => '', 'icon' => '', 'type' => 'text', 'text' => $columnVal];
$features[] = $columnFeature;
$allFeatures[$product['id']]['features'][] = $columnFeature;
}
}
else if (is_array($productFeatures) && $productFeatures) {
$features = [];
foreach ($productFeatures as $pf) {
$arrayFeature = ['name' => $pf, 'desc' => '', 'icon' => '', 'type' => 'select', 'text' => '', 'exist' => true];
$features[] = $arrayFeature;
$allFeatures[$product['id']]['features'][] = $arrayFeature;
}
}
else if (($catType == 'server') && $product['options']) {
$arrayFeature = [];
foreach (['processor', 'ram', 'disk-space', 'bandwidth', 'raid'] as $key) {
if (isset($product['options'][$key])) {
$arrayFeature[$key] = ['name' => match ($key) {
processor => __('website/products/server-list-processor'),
ram => __('website/products/server-list-ram'),
disk-space => __('website/products/server-list-disk'),
bandwidth => __('website/products/server-list-bandwidth'),
raid => __('website/products/server-list-raid')
}, 'desc' => '', 'icon' => match ($key) {
processor => 'fa-solid fa-microchip',
ram => 'fa-solid fa-memory',
disk-space => 'fa-solid fa-hard-drive',
bandwidth => 'fa-solid fa-gauge-high',
raid => 'fa-solid fa-server'
}, 'type' => 'text', 'text' => $product['options'][$key], 'exist' => true];
}
}
if (isset($product['options_lang']['location'])) {
$arrayFeature['location'] = ['name' => __('website/products/server-list-location'), 'desc' => '', 'icon' => 'fa-solid fa-location-dot', 'type' => 'text', 'text' => $product['options_lang']['location'], 'exist' => true];
}
$allFeatures[$product['id']] = ['features' => $arrayFeature];
if (empty($features)) {
$features = $arrayFeature;
}
}
}
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'comparison' . DS . 'style_' . $widgetStyle . '.php';
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
private function content_box_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$title_color = (isset($content->title_color) && $content->title_color ? $content->title_color : '');
$title_font = (isset($content->title_font) && $content->title_font ? $content->title_font : '');
$desc_color = (isset($content->description_color) && $content->description_color ? $content->description_color : '');
$desc_font = (isset($content->desc_font) && $content->desc_font ? $content->desc_font : '');
$icon_color = (isset($content->icon_color) && $content->icon_color ? $content->icon_color : '');
$icon_bg_color = (isset($content->icon_bg_color) && $content->icon_bg_color ? $content->icon_bg_color : '');
$icon_class = (isset($content->icon_class) && $content->icon_class ? $content->icon_class : '');
$item_class = (isset($content->item_class) && $content->item_class ? $content->item_class : '');
$image_width = (isset($content->image_width) && $content->image_width ? $content->image_width : '');
$style = '';
if ($title_color || $desc_color || $icon_color || $icon_bg_color) {
$style .= '#' . $widgetId . '.fon-content-box-widget{';
if ($title_color) {
$style .= '--title-color: ' . $title_color . ';';
}
if ($desc_color) {
$style .= '--desc-color: ' . $desc_color . ';';
}
if ($icon_color) {
$style .= '--icon-color: ' . $icon_color . ';';
}
if ($icon_bg_color) {
$style .= '--icon-bg-color: ' . $icon_bg_color . ';';
}
$style .= '}';
}
if ($title_font || $desc_font) {
if ($title_font) {
$style .= '#' . $widgetId . ' .fon-contentbox-title{';
$style .= self::parseFontProperties($title_font);
$style .= '}';
}
if ($desc_font) {
$style .= '#' . $widgetId . ' .fon-contentbox-content{';
$style .= self::parseFontProperties($desc_font);
$style .= '}';
}
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$attributes = 'd-flex ';
if ($content->media_position == 'top') {
$attributes .= 'flex-column justify-content-center ';
switch ($content->align) {
case 'left':
$attributes .= 'align-items-start text-start';
break;
case 'right':
$attributes .= 'align-items-end text-end';
break;
case 'center':
$attributes .= 'align-items-center text-center';
break;
}
}
else {
if ($content->media_position == 'left') {
$attributes .= 'justify-content-start text-start ';
}
else if ($content->media_position == 'right') {
$attributes .= 'justify-content-end text-end ';
}
if (isset($content->vertical_align) && $content->vertical_align) {
switch ($content->vertical_align) {
case 'top':
$attributes .= 'align-items-start';
break;
case 'bottom':
$attributes .= 'align-items-end';
break;
case 'center':
$attributes .= 'align-items-center';
break;
}
}
}
$carouselData = '';
$isCarousel = false;
if ($content->use_carousel == 'yes') {
$isCarousel = true;
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel contentbox-carousel';
}
else {
$columns = $content->column;
$containerClass = (1 < count($content->items) ? 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl : '');
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-content-box-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$output .= '<div class="' . $containerClass . '" ' . $carouselData . '>';
if ($content->items) {
$cicount = 1;
foreach ($content->items as $contentBox) {
$show_icon = isset($contentBox->show_button_icon) && $contentBox->show_button_icon = ('yes' ? true : false);
$link_icon = (isset($contentBox->button_icon) && $contentBox->button_icon ? $contentBox->button_icon : '');
$link_target = (isset($contentBox->link_target) && $contentBox->link_target ? $contentBox->link_target : '_self');
$link_icon_position = (isset($contentBox->button_icon_position) && $contentBox->button_icon_position ? $contentBox->button_icon_position : 'right');
$contentBoxImage = '';
if (is_object($contentBox->image)) {
$contentBoxImage = (isset($contentBox->image->{$this->lang}) && $contentBox->image->{$this->lang} ? $contentBox->image->{$this->lang} : array_values((array) $contentBox->image)[0] ?? '');
}
else if (is_string($contentBox->image)) {
$contentBoxImage = $contentBox->image;
}
$contentBox->image = ($contentBoxImage ? static::assetLinkDetermine($contentBoxImage) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($contentBox->image, $pageData['badress']);
$content_box_title = (isset($contentBox->content_box_title->{$this->lang}) && $contentBox->content_box_title->{$this->lang} ? $contentBox->content_box_title->{$this->lang} : array_values((array) $contentBox->content_box_title)[0] ?? '');
$content_box_title = self::getPriceHolders($content_box_title);
$content_box_content = (isset($contentBox->content_box_content->{$this->lang}) && $contentBox->content_box_content->{$this->lang} ? $contentBox->content_box_content->{$this->lang} : array_values((array) $contentBox->content_box_content)[0] ?? '');
$content_box_content = self::getPriceHolders($content_box_content);
$content_box_link_text = (isset($contentBox->link_text->{$this->lang}) && $contentBox->link_text->{$this->lang} ? $contentBox->link_text->{$this->lang} : array_values((array) $contentBox->link_text)[0] ?? '');
$image_alt = (isset($contentBox->image_alt->{$this->lang}) && $contentBox->image_alt->{$this->lang} ? $contentBox->image_alt->{$this->lang} : (isset($contentBox->image_alt) ? array_values((array) $contentBox->image_alt)[0] ?? '' : ''));
$image_title = (isset($contentBox->image_title->{$this->lang}) && $contentBox->image_title->{$this->lang} ? $contentBox->image_title->{$this->lang} : (isset($contentBox->image_title) ? array_values((array) $contentBox->image_title)[0] ?? '' : ''));
if (empty($image_alt)) {
if (!empty($content_box_title)) {
$image_alt = $content_box_title;
}
else if (!empty($image_title)) {
$image_alt = $image_title;
}
else {
$image_alt = basename($contentBox->image);
}
}
if (empty($image_title)) {
if (!empty($content_box_title)) {
$image_title = $content_box_title;
}
else if (!empty($image_alt)) {
$image_title = $image_alt;
}
else {
$image_title = basename($contentBox->image);
}
}
$link_rel = (isset($contentBox->link_rel) && $contentBox->link_rel ? $contentBox->link_rel : []);
$link_rel = ($link_rel ? ' rel="' . implode(' ', $link_rel) . '" ' : '');
if (!$isCarousel) {
$output .= '<div class="col">';
}
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'content_box' . DS . 'style_' . $content->widget_style . '.php';
if (!$isCarousel) {
$output .= '</div>';
}
++$cicount;
}
}
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function countdown_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
$style .= '#' . $widgetId . ' .fon-countdown-timer {';
if (isset($content->background) && $content->background) {
$style .= '--fon-countdown-background: ' . $content->background . ';';
}
if (isset($content->number_size) && $content->number_size) {
$style .= '--fon-countdown-number-size: ' . $content->number_size . 'px;';
}
if (isset($content->number_color) && $content->number_color) {
$style .= '--fon-countdown-number-color: ' . $content->number_color . ';';
}
if (isset($content->text_size) && $content->text_size) {
$style .= '--fon-countdown-text-size: ' . $content->text_size . 'px;';
}
if (isset($content->text_color) && $content->text_color) {
$style .= '--fon-countdown-text-color: ' . $content->text_color . ';';
}
if (isset($content->padding) && $content->padding) {
$style .= '--fon-countdown-padding: ' . $content->padding . 'px;';
}
if (isset($content->margin) && $content->margin) {
$style .= '--fon-countdown-margin: ' . $content->padding . 'px;';
}
if (isset($content->border) && $content->border) {
$style .= '--fon-countdown-border: ' . $content->border . ';';
}
if (isset($content->radius) && $content->radius) {
$style .= '--fon-countdown-radius: ' . $content->radius . 'px;';
}
if (isset($content->shadow) && $content->shadow) {
$style .= '--fon-countdown-shadow: ' . $content->shadow . ';';
}
if (isset($content->gap) && $content->gap) {
$style .= '--fon-countdown-gap: ' . $content->gap . 'px;';
}
if (isset($content->divider_color) && $content->divider_color) {
$style .= '--fon-countdown-divider-color: ' . $content->divider_color . ';';
}
if (isset($content->divider) && $content->divider != 'none') {
$style .= '--fon-countdown-divider-right: -' . ($content->gap / 2) . 'px;';
}
$style .= '}';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$attributes = '';
switch ($content->align) {
case 'left':
$attributes = 'justify-content-start text-start';
break;
case 'right':
$attributes = 'justify-content-end text-end';
break;
case 'center':
$attributes = 'justify-content-center text-center';
break;
}
$output = '';
$dateLangs = ['day' => ___('date/day'), 'hour' => ___('date/hour'), 'minute' => ___('date/minute'), 'second' => ___('date/second')];
$dateString = $content->date . ' ' . $content->time . ':00';
$dateString = date('Y/m/d H:i:s', strtotime($dateString));
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-countdown ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$output .= '<div class="fon-countdown-timer ' . $attributes . ' divider-' . $content->divider . ' text-position-' . $content->text_position . '" data-enddate="' . $dateString . '" data-lang="' . htmlentities(json_encode($dateLangs), ENT_QUOTES, 'UTF-8') . '" data-message="' . strip_tags($content->message) . '"></div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function cost_calculator_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$class = (isset($content->fon_class) && $content->fon_class ? $content->fon_class : '');
$show_title = (isset($content->show_name) && $content->show_name == 'yes' ? true : false);
$title = __('website/account_sms/introduction-calculate-title');
if ($show_title) {
$title = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : $title);
}
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="card fon-cost-calculator rounded-4 text-center international-sms-calculate ' . $class . '">';
$output .= '<div class="card-header bg-white py-3">';
$output .= '<h3 class="card-title fs-5 fw-semibold text-theme-secondary mb-0">' . $title . '</h3>';
$output .= '</div>';
$output .= '<div class="card-body" style="background: url(' . $pageData['tadress'] . 'images/map.svg) no-repeat scroll center;">';
$output .= '<select id="countries" class="form-select">';
$output .= '<option value="">' . __('website/account_sms/introduction-calculate-select-country') . '</option>';
foreach ($pageData['country_prices'] as $country) {
$cc = $country['cc'];
$prices = $country['prices'];
$output .= '<option ' . ($cc == $pageData['default_country'] ? 'selected' : '') . "\n" . ' value="' . $cc . '"' . "\n" . ' data-prices=\'' . Utility::jencode($prices) . '\'' . "\n" . ' data-pre-register="' . ($country['pre-register'] ? 'true' : 'false') . '"' . "\n" . ' data-image="' . $pageData['sadress'] . 'assets/images/flags/' . $cc . '.svg' . '">' . $country['name'] . ' </option>';
}
$output .= '</select>';
$output .= '<div id="calculateResult" style="display: none;">';
$output .= '<p class="my-4">' . __('website/account_sms/introduction-calculate-note') . ' </p>';
$currs = [];
$defCurr = '';
$currencies = [];
foreach (Money::getCurrencies() as $row) {
if ($row['id'] == $pageData['ucid']) {
array_unshift($currencies, $row);
}
else {
array_push($currencies, $row);
}
}
$output .= '<div class="d-flex justify-content-center flex-wrap gap-2 mb-3">';
foreach ($currencies as $curr) {
$currs[] = $curr['code'];
if ($curr['id'] == $pageData['ucid']) {
$defCurr = $curr['code'];
}
$output .= '<a id="currency-button-' . $curr['code'] . ' " class="' . ($curr['id'] == $pageData['ucid'] ? 'active ' : '') . ' btn btn-outline-primary currency-button" href="javascript:setCurrency(\'' . $curr['code'] . '\');void(0);">' . $curr['code'] . ' </a>';
}
$output .= '</div>';
$output .= '<h3 id="country-name">?</h3>';
$output .= '<h4 class="fs-5">';
foreach ($currs as $curr) {
$output .= '<span id="currency-' . $curr . '" ' . ($defCurr == $curr ? '' : 'style="display: none;"') . ' class="currency-content">' . "\n" . ' 1 SMS = <span id="calculate-' . $curr . '-amount">0</span> <span style="font-size:20px;">' . $curr . '</span><br>' . "\n" . ' <span class="amount-thousands">(1000 SMS = <span id="calculate-' . $curr . '-amount-thousands">0</span> ' . $curr . ' )</span>' . "\n" . ' </span>';
}
$output .= '</h2>';
$output .= '<div class="fs-12" id="country_pre_register">' . __('website/account_sms/introduction-calculate-pre-register-note') . ' </div>';
$output .= '<input type="hidden" id="defCurrency" value="' . $defCurr . ' ">';
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="card-footer bg-white d-grid">';
$output .= '<a class="btn btn-secondary btn-lg" href="' . $pageData['download_prices'] . ' /' . $defCurr . ' " id="download_prices" target="_blank">' . __('website/account_sms/introduction-download-prices') . ' </a>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function domain_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'default');
$slogan = (isset($content->slogan) && $content->slogan ? (array) $content->slogan : [$this->lang => __('website/domain/slogan', ['{price}' => '{{domain:com:register}}'])]);
$show_ai = (isset($content->show_ai) && $content->show_ai == 'yes' ? true : false);
$ai_button_title = self::getFieldMultilingualText($content->ai_button_title, $this->lang, __('theme/domain/ai_button_title'));
$classic_button_title = self::getFieldMultilingualText($content->classic_button_title, $this->lang, __('theme/domain/classic_button_title'));
$contentTitle = self::getFieldMultilingualText($content->title, $this->lang, '');
$button_text = self::getFieldMultilingualText($content->button_text, $this->lang, __('website/index/domain-check-query-button'));
$tld_title = self::getFieldMultilingualText($content->tld_title, $this->lang, __('website/domain/meta/title'));
$tld_register = self::getFieldMultilingualText($content->tld_register, $this->lang, __('admin/orders/create-domain-transaction-register'));
$input_placeholders = self::getFieldMultilingualText($content->input_placeholders, $this->lang, __('theme/domain/input_placeholders'));
if ($input_placeholders) {
$input_placeholders = (!is_array($input_placeholders) ? explode(PHP_EOL, $input_placeholders) : $input_placeholders);
}
else {
$input_placeholders = __('theme/domain/input_placeholders');
}
$input_placeholders = htmlspecialchars(json_encode($input_placeholders, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$assets = ['type-placeholder'];
if ($show_ai) {
$assets[] = 'fon-ai-domain-suggest';
$aiConfig = Modules::Config('Addons', 'FonPageBuilder');
if (isset($aiConfig['ai']['tlds']) && $aiConfig['ai']['tlds']) {
$aiTlds = (is_string($aiConfig['ai']['tlds']) ? explode(',', $aiConfig['ai']['tlds']) : $aiConfig['ai']['tlds']);
$aiTlds = array_map('trim', $aiTlds);
}
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' && $content->show_tlds == 'yes' ? true : false);
$carouselData = '';
if ($isCarousel) {
$assets[] = 'slick';
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
}
$this->addAsset($assets);
$domain_override_uscurrency = Config::get('options/domain-override-user-currency');
$form_action = (isset($pageData['domain']) && $pageData['domain']['tlds'] ? $pageData['domain']['form_action'] : Controllers::$init->CRLink('domain'));
if ($content->show_tlds == 'yes') {
$spotlights = ($pageData['page'] == 'index' ? ___('blocks/home-domain-check/items', false, $this->lang) : __('website/domain/spotlight-tlds', false, $this->lang));
if (is_array($spotlights) && !empty($spotlights)) {
$wherein = implode('\',\'', $spotlights);
$tlds = self::getTldList($wherein);
}
else {
$tlds = [];
}
if ($tlds) {
$firstPrice = self::getPriceHolders($slogan[$this->lang]);
}
}
else if ($content->show_slogan) {
$firstPrice = self::getPriceHolders($slogan[$this->lang]);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-domain-widget ' . $content->fon_class . ' ' . ($show_ai ? 'domain-ai-enabled' : '') . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'domain' . DS . 'style_' . $widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function domain_form_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$firstPrice = (isset($pageData['domain']['firstPrice']) ? $pageData['domain']['firstPrice'] : '');
$box_tldList = (isset($pageData['domain']['tlds']) ? $pageData['domain']['tlds'] : false);
$tldList = (isset($pageData['domain']['tldList']) ? $pageData['domain']['tldList'] : false);
$tldList = ($tldList ? $tldList : self::getTldList());
$captcha = (isset($pageData['domain']['captcha']) ? $pageData['domain']['captcha'] : false);
$domain_override_uscurrency = Config::get('options/domain-override-user-currency');
$formAction = (isset($pageData['domain']['form_action']) ? $pageData['domain']['form_action'] : Controllers::$init->CRLink('domain'));
$register_link = Controllers::$init->CRLink('domain');
$transfer_link = Controllers::$init->CRLink('domain-transfer');
$whois_link = Controllers::$init->CRLink('domain-whois');
$show_ai = (isset($content->show_ai) && $content->show_ai == 'yes' ? true : false);
$ai_button_title = self::getFieldMultilingualText($content->ai_button_title, $this->lang, __('theme/domain/ai_button_title'));
$classic_button_title = self::getFieldMultilingualText($content->classic_button_title, $this->lang, __('theme/domain/classic_button_title'));
$form_type = (isset($content->form_type) && $content->form_type ? $content->form_type : 'domain');
$form_title = self::getFieldMultilingualText($content->form_title, $this->lang, '');
$form_description = (isset($content->form_description->{$this->lang}) && $content->form_description->{$this->lang} ? self::getPriceHolders($content->form_description->{$this->lang}) : __('website/domain/slogan', ['{price}' => $firstPrice]));
$form_align = (isset($content->form_align) && $content->form_align ? $content->form_align : (object) ['xl' => 'center', 'lg' => 'center', 'md' => 'center', 'sm' => 'center', 'xs' => 'center']);
$show_tlds = (isset($content->show_tlds) && $content->show_tlds == 'yes' ? true : false);
$widgetTlds = (isset($content->tld_list) && $content->tld_list != 'none' ? explode(',', trim(str_replace('items:', '', $content->tld_list))) : false);
$show_register = (isset($content->show_register) && $content->show_register == 'yes' ? true : false);
$register_title = self::getFieldMultilingualText($content->register_title, $this->lang, __('theme/domain/register-title'));
$show_transfer = (isset($content->show_transfer) && $content->show_transfer == 'yes' ? true : false);
$transfer_title = self::getFieldMultilingualText($content->transfer_title, $this->lang, __('theme/domain/transfer-title'));
$show_whois = (isset($content->show_whois) && $content->show_whois == 'yes' ? true : false);
$whois_title = self::getFieldMultilingualText($content->whois_title, $this->lang, __('theme/domain/whois-title'));
$show_captcha = (isset($content->show_captcha) && $content->show_captcha == 'yes' ? true : false);
$input_placeholders = self::getFieldMultilingualText($content->input_placeholders, $this->lang, __('theme/domain/input_placeholders'));
if ($input_placeholders) {
$input_placeholders = (!is_array($input_placeholders) ? explode(PHP_EOL, $input_placeholders) : $input_placeholders);
}
else {
$input_placeholders = __('theme/domain/input_placeholders');
}
$input_placeholders = htmlspecialchars(json_encode($input_placeholders, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8');
$alignClass = '';
$justifyClass = '';
foreach ($form_align as $key => $align) {
$alignClass .= ($key == 'xs' ? 'text-' : 'text-' . $key . '-');
$justifyClass .= ($key == 'xs' ? 'justify-content-' : 'justify-content-' . $key . '-');
if ($align == 'left') {
$alignClass .= 'start ';
$justifyClass .= 'start ';
}
else if ($align == 'right') {
$alignClass .= 'end ';
$justifyClass .= 'end ';
}
else {
$alignClass .= 'center ';
$justifyClass .= 'center ';
}
}
$style = '';
$style .= '#' . $widgetId . ' .fon-domain-form-title{';
if (isset($content->form_title_color) && $content->form_title_color) {
$style .= 'color: ' . $content->form_title_color . ';';
}
if (isset($content->form_title_font) && $content->form_title_font) {
$style .= self::parseFontProperties($content->form_title_font);
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-domain-form-description{';
if (isset($content->form_description_color) && $content->form_description_color) {
$style .= 'color: ' . $content->form_description_color . ';';
}
if (isset($content->form_description_font) && $content->form_description_font) {
$style .= self::parseFontProperties($content->form_description_font);
}
$style .= '}';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
if ($show_ai) {
$this->addAsset(['type-placeholder', 'fon-ai-domain-suggest']);
$aiConfig = Modules::Config('Addons', 'FonPageBuilder');
if (isset($aiConfig['ai']['tlds']) && $aiConfig['ai']['tlds']) {
$aiTlds = (is_string($aiConfig['ai']['tlds']) ? explode(',', $aiConfig['ai']['tlds']) : $aiConfig['ai']['tlds']);
$aiTlds = array_map('trim', $aiTlds);
}
}
else {
$this->addAsset('type-placeholder');
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-domain-form-widget ' . $form_type . ' ' . $content->fon_class . ' ' . ($show_ai ? 'domain-ai-enabled' : '') . '">';
$output .= '<div class="fon-widget-content ' . $alignClass . '">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'domain_form' . DS . $form_type . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function domain_tlds_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$currency_symbols = (isset($pageData['currency_symbols']) ? $pageData['currency_symbols'] : self::getCurrencySymbols());
$tldList = (isset($pageData['domain']['tldList']) ? $pageData['domain']['tldList'] : false);
$tldList = ($tldList ? $tldList : self::getTldList());
$domain_override_uscurrency = Config::get('options/domain-override-user-currency');
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'default');
$widgetTlds = (isset($content->tld_list) && $content->tld_list != 'none' ? explode(',', trim(str_replace('items:', '', $content->tld_list))) : false);
$tld_limit = (isset($content->tld_limit) && $content->tld_limit ? $content->tld_limit : 10);
$tld_price_type = (isset($content->tld_price_type) && $content->tld_price_type ? $content->tld_price_type : 'register');
$show_images = (isset($content->tld_images) && $content->tld_images == 'yes' ? true : false);
$show_register = (isset($content->show_register) && $content->show_register == 'yes' ? true : false);
$register_link = (isset($content->register_link) && $content->register_link ? $content->register_link : Controllers::$init->CRLink('domain'));
$register_title = (isset($content->register_title->{$this->lang}) && $content->register_title->{$this->lang} ? $content->register_title->{$this->lang} : __('theme/domain/register-title'));
$inline_register = false;
if (strpos($register_link, 'http://') === false || strpos($register_link, 'https://') === false) {
$inline_register = true;
}
$show_transfer = (isset($content->show_transfer) && $content->show_transfer == 'yes' ? true : false);
$transfer_link = Controllers::$init->CRLink('domain-transfer');
$transfer_title = (isset($content->transfer_title->{$this->lang}) && $content->transfer_title->{$this->lang} ? $content->transfer_title->{$this->lang} : __('theme/domain/transfer-title'));
$show_slogan = (isset($content->show_slogan) && $content->show_slogan == 'yes' ? true : false);
$tld_slogan = (isset($content->tld_slogan->{$this->lang}) && $content->tld_slogan->{$this->lang} ? $content->tld_slogan->{$this->lang} : __('website/domain/slogan'));
$column = (isset($content->column) && $content->column ? $content->column : (object) ['xl' => 5, 'lg' => 4, 'md' => 3, 'sm' => 2, 'xs' => 1]);
$row = (isset($content->row) && $content->row ? $content->row : (object) ['xl' => 1, 'lg' => 1, 'md' => 1, 'sm' => 1, 'xs' => 1]);
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$carouselData = '';
$columns = [];
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" data-row="' . $content->use_row . '" data-rows="' . htmlspecialchars(Utility::jencode($row, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel spotlight-tld-carousel';
}
else {
$columns = $content->column;
$containerClass = 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl;
}
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-domain-tlds-widget ' . $content->fon_class . '">';
$output .= '<div class="spot-tld-list tld-image ' . $containerClass . '" ' . $carouselData . ' id="spot-tld-lists">';
$count = 1;
foreach ($tldList as $tld) {
if ($widgetTlds && !in_array($tld['id'], $widgetTlds)) {
continue;
}
if (!$widgetTlds && $tld_limit < $count) {
break;
}
$tld_image = false;
if ($show_images) {
foreach (['svg', 'png', 'jpg'] as $ext) {
$img_path = 'images' . DS . 'tldlogos' . DS . $tld['name'] . '.' . $ext;
if (file_exists(View::$init->get_template_dir() . $img_path)) {
$tld_image = $img_path;
$imageDimensions = static::getImageDimensions($pageData['tadress'] . $img_path, $pageData['badress']);
}
}
}
if ($tld['promo_status'] && (substr($tld['promo_duedate'], 0, 4) == '1881') || DateManager::strtotime() < DateManager::strtotime($tld['promo_duedate'] . ' 23:59:59')) {
if (0 < $tld['promo_register_price']) {
if (0 < $tld['reg_price']['amount']) {
$tld['reg_price']['discount'] = round((($tld['reg_price']['amount'] - $tld['promo_register_price']) / $tld['reg_price']['amount']) * 100, 2);
}
else {
$tld['reg_price']['discount'] = 0;
}
$tld['reg_price']['amount'] = $tld['promo_register_price'];
}
if (0 < $tld['promo_transfer_price']) {
if (0 < $tld['tra_price']['amount']) {
$tld['tra_price']['discount'] = round((($tld['tra_price']['amount'] - $tld['promo_transfer_price']) / $tld['tra_price']['amount']) * 100, 2);
}
else {
$tld['tra_price']['discount'] = 0;
}
$tld['tra_price']['amount'] = $tld['promo_transfer_price'];
}
}
$registerPrice = self::calculatePrices([$tld['reg_price']], $currency_symbols, $domain_override_uscurrency, 'domain');
$transferPrice = self::calculatePrices([$tld['tra_price']], $currency_symbols, $domain_override_uscurrency, 'domain');
$renewPrice = self::calculatePrices([$tld['ren_price']], $currency_symbols, $domain_override_uscurrency, 'domain');
if ($tld_price_type == 'transfer') {
$registerPrice = $transferPrice;
}
else if ($tld_price_type == 'renew') {
$registerPrice = $renewPrice;
}
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'domain_tlds' . DS . 'style_' . $widget_style . '.php';
++$count;
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function domain_prices_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$currency_symbols = (isset($pageData['currency_symbols']) ? $pageData['currency_symbols'] : self::getCurrencySymbols());
$tldList = (isset($pageData['domain']['tldList']) ? $pageData['domain']['tldList'] : false);
$tldList = ($tldList ? $tldList : self::getTldList());
$domain_override_uscurrency = Config::get('options/domain-override-user-currency');
$show_search = (isset($content->show_search) && $content->show_search == 'yes' ? true : false);
$use_pagination = (isset($content->use_pagination) && $content->use_pagination == 'yes' ? true : false);
$pagination_type = (isset($content->pagination_type) && $content->pagination_type ? $content->pagination_type : 'pagination');
$pagination_limit = (isset($content->pagination_limit) && $content->pagination_limit ? $content->pagination_limit : 10);
$page_type = (isset($pageData['page']) ? $pageData['page'] : 'domain');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-domain-prices-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'domain_prices' . DS . $page_type . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function domain_faqs_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$page_type = (isset($pageData['page']) ? $pageData['page'] : 'domain');
$faqs = (isset($pageData['domain']['faqs']) ? $pageData['domain']['faqs'] : false);
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'default');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
if ($faqs && is_array($faqs) && count($faqs)) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-domain-faqs-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'domain_faqs' . DS . 'style_' . $widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
private function faqs_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$widget_style = 'default';
$category = (isset($content->category) && $content->category ? $content->category : 'hosting:none');
list($categoryType, $categoryId) = explode(':', $category);
$faqs = ___('constants/category-' . $categoryType . '/faq');
if ($categoryType && $categoryId) {
if ($categoryId != 'none') {
$categoryInfo = $this->getCategory($categoryId, 'products', $categoryType);
if (isset($categoryInfo['faqs']) && !empty($categoryInfo['faqs'])) {
$faqs = Utility::jdecode($categoryInfo['faqs'], true);
}
}
}
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
if ($faqs && is_array($faqs) && count($faqs)) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-' . $categoryType . '-faqs-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'faqs' . DS . 'style_' . $widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
private function feature_box_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$style = '';
if ($content->widget_style == 'custom') {
if (($content->media_type != 'icon') && $content->image_width && $content->image_height) {
$style .= '#' . $widgetId . ' .feature-image{';
$style .= 'width:' . ($content->image_width && $content->image_width ? $content->image_width . 'px' : '100%') . ';';
$style .= 'height:' . ($content->image_height && $content->image_height ? $content->image_height . 'px' : 'auto') . ';';
$style .= '}';
}
if ($content->media_type != 'image') {
$style .= '#' . $widgetId . ' .feature-icon{';
if (isset($content->icon_size) && $content->icon_size) {
$style .= 'font-size:' . $content->icon_size . 'px;';
$style .= 'width:' . $content->icon_size . 'px;';
$style .= 'height:' . $content->icon_size . 'px;';
$style .= 'line-height:' . $content->icon_size . 'px;';
}
if (isset($content->icon_color_type) && $content->icon_color_type == 'flat') {
$style .= '--bs-normal-color:' . $content->icon_color->normal . ';';
$style .= '--bs-hover-color:' . $content->icon_color->hover . ';';
}
else if (isset($content->icon_color_type) && $content->icon_color_type == 'gradient') {
$style .= self::parseGradient($content->icon_gradient->normal, 'normal-color');
$style .= self::parseGradient($content->icon_gradient->hover, 'hover-color');
}
$style .= '}';
}
$style .= '#' . $widgetId . ' .feature-box-media-container{';
if (isset($content->media_border->normal) && $content->media_border->normal) {
$style .= '--bs-normal-border:' . $content->media_border->normal . ';';
}
if (isset($content->media_border->hover) && $content->media_border->hover) {
$style .= '--bs-hover-border:' . $content->media_border->hover . ';';
}
if (isset($content->media_radius->normal) && $content->media_radius->normal) {
$style .= '--bs-normal-radius:' . $content->media_radius->normal . 'px;';
}
if (isset($content->media_radius->hover) && $content->media_radius->hover) {
$style .= '--bs-hover-radius:' . $content->media_radius->hover . 'px;';
}
if (isset($content->media_shadow->normal) && $content->media_shadow->normal) {
$style .= '--bs-normal-shadow:' . $content->media_shadow->normal . ';';
}
if (isset($content->media_shadow->hover) && $content->media_shadow->hover) {
$style .= '--bs-hover-shadow:' . $content->media_shadow->hover . ';';
}
if (isset($content->media_background_type) && $content->media_background_type == 'flat') {
$style .= '--bs-normal-bg:' . $content->media_background->normal . ';';
$style .= '--bs-hover-bg:' . $content->media_background->hover . ';';
}
else if (isset($content->media_background_type) && $content->media_background_type == 'gradient') {
$style .= self::parseGradient($content->media_gradient->normal, 'normal-bg');
$style .= self::parseGradient($content->media_gradient->hover, 'hover-bg');
}
if (isset($content->media_padding) && $content->media_padding) {
$style .= 'padding:' . $content->media_padding . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .feature-box-title, #' . $widgetId . ' .feature-box-title a{';
if (isset($content->title_color->normal) && $content->title_color->normal) {
$style .= '--bs-normal-color:' . $content->title_color->normal . ';';
}
if (isset($content->title_color->hover) && $content->title_color->hover) {
$style .= '--bs-hover-color:' . $content->title_color->hover . ';';
}
if (isset($content->title_font)) {
$style .= self::parseFontProperties($content->title_font);
}
$style .= '}';
$style .= '#' . $widgetId . ' .feature-box-desc{';
if (isset($content->content_color->normal) && $content->content_color->normal) {
$style .= '--bs-normal-color:' . $content->content_color->normal . ';';
}
if (isset($content->content_color->hover) && $content->content_color->hover) {
$style .= '--bs-hover-color:' . $content->content_color->hover . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .feature-box{';
if (isset($content->background_type) && $content->background_type == 'flat') {
$style .= '--bs-normal-bg:' . $content->background->normal . ';';
$style .= '--bs-hover-bg:' . $content->background->hover . ';';
}
else if (isset($content->background_type) && $content->background_type == 'gradient') {
$style .= self::parseGradient($content->background_gradient->normal, 'normal-bg');
$style .= self::parseGradient($content->background_gradient->hover, 'hover-bg');
}
else if (isset($content->background_type) && $content->background_type == 'image') {
$style .= 'background:url(' . self::assetLinkDetermine($content->background_image) . ') no-repeat scroll center center / cover;';
}
if (isset($content->shadow->normal) && $content->shadow->normal) {
$style .= '--bs-normal-shadow:' . $content->shadow->normal . ';';
}
if (isset($content->shadow->hover) && $content->shadow->hover) {
$style .= '--bs-hover-shadow:' . $content->shadow->hover . ';';
}
if (isset($content->border_radius->normal) && $content->border_radius->normal) {
$style .= '--bs-normal-radius:' . $content->border_radius->normal . 'px;';
}
if (isset($content->border_radius->hover) && $content->border_radius->hover) {
$style .= '--bs-hover-radius:' . $content->border_radius->hover . 'px;';
}
if (isset($content->use_border) && $content->use_border == 'yes') {
if (isset($content->border->normal) && $content->border->normal) {
$style .= '--bs-normal-border:' . $content->border->normal . ';';
}
if (isset($content->border->hover) && $content->border->hover) {
$style .= '--bs-hover-border:' . $content->border->hover . ';';
}
}
if (isset($content->padding) && $content->padding) {
$style .= 'padding:' . $content->padding . 'px;';
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$attributes = '';
if ($content->media_position == 'top') {
$attributes .= 'justify-content-center ';
switch ($content->align) {
case 'left':
$attributes .= 'align-items-start ';
break;
case 'right':
$attributes .= 'align-items-end ';
break;
case 'center':
$attributes .= 'align-items-center ';
break;
}
}
else {
if ($content->media_position == 'left') {
$attributes .= 'justify-content-start ';
}
else if ($content->media_position == 'right') {
$attributes .= 'justify-content-end ';
}
if (isset($content->vertical_align) && $content->vertical_align) {
switch ($content->vertical_align) {
case 'top':
$attributes .= 'align-items-start ';
break;
case 'bottom':
$attributes .= 'align-items-end ';
break;
case 'center':
$attributes .= 'align-items-center ';
break;
}
}
}
switch ($content->align) {
case 'left':
$attributes .= 'text-start';
break;
case 'right':
$attributes .= 'text-end';
break;
case 'center':
$attributes .= 'text-center';
break;
}
if ($content->widget_style != 'custom') {
if (isset($content->use_shadow) && $content->use_shadow == 'yes') {
$attributes .= ' with-shadow';
}
}
$image = '';
if (is_object($content->image)) {
$image = (isset($content->image->{$this->lang}) && $content->image->{$this->lang} ? $content->image->{$this->lang} : array_values((array) $content->image)[0] ?? '');
}
else if (is_string($content->image)) {
$image = $content->image;
}
$content->image = ($image ? static::assetLinkDetermine($image) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($image, $pageData['badress']);
$content_title = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
$content_title = self::getPriceHolders($content_title);
$content_content = (isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : array_values((array) $content->content)[0] ?? '');
$content_content = self::getPriceHolders($content_content);
$content_link = (isset($content->link->{$this->lang}) && $content->link->{$this->lang} ? $content->link->{$this->lang} : array_values((array) $content->link)[0] ?? '');
$content_button_text = (isset($content->button_text->{$this->lang}) && $content->button_text->{$this->lang} ? $content->button_text->{$this->lang} : array_values((array) $content->button_text)[0] ?? '');
$image_alt = (isset($content->image_alt->{$this->lang}) && $content->image_alt->{$this->lang} ? $content->image_alt->{$this->lang} : (isset($content->image_alt) ? array_values((array) $content->image_alt)[0] ?? '' : ''));
$image_title = (isset($content->image_title->{$this->lang}) && $content->image_title->{$this->lang} ? $content->image_title->{$this->lang} : (isset($content->image_title) ? array_values((array) $content->image_title)[0] ?? '' : ''));
$link_rel = (isset($content->link_rel) && $content->link_rel ? $content->link_rel : []);
$link_rel = ($link_rel ? ' rel="' . implode(' ', $link_rel) . '" ' : '');
if (empty($image_alt)) {
if (!empty($content_title)) {
$image_alt = $content_title;
}
else if (!empty($image_title)) {
$image_alt = $image_title;
}
else {
$image_alt = basename($content->image);
}
}
if (empty($image_title)) {
if (!empty($title)) {
$image_title = $title;
}
else if (!empty($image_alt)) {
$image_title = $image_alt;
}
else {
$image_title = basename($content->image);
}
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-feature-box-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'feature_box' . DS . 'style_' . $content->widget_style . '.php';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function flipbox_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$front_text = (isset($content->front_text) && isset($content->front_text->{$this->lang}) && $content->front_text->{$this->lang} ? $content->front_text->{$this->lang} : (isset($content->front_text) ? array_values((array) $content->front_text)[0] ?? '' : ''));
$front_align = (isset($content->front_align) && $content->front_align ? $content->front_align : 'center_center');
$front_text_color = (isset($content->front_text_color) && $content->front_text_color ? $content->front_text_color : '');
$front_bg_type = (isset($content->front_bg_type) && $content->front_bg_type ? $content->front_bg_type : 'color');
$front_bg_color = (isset($content->front_bg_color) && $content->front_bg_color ? $content->front_bg_color : '');
$front_bg_image = (isset($content->front_bg_image) && isset($content->front_bg_image->{$this->lang}) && $content->front_bg_image->{$this->lang} ? $content->front_bg_image->{$this->lang} : (isset($content->front_bg_image) ? array_values((array) $content->front_bg_image)[0] ?? '' : ''));
$front_bg_image = ($front_bg_image ? static::assetLinkDetermine($front_bg_image) : $lazyPlaceholder);
$front_bg_gradient = (isset($content->front_bg_gradient) && $content->front_bg_gradient ? $content->front_bg_gradient : '');
$front_border = (isset($content->front_border) && $content->front_border ? $content->front_border : '');
$front_radius = (isset($content->front_radius) && $content->front_radius ? $content->front_radius : 0);
$front_shadow = (isset($content->front_shadow) && $content->front_shadow ? $content->front_shadow : '');
$back_text = (isset($content->back_text) && isset($content->back_text->{$this->lang}) && $content->back_text->{$this->lang} ? $content->back_text->{$this->lang} : (isset($content->back_text) ? array_values((array) $content->back_text)[0] ?? '' : ''));
$back_align = (isset($content->back_align) && $content->back_align ? $content->back_align : 'center_center');
$back_text_color = (isset($content->back_text_color) && $content->back_text_color ? $content->back_text_color : '');
$back_bg_type = (isset($content->back_bg_type) && $content->back_bg_type ? $content->back_bg_type : 'color');
$back_bg_color = (isset($content->back_bg_color) && $content->back_bg_color ? $content->back_bg_color : '');
$back_bg_image = (isset($content->back_bg_image) && isset($content->back_bg_image->{$this->lang}) && $content->back_bg_image->{$this->lang} ? $content->back_bg_image->{$this->lang} : (isset($content->back_bg_image) ? array_values((array) $content->back_bg_image)[0] ?? '' : ''));
$back_bg_image = ($back_bg_image ? static::assetLinkDetermine($back_bg_image) : $lazyPlaceholder);
$back_bg_gradient = (isset($content->back_bg_gradient) && $content->back_bg_gradient ? $content->back_bg_gradient : '');
$back_border = (isset($content->back_border) && $content->back_border ? $content->back_border : '');
$back_radius = (isset($content->back_radius) && $content->back_radius ? $content->back_radius : 0);
$back_shadow = (isset($content->back_shadow) && $content->back_shadow ? $content->back_shadow : '');
$flip_behavior = (isset($content->flip_behavior) && $content->flip_behavior ? $content->flip_behavior : 'hover');
$flip_style = (isset($content->flip_style) && $content->flip_style ? $content->flip_style : 'rotate');
$flip_direction = (isset($content->flip_direction) && $content->flip_direction ? $content->flip_direction : 'left');
$height = (isset($content->height) && $content->height ? $content->height : '280');
$fon_class = (isset($content->fon_class) && $content->fon_class ? $content->fon_class : '');
$style = '';
if (is_object($height)) {
$responsiveItems = [
'.fon-flipbox-panel' . ($flip_style == '3d' ? '-3d' : '') => [
['type' => 'height', 'unit' => 'px', 'value' => $height]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
else {
$style .= '#' . $widgetId . ' .fon-flipbox-panel' . ($flip_style == '3d' ? '-3d' : '') . '{';
$style .= 'height:' . $height . 'px;';
$style .= '}';
}
$style .= '#' . $widgetId . ' .fon-flipbox-front' . ($flip_style == '3d' ? '-3d' : '') . '{';
if ($front_text_color) {
$style .= 'color: ' . $front_text_color . ';';
}
if ($front_border) {
$style .= 'border: ' . $front_border . ';';
}
if ($front_radius) {
$style .= 'border-radius: ' . $front_radius . 'px;';
}
if ($front_shadow) {
$style .= 'box-shadow: ' . $front_shadow . ';';
}
if ($front_bg_type == 'color') {
$style .= 'background-color: ' . $front_bg_color . ';';
}
else if ($front_bg_type == 'image') {
$style .= 'background-color: ' . $front_bg_color . ';';
$style .= 'background-image: url(' . $front_bg_image . ');';
}
else if ($front_bg_type == 'gradient') {
$style .= 'background-color: ' . $front_bg_color . ';';
$style .= self::parseGradient($front_bg_gradient) . ';';
}
switch ($front_align) {
case 'top_left':
$style .= 'justify-content: start;';
$style .= 'text-align: start;';
break;
case 'top_center':
$style .= 'justify-content: start;';
$style .= 'text-align: center;';
break;
case 'top_right':
$style .= 'justify-content: start;';
$style .= 'text-align: end;';
break;
case 'center_left':
$style .= 'justify-content: center;';
$style .= 'text-align: start;';
break;
case 'center_center':
$style .= 'justify-content: center;';
$style .= 'text-align: center;';
break;
case 'center_right':
$style .= 'justify-content: center;';
$style .= 'text-align: end;';
break;
case 'bottom_left':
$style .= 'justify-content: end;';
$style .= 'text-align: start;';
break;
case 'bottom_center':
$style .= 'justify-content: end;';
$style .= 'text-align: center;';
break;
case 'bottom_right':
$style .= 'justify-content: end;';
$style .= 'text-align: end;';
break;
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-flipbox-back' . ($flip_style == '3d' ? '-3d' : '') . '{';
if ($back_text_color) {
$style .= 'color: ' . $back_text_color . ';';
}
if ($back_border) {
$style .= 'border: ' . $back_border . ';';
}
if ($back_radius) {
$style .= 'border-radius: ' . $back_radius . 'px;';
}
if ($back_shadow) {
$style .= 'box-shadow: ' . $back_shadow . ';';
}
if ($back_bg_type == 'color') {
$style .= 'background-color: ' . $back_bg_color . ';';
}
else if ($back_bg_type == 'image') {
$style .= 'background-color: ' . $back_bg_color . ';';
$style .= 'background-image: url(' . $back_bg_image . ');';
}
else if ($back_bg_type == 'gradient') {
$style .= 'background-color: ' . $back_bg_color . ';';
$style .= self::parseGradient($back_bg_gradient) . ';';
}
switch ($back_align) {
case 'top_left':
$style .= 'justify-content: start;';
$style .= 'text-align: start;';
break;
case 'top_center':
$style .= 'justify-content: start;';
$style .= 'text-align: center;';
break;
case 'top_right':
$style .= 'justify-content: start;';
$style .= 'text-align: end;';
break;
case 'center_left':
$style .= 'justify-content: center;';
$style .= 'text-align: start;';
break;
case 'center_center':
$style .= 'justify-content: center;';
$style .= 'text-align: center;';
break;
case 'center_right':
$style .= 'justify-content: center;';
$style .= 'text-align: end;';
break;
case 'bottom_left':
$style .= 'justify-content: end;';
$style .= 'text-align: start;';
break;
case 'bottom_center':
$style .= 'justify-content: end;';
$style .= 'text-align: center;';
break;
case 'bottom_right':
$style .= 'justify-content: end;';
$style .= 'text-align: end;';
break;
}
$style .= '}';
if ($flip_style == '3d') {
$style .= '#' . $widgetId . ' .fon-flipbox-front-3d .fon-flipbox-inner-3d{';
switch ($front_align) {
case 'top_left':
case 'top_center':
case 'top_right':
$style .= 'top: 25px;';
break;
case 'center_left':
case 'center_center':
case 'center_right':
$style .= 'top: 50%;';
$style .= 'transform: translateY(-50%) translateZ(60px)';
break;
case 'bottom_left':
case 'bottom_center':
case 'bottom_right':
$style .= 'bottom: 25px;';
break;
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-flipbox-back-3d .fon-flipbox-inner-3d{';
switch ($back_align) {
case 'top_left':
case 'top_center':
case 'top_right':
$style .= 'top: 25px;';
break;
case 'center_left':
case 'center_center':
case 'center_right':
$style .= 'top: 50%;';
$style .= 'transform: translateY(-50%) translateZ(60px)';
break;
case 'bottom_left':
case 'bottom_center':
case 'bottom_right':
$style .= 'bottom: 25px;';
break;
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-flipbox flip-style-' . $flip_style . ' flip-direction-' . $flip_direction . ' flip-on-' . $flip_behavior . ' ' . $fon_class . '">';
$output .= '<div class="fon-flipbox-panel' . ($flip_style == '3d' ? '-3d' : '') . '">';
if ($flip_style == '3d') {
$output .= '<div class="fon-flipbox-3d-item">';
}
$output .= '<div class="fon-flipbox-front' . ($flip_style == '3d' ? '-3d' : '') . ' flipbox">';
$output .= '<div class="fon-flipbox-inner' . ($flip_style == '3d' ? '-3d' : '') . '">';
$output .= $front_text;
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="fon-flipbox-back' . ($flip_style == '3d' ? '-3d' : '') . ' flipbox">';
$output .= '<div class="fon-flipbox-inner' . ($flip_style == '3d' ? '-3d' : '') . '">';
$output .= $back_text;
$output .= '</div>';
$output .= '</div>';
if ($flip_style == '3d') {
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function formbuilder_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$email_addresses = Config::get('contact/email-addresses');
$to_email = (isset($content->to_email) && $content->to_email ? $content->to_email : $email_addresses[0]);
$email_subject = (isset($content->email_subject) && $content->email_subject ? $content->email_subject : '');
$email_body = (isset($content->email_body) && $content->email_body ? $content->email_body : '');
$hide_labels = (isset($content->hide_labels) && $content->hide_labels == 'yes' ? 1 : 0);
$hidden_label_class = ($hide_labels ? 'visually-hidden' : '');
$floating_labels = (isset($content->floating_labels) && $content->floating_labels == 'yes' ? 1 : 0);
$captcha_status = (isset($content->enable_captcha) && $content->enable_captcha == 'yes' ? 1 : 0);
$enable_policy = (isset($content->enable_policy) && $content->enable_policy == 'yes' ? 1 : 0);
$enable_redirect = (isset($content->enable_redirect) && $content->enable_redirect == 'yes' ? 1 : 0);
$redirect_link = (isset($content->redirect_link->{$this->lang}) && $content->redirect_link->{$this->lang} ? $content->redirect_link->{$this->lang} : '');
$field_gap = (isset($content->field_gap) && $content->field_gap ? 'g-' . $content->field_gap : 'g-3');
$required_message = (isset($content->required_message->{$this->lang}) && $content->required_message->{$this->lang} ? $content->required_message->{$this->lang} : __('theme/formbuilder/required_message'));
$error_message = (isset($content->error_message->{$this->lang}) && $content->error_message->{$this->lang} ? $content->error_message->{$this->lang} : __('theme/formbuilder/error_message'));
$success_message = (isset($content->success_message->{$this->lang}) && $content->success_message->{$this->lang} ? $content->success_message->{$this->lang} : __('theme/formbuilder/success_message'));
$button_text = (isset($content->button_text->{$this->lang}) && $content->button_text->{$this->lang} ? $content->button_text->{$this->lang} : array_values((array) $content->button_text)[0] ?? '');
$button_position = (isset($content->button_position) && $content->button_position ? $content->button_position : 'end');
if (!$captcha_status && Config::get('options/captcha/status')) {
$captcha_status = Config::get('options/captcha/status');
}
if (!$captcha_status && Config::get('options/BotShield/status')) {
Helper::Load('BotShield');
$captcha_status = BotShield::is_blocked('contact');
}
if ($captcha_status) {
Helper::Load('Captcha');
$captcha = Helper::get('Captcha');
}
$style = '';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-label{';
if (isset($content->label_color) && $content->label_color) {
$style .= 'color: ' . $content->label_color . ';';
}
if (isset($content->label_font) && $content->label_font) {
$style .= self::parseFontProperties($content->label_font);
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-select, #' . $widgetId . ' .fon-formbuilder-form .form-control {';
if (isset($content->field_color) && $content->field_color->normal) {
$style .= 'color: ' . $content->field_color->normal . ';';
}
if (isset($content->field_background) && $content->field_background->normal) {
$style .= 'background-color: ' . $content->field_background->normal . ';';
}
if (isset($content->field_border_width) && $content->field_border_width->normal) {
$style .= 'border-width: ' . $content->field_border_width->normal . 'px;';
}
if (isset($content->field_border_color) && $content->field_border_color->normal) {
$style .= 'border-color: ' . $content->field_border_color->normal . ';';
}
if (isset($content->field_border_radius) && 0 < $content->field_border_radius) {
$style .= 'border-radius: ' . $content->field_border_radius . 'px;';
}
if (isset($content->field_padding) && $content->field_padding) {
$padding = '';
if (isset($content->field_padding->top) && $content->field_padding->top) {
$padding .= $content->field_padding->top . 'px ';
}
if (isset($content->field_padding->right) && $content->field_padding->right) {
$padding .= $content->field_padding->right . 'px ';
}
if (isset($content->field_padding->bottom) && $content->field_padding->bottom) {
$padding .= $content->field_padding->bottom . 'px ';
}
if (isset($content->field_padding->left) && $content->field_padding->left) {
$padding .= $content->field_padding->left . 'px ';
}
if ($padding) {
$style .= 'padding: ' . $padding . ';';
}
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-select:hover,#' . $widgetId . ' .fon-formbuilder-form .form-select:focus, #' . $widgetId . ' .fon-formbuilder-form .form-control:hover, #' . $widgetId . ' .fon-formbuilder-form .form-control:active, #' . $widgetId . ' .fon-formbuilder-form .form-control:focus{';
if (isset($content->field_color) && $content->field_color->hover) {
$style .= 'color: ' . $content->field_color->hover . ';';
}
if (isset($content->field_background) && $content->field_background->hover) {
$style .= 'background-color: ' . $content->field_background->hover . ';';
}
if (isset($content->field_border_width) && $content->field_border_width->hover) {
$style .= 'border-width: ' . $content->field_border_width->hover . 'px!important;';
}
if (isset($content->field_border_color) && $content->field_border_color->hover) {
$style .= 'border-color: ' . $content->field_border_color->hover . '!important;';
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-select, #' . $widgetId . ' .fon-formbuilder-form .input-icon .from-control{';
if (isset($content->field_padding) && $content->field_padding) {
$padding = 0;
if (isset($content->field_padding->left) && $content->field_padding->left) {
$padding = $content->field_padding->left;
}
else if (isset($content->field_padding->right) && $content->field_padding->right) {
$padding = $content->field_padding->right;
}
$style .= 'padding-left: ' . ($padding + 30) . 'px;';
}
$style .= '}';
if (!$floating_labels) {
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-control:placeholder{';
if (isset($content->field_placeholder) && $content->field_placeholder->normal) {
$style .= 'color: ' . $content->field_placeholder->normal . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .form-control:hover::placeholder{';
if (isset($content->field_placeholder) && $content->field_placeholder->hover) {
$style .= 'color: ' . $content->field_placeholder->hover . ';';
}
$style .= '}';
}
if (isset($content->radio_color) && $content->radio_color) {
$style .= '#' . $widgetId . ' .fon-formbuilder-form input[type="radio"].form-check-input:checked{';
$style .= 'border-color: ' . $content->radio_color . ';';
$style .= 'background-color: ' . $content->radio_color . ';';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form input[type="radio"]:hover, #' . $widgetId . ' .fon-formbuilder-form input[type="radio"]:focus{';
$style .= 'border-color: ' . $content->radio_color . ';';
$style .= '}';
}
if (isset($content->checkbox_color) && $content->checkbox_color) {
$style .= '#' . $widgetId . ' .fon-formbuilder-form input[type="checkbox"].form-check-input:checked{';
$style .= 'border-color: ' . $content->checkbox_color . ';';
$style .= 'background-color: ' . $content->checkbox_color . ';';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form input[type="checkbox"]:hover,#' . $widgetId . ' .fon-formbuilder-form input[type="checkbox"]:focus{';
$style .= 'border-color: ' . $content->checkbox_color . ';';
$style .= '}';
}
$style .= '#' . $widgetId . ' .fon-formbuilder-form .input-group .input-group-text{';
if (isset($content->input_group_color) && $content->input_group_color->normal) {
$style .= 'color: ' . ($content->input_group_color->normal ?? 'var(--bs-body-color)') . ';';
}
if (isset($content->input_group_bg) && $content->input_group_bg->normal) {
$style .= 'background-color: ' . ($content->input_group_bg->normal ?? 'var(--bs-body-color)') . ';';
}
if (isset($content->field_border_width) && $content->field_border_width->normal) {
$style .= 'border-width: ' . $content->field_border_width->normal . 'px;';
}
if (isset($content->field_border_color) && $content->field_border_color->normal) {
$style .= 'border-color: ' . $content->field_border_color->normal . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-formbuilder-form .input-group:hover .input-group-text{';
if (isset($content->input_group_color) && $content->input_group_color->hover) {
$style .= 'color: ' . ($content->input_group_color->hover ?? 'var(--bs-body-color)') . ';';
}
if (isset($content->input_group_bg) && $content->input_group_bg->hover) {
$style .= 'background-color: ' . ($content->input_group_bg->hover ?? 'var(--bs-body-color)') . ';';
}
if (isset($content->field_border_width) && $content->field_border_width->hover) {
$style .= 'border-width: ' . $content->field_border_width->hover . 'px!important;';
}
if (isset($content->field_border_color) && $content->field_border_color->hover) {
$style .= 'border-color: ' . $content->field_border_color->hover . '!important;';
}
$style .= '}';
if (isset($content->field_background) && $content->field_background->hover) {
$style .= '#' . $widgetId . ' form-floating>.form-control-plaintext~label::after, .form-floating>.form-control:focus~label::after, .form-floating>.form-control:not(:placeholder-shown)~label::after, .form-floating>.form-select~label::after {';
$style .= 'background-color: ' . $content->field_background->hover . ';';
$style .= '}';
}
$style .= "\n" . ' .fon-website-field {' . "\n" . ' opacity: 0;' . "\n" . ' position: absolute;' . "\n" . ' top: 0;' . "\n" . ' left: 0;' . "\n" . ' height: 0;' . "\n" . ' width: 0;' . "\n" . ' z-index: -1;' . "\n" . ' overflow: hidden;' . "\n" . ' }' . "\n" . ' ';
if ($content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-formbuilder-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$output .= '<form class="fon-formbuilder-form row ' . $field_gap . ' needs-validation" ' . ($enable_redirect && $redirect_link != '' ? 'data-redirect="true" data-redirect-link="' . $redirect_link . '"' : '') . ' method="post" action="' . APP_URI . '/addon/FonPageBuilder" id="fon-' . $moduleId . '" novalidate>';
if (isset($content->items) && is_array($content->items)) {
$increated_id = mt_rand(100000, 999999);
foreach ($content->items as $item_key => $item_value) {
if ($increated_id === $increated_id) {
++$increated_id;
}
$field_type = (isset($item_value->field_type) && $item_value->field_type ? $item_value->field_type : 'text');
$field_name = (isset($item_value->field_name) && $item_value->field_name ? $item_value->field_name : '');
$field_title = (isset($item_value->field_title->{$this->lang}) && $item_value->field_title->{$this->lang} ? $item_value->field_title->{$this->lang} : array_values((array) $item_value->field_title)[0] ?? '');
$field_placeholder = (isset($item_value->field_placeholder->{$this->lang}) && $item_value->field_placeholder->{$this->lang} ? $item_value->field_placeholder->{$this->lang} : array_values((array) $item_value->field_title)[0] ?? '');
$field_is_required = (isset($item_value->field_is_required) && $item_value->field_is_required == 'yes' ? true : false);
$field_required_star = (isset($item_value->field_required_star) && $item_value->field_required_star == 'yes' ? true : false);
$item_name_id = ($field_type ? 'fon-formbuilder-field-' . $item_key . '-' . $moduleId : '');
$field_number_min = (isset($item_value->field_number_min) && $item_value->field_number_min != '' ? $item_value->field_number_min : '');
$field_number_max = (isset($item_value->field_number_max) && $item_value->field_number_max ? $item_value->field_number_max : '');
$field_number_step = (isset($item_value->field_number_step) && $item_value->field_number_step ? $item_value->field_number_step : '');
$field_height = (isset($item_value->field_height) && $item_value->field_height ? $item_value->field_height . 'px' : '100px');
$field_is_resize = (isset($item_value->field_is_resize) && $item_value->field_is_resize == 'yes' ? true : false);
$field_min_character = (isset($item_value->field_min_character) && $item_value->field_min_character ? ' minlength = ' . $item_value->field_min_character : '');
$field_max_character = (isset($item_value->field_max_character) && $item_value->field_max_character ? ' maxlength = ' . $item_value->field_max_character : '');
$field_width = (isset($item_value->field_width) && $item_value->field_width ? $item_value->field_width : (object) ['xl=>12', 'lg=>12', 'md=>12', 'sm=>12', 'xs=>12']);
$field_width_class = 'col-' . $field_width->xs . ' col-sm-' . $field_width->sm . ' col-md-' . $field_width->md . ' col-lg-' . $field_width->lg . ' col-xl-' . $field_width->xl;
$field_inline = (isset($item_value->field_inline) && $item_value->field_inline == 'yes' ? true : false);
$field_hide_label = (isset($item_value->field_hide_label) && $item_value->field_hide_label == 'yes' ? true : false);
$field_show_icon = (isset($item_value->field_show_icon) && $item_value->field_show_icon == 'yes' ? true : false);
$field_icon = (isset($item_value->field_icon) && $item_value->field_icon ? $item_value->field_icon : '');
if ($field_type == 'radio') {
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$field_hide_label) {
$output .= '<label class="form-label ' . $hidden_label_class . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
$output .= '<div class="fon-formbuilder-radio-content">';
if (isset($item_value->field_radio_items) && is_array($item_value->field_radio_items)) {
$inner_values = $item_value->field_radio_items;
foreach ($inner_values as $inner_item_key => $inner_item_value) {
$inner_item_value_title = (isset($inner_item_value->title->{$this->lang}) && $inner_item_value->title->{$this->lang} ? $inner_item_value->title->{$this->lang} : array_values((array) $inner_item_value->title)[0] ?? '');
if ($inner_item_value_title) {
$output .= '<div class="form-check ' . ($field_inline ? 'form-check-inline' : '') . '">';
$inner_item_id = 'fon-form-' . $increated_id . '-radio-' . $inner_item_key;
$is_radio_checked = (isset($inner_item_value->is_checked) && $inner_item_value->is_checked == '1' ? true : false);
$output .= '<input type="radio" name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']" id="' . $inner_item_id . '" value="' . $inner_item_value->value . '" class="form-check-input"' . ($is_radio_checked ? ' checked' : '') . '' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
$output .= '<label for="' . $inner_item_id . '" class="form-check-label">' . $inner_item_value_title . '</label>';
$output .= '</div>';
}
}
}
$output .= ($field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
$output .= '</div>';
$output .= '</div>';
}
else if ($field_type === 'checkbox') {
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$field_hide_label) {
$output .= '<label class="form-label ' . $hidden_label_class . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
$output .= '<div class="fon-formbuilder-checkbox-content">';
if (isset($item_value->field_checkbox_items) && is_array($item_value->field_checkbox_items)) {
$inner_values = $item_value->field_checkbox_items;
$checkbocFieldName = 'formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']';
if (is_array($inner_values) && 1 < count($inner_values)) {
$checkbocFieldName .= '[]';
}
foreach ($inner_values as $inner_item_key => $inner_item_value) {
$inner_item_value_title = (isset($inner_item_value->title->{$this->lang}) && $inner_item_value->title->{$this->lang} ? $inner_item_value->title->{$this->lang} : array_values((array) $inner_item_value->title)[0] ?? '');
if ($inner_item_value_title) {
$output .= '<div class="form-check ' . ($field_inline ? 'form-check-inline' : '') . '">';
$inner_item_id = 'fon-form-' . $increated_id . '-checkbox-' . $inner_item_key;
$is_checkbox_checked = (isset($inner_item_value->is_checked) && $inner_item_value->is_checked == '1' ? true : false);
$output .= '<input type="checkbox" name="' . $checkbocFieldName . '" id="' . $inner_item_id . '" value="' . $inner_item_value->value . '" class="form-check-input ' . (1 < count($inner_values) ? 'multiple' : '') . '"' . ($is_checkbox_checked ? ' checked' : '') . '' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
$output .= '<label for="' . $inner_item_id . '" class="form-check-label">' . $inner_item_value_title . '</label>';
$output .= '</div>';
}
}
}
$output .= ($field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
$output .= '</div>';
$output .= '</div>';
}
else if ($field_type == 'textarea') {
$invalidMessage = [];
if ($field_is_required) {
$invalidMessage[] = __('theme/required_field');
}
if ($field_min_character != '') {
$invalidMessage[] = sprintf(__('theme/required_field_min_char'), $item_value->field_min_character);
}
if ($field_max_character != '') {
$invalidMessage[] = sprintf(__('theme/required_field_max_char'), $item_value->field_max_character);
}
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($field_show_icon && $field_icon) {
$output .= '<div class="input-group ' . ($field_is_required ? 'has-validation' : '') . '">';
$output .= '<span class="input-group-text"><i class="' . $field_icon . '"></i></span>';
}
if ($floating_labels) {
$output .= '<div class="form-floating">';
}
$output .= '<textarea name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']" id="' . $item_name_id . '" rows="5" class="form-control' . ($field_is_resize ? '' : ' not-resize') . '" placeholder="' . ($field_placeholder && !$floating_labels ? $field_placeholder : $field_title) . '" ' . ($field_is_required ? ' aria-required="true" required' : '') . $field_max_character . $field_min_character . ' style="height:' . $field_height . '"></textarea>';
if ($field_title && $floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if (!$floating_labels && $field_is_required || $field_min_character != '' || $field_max_character != '') {
$output .= '<div class="invalid-feedback">' . implode(', ', $invalidMessage) . '</div>';
}
if ($floating_labels) {
$output .= '</div>';
if ($field_is_required || $field_min_character != '' || $field_max_character != '') {
$output .= '<div class="invalid-feedback">' . implode(', ', $invalidMessage) . '</div>';
}
}
if ($field_show_icon && $field_icon) {
$output .= '</div>';
}
$output .= '</div>';
}
else if ($field_type == 'select') {
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($field_show_icon && $field_icon) {
$output .= '<div class="input-group ' . ($field_is_required ? 'has-validation' : '') . '">';
$output .= '<span class="input-group-text"><i class="' . $field_icon . '"></i></span>';
}
if ($floating_labels) {
$output .= '<div class="form-floating">';
}
if (isset($item_value->field_select_items) && is_array($item_value->field_select_items)) {
$inner_values = $item_value->field_select_items;
$output .= '<select class="form-select" name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']" id="' . $item_name_id . '"' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
$output .= ($field_placeholder ? '<option value="">' . $field_placeholder . '</option>' : '');
foreach ($inner_values as $inner_item_key => $inner_item_value) {
$inner_item_value_title = (isset($inner_item_value->title->{$this->lang}) && $inner_item_value->title->{$this->lang} ? $inner_item_value->title->{$this->lang} : array_values((array) $inner_item_value->title)[0] ?? '');
if ($inner_item_value_title) {
$is_checked = (isset($inner_item_value->is_checked) && $inner_item_value->is_checked == '1' ? true : false);
$output .= '<option value="' . $inner_item_value->value . '"' . ($is_checked ? ' selected' : '') . '>' . $inner_item_value_title . '</option>';
}
}
$output .= '</select>';
$output .= (!$floating_labels && $field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
}
if ($field_title && $floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($floating_labels) {
$output .= '</div>';
$output .= ($field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
}
if ($field_show_icon && $field_icon) {
$output .= '</div>';
}
$output .= '</div>';
}
else if ($field_type == 'number') {
$invalidMessage = [];
if ($field_is_required) {
$invalidMessage[] = __('theme/required_field');
}
if ($field_number_min != '') {
$invalidMessage[] = sprintf(__('theme/required_field_min'), $field_number_min);
}
if ($field_number_max != '') {
$invalidMessage[] = sprintf(__('theme/required_field_max'), $field_number_max);
}
if ($field_number_step != '') {
$invalidMessage[] = sprintf(__('theme/required_field_step'), $field_number_step);
}
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($field_show_icon && $field_icon) {
$output .= '<div class="input-group ' . ($field_is_required ? 'has-validation' : '') . '">';
$output .= '<span class="input-group-text"><i class="' . $field_icon . '"></i></span>';
}
if ($floating_labels) {
$output .= '<div class="form-floating">';
}
$output .= '<input type="number" id="' . $item_name_id . '" name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']" class="form-control"' . ($field_number_min != '' ? ' min="' . $field_number_min . '"' : '') . '' . ($field_number_max ? ' max="' . $field_number_max . '"' : '') . '' . ($field_number_step ? ' step="' . $field_number_step . '"' : '') . ' placeholder="' . ($field_placeholder && !$floating_labels ? $field_placeholder : $field_title) . '" ' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
if (!$floating_labels && $field_is_required || $field_number_min != '' || $field_number_max != '' || $field_number_step != '') {
$output .= '<div class="invalid-feedback">' . implode(', ', $invalidMessage) . '</div>';
}
if ($field_title && $floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($floating_labels) {
$output .= '</div>';
if ($field_is_required || $field_number_min != '' || $field_number_max != '' || $field_number_step != '') {
$output .= '<div class="invalid-feedback">' . implode(', ', $invalidMessage) . '</div>';
}
}
if ($field_show_icon && $field_icon) {
$output .= '</div>';
}
$output .= '</div>';
}
else if ($field_type == 'title') {
$font_style = self::parseFontProperties($item_value->heading_font);
$item_unique_class = 'fon-formbuilder-heading-' . $item_key;
$heading_selector = (isset($item_value->heading_selector) && $item_value->heading_selector ? $item_value->heading_selector : 'h3');
$output .= '<' . $heading_selector . ' class="fon-widget-title ' . $item_unique_class . '" style="' . $font_style . '">';
$output .= $field_title;
$output .= '</' . $heading_selector . '>';
}
else {
$output .= '<div class="' . $field_width_class . ' ' . $item_name_id . '">';
if ($field_title && !$floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($field_show_icon && $field_icon && !in_array($field_type, ['date' => true, 'time' => true, 'date-time' => true, 'tel' => true])) {
$output .= '<div class="input-group ' . ($field_is_required ? 'has-validation' : '') . '">';
$output .= '<span class="input-group-text"><i class="' . $field_icon . '"></i></span>';
}
if ($floating_labels) {
$output .= '<div class="form-floating">';
}
if ($field_type == 'tel') {
$output .= '<input type="hidden" id="' . $item_name_id . '-hidden" name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']"/>';
$output .= '<input type="' . $field_type . '" id="' . $item_name_id . '" class="form-control" placeholder="' . ($field_placeholder && !$floating_labels ? $field_placeholder : $field_title) . '" ' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
}
else {
$output .= '<input type="' . $field_type . '" id="' . $item_name_id . '" name="formbuilder[' . $field_name . '' . ($field_is_required ? '*' : '') . ']" class="form-control" placeholder="' . ($field_placeholder && !$floating_labels ? $field_placeholder : $field_title) . '" ' . ($field_is_required ? ' aria-required="true" required' : '') . '>';
}
$output .= (!$floating_labels && $field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
if ($field_title && $floating_labels) {
$output .= '<label class="form-label ' . $hidden_label_class . '" for="' . $item_name_id . '">' . $field_title . '' . ($field_required_star && $field_is_required ? '<span class="fon-field-required text-danger"> *</span>' : '') . '</label>';
}
if ($floating_labels) {
$output .= '</div>';
$output .= ($field_is_required ? '<div class="invalid-feedback">' . __('theme/required_field') . '</div>' : '');
}
if ($field_show_icon && $field_icon && !in_array($field_type, ['date' => true, 'time' => true, 'date-time' => true, 'tel' => true])) {
$output .= '</div>';
}
if ($field_type == 'email') {
$output .= '<input type="hidden" name="email_field" value="' . $field_name . '" >';
}
$output .= '</div>';
}
}
}
$required_fields_list = [];
if (isset($content->items) && is_array($content->items)) {
foreach ($content->items as $item) {
$is_req = isset($item->field_is_required) && $item->field_is_required == 'yes';
if ($is_req) {
$required_fields_list[] = $item->field_name;
}
}
}
$hidden_fields = ['to_email' => base64_encode($to_email), 'req_fields' => $required_fields_list];
$hidden_fields_json = json_encode($hidden_fields);
$hiddenFields = Crypt::encode($hidden_fields_json, Config::get('crypt/system'));
$salt_key = md5('e5i6t8sev0e3ne2sur6mvpl3tx6oz2608u8llzr8w1czagy0jxff' . $hiddenFields);
$output .= '<input type="hidden" name="form_features" value="' . $hiddenFields . ':' . $salt_key . '" >';
$output .= '<input type="hidden" name="form_id" value="fon-' . $moduleId . '">';
$output .= '<input type="hidden" name="email_subject" value="' . Crypt::encode($email_subject, Config::get('crypt/system')) . '">';
$output .= '<textarea style="display:none;" name="email_body" aria-label="Not For Read">' . Crypt::encode($email_body, Config::get('crypt/system')) . '</textarea>';
$output .= '<input type="hidden" name="success_message" value="' . Crypt::encode($success_message, Config::get('crypt/system')) . '">';
$output .= '<input type="hidden" name="error_message" value="' . Crypt::encode($error_message, Config::get('crypt/system')) . '">';
$output .= '<input type="hidden" name="module_operation" value="ajax_form_submit">';
$output .= '<input type="hidden" name="lang" value="' . $this->lang . '">';
$output .= '<input type="hidden" name="enable_captcha" value="' . $captcha_status . '">';
$honeypot_name = 'formbuilder_' . md5(uniqid(mt_rand(), true));
Session::set('formbuilder_honeypot_name', $honeypot_name, true);
$output .= '<input type="hidden" name="' . $honeypot_name . '" value="">';
$output .= Validation::get_csrf_token('formbuilder_form');
$encrypted_time = Crypt::encode(time(), Config::get('crypt/system'));
$output .= '<input type="hidden" name="form_loaded_at" value="' . $encrypted_time . '">';
if (isset($captcha) && $captcha) {
$output .= '<div class="' . ($captcha->input ? 'mb-3' : '') . '">';
$output .= '<div class="input-group has-validation">';
$output .= '<span class="input-group-text p-0 border-0 overflow-hidden">' . $captcha->getOutput() . '</span>';
if ($captcha->input) {
$output .= '<input name="' . $captcha->input_name . '" type="text" class="form-control" aria-label="' . ___('needs/form-captcha-label') . '" placeholder="' . ___('needs/form-captcha-label') . '" required>';
$output .= '<div class="invalid-feedback">' . __('theme/required_field') . '</div>';
}
$output .= '</div>';
$output .= '</div>';
}
if ($enable_policy || Config::get('options/gdpr-status')) {
$output .= '<div class="form-check">';
$output .= '<input class="form-check-input" type="checkbox" name="policy" id="policy-' . $widgetId . '" value="Yes" aria-required="true" required onchange="if($(this).prop(\'checked\')) {$(\'#fon-btn-' . $moduleId . '\').removeClass(\'disabled\').removeAttr(\'role aria-disabled\')} else {$(\'#fon-btn-' . $moduleId . '\').addClass(\'disabled\').attr({\'role\':\'button\',\'aria-disabled\':\'true\'});}">';
$output .= '<label class="form-check-label fs-12" for="policy-' . $widgetId . '">' . __('website/account_info/gdpr-tx4', ['{link}' => Controllers::$init->CRLink('contract2')]) . '</label>';
$output .= '<input type="hidden" value="true" name="is_policy">';
$output .= '</div>';
}
if ($button_text) {
$output .= '<div class="fon-formbuilder-btn text-' . $button_position . '">';
$btnProperties = ['is_btn' => true, 'type' => 'submit', 'disabled' => ($enable_policy || Config::get('options/gdpr-status') ? 'true' : 'false')];
$output .= $this->parseButton($content, $moduleId, $pageData, $btnProperties);
$output .= '</div>';
}
$output .= '<div class="fon-website-field" aria-hidden="true">' . "\n" . ' <label for="website_control">Website</label>' . "\n" . ' <input type="text" id="website_control" name="website_control" tabindex="-1" autocomplete="off">' . "\n" . ' </div>';
$output .= '</form>';
$output .= '<div style="display:none;margin-top:10px;" class="fon-formbuilder-ajax-status"></div>';
$output .= '</div>';
$output .= '</div>';
$this->addAsset('intlTelInput');
$ipInfo = UserManager::ip_info();
$countryCode = ($ipInfo && isset($ipInfo['countryCode']) ? $ipInfo['countryCode'] : ___('package/code'));
if (!$countryCode || strlen($countryCode) !== 2) {
$countryCode = 'TR';
}
$captchaJs = (isset($captcha) && $captcha ? $captcha->submit_after_js() : '');
$selectedLangJs = (Language::selected() == 'tr' ? 'Ara' : 'Search');
$pendingText = addslashes(__('website/others/button1-pending'));
$js = ' <script>' . "\n" . ' function ' . $moduleId . '_submit(result){' . "\n" . ' ' . $captchaJs . "\n" . ' if(result != ""){' . "\n" . ' var solve = typeof result === "string" ? getJson(result) : result;' . "\n" . ' if(solve !==false && solve != undefined && typeof(solve) == "object"){ ' . "\n" . ' if(solve.status == "error"){' . "\n" . ' if(solve.for != undefined && solve.for != ""){' . "\n" . ' $("#fon-' . $moduleId . '").removeClass("was-validated");' . "\n" . ' $("#fon-' . $moduleId . ' " +solve.for).focus();' . "\n" . ' $("#fon-' . $moduleId . ' " +solve.for).addClass("is-invalid");' . "\n" . ' $("#fon-' . $moduleId . ' " +solve.for).parent(".form-floating").addClass("is-invalid");' . "\n" . ' $("#fon-' . $moduleId . ' " +solve.for).change(function(){' . "\n" . ' $(this).removeClass("is-invalid");' . "\n" . ' $(this).parent(".form-floating").removeClass("is-invalid");' . "\n" . ' });' . "\n" . ' }' . "\n" . ' if(solve.fors != undefined && solve.fors.length > 0){' . "\n" . ' $("#fon-' . $moduleId . '").removeClass("was-validated");' . "\n" . ' for (var i = 0; i < solve.fors.length; i++) {' . "\n" . ' $(\'#fon-' . $moduleId . ' [name="formbuilder[\' +solve.fors[i] + \']"]\').addClass("is-invalid");' . "\n" . ' $(\'#fon-' . $moduleId . ' [name="formbuilder[\' +solve.fors[i] + \']"]\').parent(".form-floating").addClass("is-invalid");' . "\n" . ' $(\'#fon-' . $moduleId . ' [name="formbuilder[\' +solve.fors[i] + \']"]\').change(function(){' . "\n" . ' $(this).removeClass("is-invalid");' . "\n" . ' $(this).parent(".form-floating").removeClass("is-invalid");' . "\n" . ' });' . "\n" . ' }' . "\n" . ' }' . "\n" . ' alert_error(solve.message,{timer:3000});' . "\n" . ' }' . "\n" . ' else if(solve.status == "success"){ ' . "\n" . ' alert_success(solve.message,{timer:3000});' . "\n" . ' setTimeout(function(){' . "\n" . ' location.reload();' . "\n" . ' }, 3000);' . "\n" . ' }' . "\n" . ' }else {' . "\n" . ' console.log(result);' . "\n" . ' }' . "\n" . ' }' . "\n" . ' }' . "\n" . ' ' . "\n" . ' function initAllPhoneInputs() {' . "\n" . ' if (typeof window.intlTelInput !== "function") {' . "\n" . ' return;' . "\n" . ' }' . "\n" . ' if (window.allPhonesInitialized) return;' . "\n" . ' ' . "\n" . ' const telInputs = document.querySelectorAll(\'input[type="tel"]\');' . "\n" . ' if (telInputs.length === 0) {' . "\n" . ' return; ' . "\n" . ' }' . "\n" . ' ' . "\n" . ' const object_code = {' . "\n" . ' geoIpLookup: function (callback) {' . "\n" . ' callback("' . $countryCode . '");' . "\n" . ' },' . "\n" . ' autoPlaceholder: "on",' . "\n" . ' formatOnDisplay: true,' . "\n" . ' initialCountry: "auto", ' . "\n" . ' nationalMode: false,' . "\n" . ' placeholderNumberType: "MOBILE",' . "\n" . ' preferredCountries: ["tr","us", "gb", "ch", "ca", "de", "it"],' . "\n" . ' showSelectedDialCode: true,' . "\n" . ' countrySearch: true,' . "\n" . ' strictMode: true,' . "\n" . ' i18n: {' . "\n" . ' tr: "Türkiye",' . "\n" . ' searchPlaceholder: "' . $selectedLangJs . '"' . "\n" . ' },' . "\n" . ' useFullscreenPopup: false,' . "\n" . ' utilsScript: "' . $pageData['tadress'] . 'js/intltelinput/js/utils.js"' . "\n" . ' };' . "\n" . ' telInputs.forEach(function(input) {' . "\n" . ' if (input.getAttribute("data-intl-initialized") === "true") return;' . "\n" . ' ' . "\n" . ' input.setAttribute("data-intl-initialized", "true");' . "\n" . ' ' . "\n" . ' const iti = window.intlTelInput(input, object_code);' . "\n" . ' ' . "\n" . ' if (iti.promise) {' . "\n" . ' iti.promise.then(() => {' . "\n" . ' const hiddenInputId = input.id + "-hidden";' . "\n" . ' const hiddenInput = document.getElementById(hiddenInputId);' . "\n" . ' ' . "\n" . ' const updateHidden = () => {' . "\n" . ' if (hiddenInput) {' . "\n" . ' hiddenInput.value = iti.getNumber();' . "\n" . ' }' . "\n" . ' };' . "\n" . ' ' . "\n" . ' updateHidden();' . "\n" . ' input.addEventListener("input", updateHidden);' . "\n" . ' input.addEventListener("countrychange", updateHidden);' . "\n" . ' });' . "\n" . ' }' . "\n" . ' });' . "\n" . ' window.allPhonesInitialized = true;' . "\n" . ' }' . "\n" . ' var phoneInitInterval = setInterval(function() {' . "\n" . ' if (typeof window.intlTelInput === "function") {' . "\n" . ' initAllPhoneInputs();' . "\n" . ' if (window.allPhonesInitialized) {' . "\n" . ' clearInterval(phoneInitInterval);' . "\n" . ' }' . "\n" . ' }' . "\n" . ' }, 200);' . "\n" . ' ' . "\n" . ' $(document).ready(function(){' . "\n" . ' $("#fon-btn-' . $moduleId . '").on("click",function(e){' . "\n" . ' e.preventDefault();' . "\n" . ' var form = $("#fon-' . $moduleId . '");' . "\n" . ' if (!form[0].checkValidity()) {' . "\n" . ' e.preventDefault();' . "\n" . ' e.stopPropagation();' . "\n" . ' form.addClass("was-validated");' . "\n" . ' form.find(":invalid").parent(".form-floating").addClass("is-invalid");' . "\n" . ' return (alert_error("' . $required_message . '",{timer:3000}));' . "\n" . ' }' . "\n" . ' MioAjaxElement($(this),{' . "\n" . ' waiting_text: "' . $pendingText . '",' . "\n" . ' result:"' . $moduleId . '_submit",' . "\n" . ' });' . "\n" . ' });' . "\n" . ' if($("#fon-' . $moduleId . ' .form-check-input.multiple").length > 0){' . "\n" . ' var _requiredCheckboxes = $("#fon-' . $moduleId . ' .form-check-input.multiple:checkbox[required]");' . "\n" . ' _requiredCheckboxes.each(function (i, el) {' . "\n" . ' var _checkboxList = $(this).closest(".fon-formbuilder-checkbox-content");' . "\n" . ' ' . "\n" . ' if (!_checkboxList.hasClass("rqCheckboxList")) {' . "\n" . ' _checkboxList.addClass("rqCheckboxList");' . "\n" . ' }' . "\n" . ' });' . "\n" . ' ' . "\n" . ' var _requiredCheckboxLists = $(".rqCheckboxList");' . "\n" . ' ' . "\n" . ' _requiredCheckboxLists.each(function (i, el) {' . "\n" . ' var _checkboxList = $(this);' . "\n" . ' _checkboxList.on("change", "input[type=\\"checkbox\\"]", function (e) {' . "\n" . ' updateCheckboxesRequired($(this).parents(".rqCheckboxList"));' . "\n" . ' });' . "\n" . ' ' . "\n" . ' updateCheckboxesRequired(_checkboxList);' . "\n" . ' });' . "\n" . ' ' . "\n" . ' function updateCheckboxesRequired(_checkboxList) {' . "\n" . ' var _checkbox = _checkboxList.find("input[type=\\"checkbox\\"]").eq(0),' . "\n" . ' checkboxName = _checkbox.attr("name"),' . "\n" . ' checkboxNameAttr = "[name=\\"" + checkboxName + "\\"]",' . "\n" . ' _checkBoxes = _checkboxList.find("input[type=\\"checkbox\\"]" + checkboxNameAttr);' . "\n" . ' ' . "\n" . ' if (_checkboxList.find(checkboxNameAttr + ":checked").length > 0) {' . "\n" . ' _checkBoxes.prop("required", false);' . "\n" . ' } else {' . "\n" . ' _checkBoxes.prop("required", true);' . "\n" . ' }' . "\n" . ' }' . "\n" . ' }' . "\n" . ' ' . "\n" . ' ' . "\n" . ' });' . "\n" . ' ' . "\n" . ' </script>';
$this->addScript('footer', $pageData['page'], $js);
return $output;
}
private function gallery_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$uploadDir = RESOURCE_DIR . 'uploads' . DIRECTORY_SEPARATOR . 'fonpagebuilder';
$imageBaseDir = RESOURCE_DIR . 'uploads' . DIRECTORY_SEPARATOR . 'fonpagebuilder';
$thumbBaseDir = RESOURCE_DIR . 'uploads' . DIRECTORY_SEPARATOR . 'fongallerythumb';
$layout = (isset($content->layout) && $content->layout ? $content->layout : 'bootstrap');
$thumb_width = (isset($content->thumb_width) && $content->thumb_width ? (int) $content->thumb_width : 600);
$thumb_height = (isset($content->thumb_height) && $content->thumb_height ? (int) $content->thumb_height : 400);
$border_radius = (isset($content->border_radius) && $content->border_radius ? (int) $content->border_radius : 0);
$column = (isset($content->column) && $content->column ? (array) $content->column : ['xl' => 4, 'lg' => 4, 'md' => 3, 'sm' => 2, 'xs' => 2]);
$method = (isset($content->method) && $content->method ? $content->method : 'folder');
$folder = (isset($content->folder) && $content->folder ? trim((string) $content->folder) : '');
$items = (isset($content->items) && $content->items ? $content->items : []);
$fallbackImage = '/templates/website/Datawise/images/image-fallback.svg';
$gridXs = min(6, max(1, (int) ($column['xs'] ?? 2)));
$gridSm = min(6, max(1, (int) ($column['sm'] ?? 2)));
$gridMd = min(6, max(1, (int) ($column['md'] ?? 3)));
$gridLg = min(6, max(1, (int) ($column['lg'] ?? 4)));
$gridXl = min(6, max(1, (int) ($column['xl'] ?? 4)));
$gridRowClasses = sprintf('row g-3 row-cols-%d row-cols-sm-%d row-cols-md-%d row-cols-lg-%d row-cols-xl-%d', $gridXs, $gridSm, $gridMd, $gridLg, $gridXl);
if ($layout === 'slide') {
$gridRowClasses = 'flex-nowrap ' . $gridRowClasses;
}
$masonryColumnCounts = sprintf('--column-xs: %d; --column-sm: %d; --column-md: %d; --column-lg: %d; --column-xl: %d;', $gridXs, $gridSm, $gridMd, $gridLg, $gridXl);
$images = [];
if (($method == 'folder') && $folder) {
$folder = trim($this->sanitizeRelativePath($folder), '/');
$targetFolder = realpath($imageBaseDir . DIRECTORY_SEPARATOR . $folder);
$baseRealPath = realpath($uploadDir);
if ($targetFolder === false || $baseRealPath === false || strpos($targetFolder, $baseRealPath) !== 0) {
return '<div class="alert alert-danger">Klasör bulunamadı veya erişim izni yok.</div>';
}
$extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif'];
$files = scandir($targetFolder) ?: [];
foreach ($files as $fileName) {
if (($fileName === '.') || $fileName === '..') {
continue;
}
$fullPath = $targetFolder . DIRECTORY_SEPARATOR . $fileName;
if (!is_file($fullPath)) {
continue;
}
$extension = strtolower((string) pathinfo($fileName, PATHINFO_EXTENSION));
if (!in_array($extension, $extensions, true)) {
continue;
}
$imagePath = $folder . '/' . $fileName;
$thumbs = $this->buildGalleryThumbForImage($imagePath, $imageBaseDir, $thumbBaseDir, $thumb_width, $thumb_height);
$images[] = ['path' => static::assetLinkDetermine('resources/uploads/fonpagebuilder/' . $imagePath), 'title' => $this->buildGalleryPrettyTitle((string) pathinfo($fileName, PATHINFO_FILENAME)), 'thumb_crop' => static::assetLinkDetermine('resources/uploads/' . $thumbs['crop']), 'thumb_fit' => static::assetLinkDetermine('resources/uploads/' . $thumbs['fit'])];
}
}
else if (($method == 'images') && is_array($items)) {
foreach ($items as $item) {
if (isset($item->gallery_image) && $item->gallery_image) {
$imagePath = trim((string) $item->gallery_image);
if (preg_match('/^https?:\\/\\//i', $imagePath)) {
$thumbs = ['crop' => $imagePath, 'fit' => $imagePath];
}
else {
$search = 'resources/uploads/fonpagebuilder/';
$cleanPath = str_replace($search, '', ltrim($imagePath, '/'));
$thumbs = $this->buildGalleryThumbForImage($cleanPath, $imageBaseDir, $thumbBaseDir, $thumb_width, $thumb_height);
}
$title = '';
if (is_object($item->image_title)) {
$title = (isset($item->image_title->{$this->lang}) && $item->image_title->{$this->lang} ? $item->image_title->{$this->lang} : array_values((array) $item->image_title)[0] ?? '');
}
else if (is_string($item->image_title)) {
$title = $item->image_title;
}
$images[] = ['path' => static::assetLinkDetermine($imagePath), 'title' => ($title ? $title : $this->buildGalleryPrettyTitle((string) pathinfo($imagePath, PATHINFO_FILENAME))), 'thumb_crop' => static::assetLinkDetermine('resources/uploads/' . $thumbs['crop']), 'thumb_fit' => static::assetLinkDetermine('resources/uploads/' . $thumbs['fit'])];
}
}
}
$style = '@keyframes _gallery-shimmer {' . "\n" . ' 0% { background-position: 200% 0; }' . "\n" . ' 100% { background-position: -200% 0; }' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .horizontal-slider-viewport {' . "\n" . ' overflow: hidden;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] .gallery-item {' . "\n" . ' break-inside: avoid;' . "\n" . ' margin-bottom: 1rem;' . "\n" . ' }' . "\n" . ' ' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="justified"] {' . "\n" . ' display: grid;' . "\n" . ' grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));' . "\n" . ' gap: 0.75rem;' . "\n" . ' align-items: start;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="metro"] {' . "\n" . ' display: grid;' . "\n" . ' grid-template-columns: repeat(2, minmax(0, 1fr));' . "\n" . ' gap: 15px;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .gallery-item.is-loading {' . "\n" . ' background: linear-gradient(' . "\n" . ' 90deg,' . "\n" . ' #e9ecef 25%,' . "\n" . ' #f4f5f6 50%,' . "\n" . ' #e9ecef 75%' . "\n" . ' );' . "\n" . ' background-size: 400% 100%;' . "\n" . ' animation: _gallery-shimmer 1.6s ease-in-out infinite;' . "\n" . ' min-height: 120px;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .gallery-item.is-loading {' . "\n" . ' min-height: 0;' . "\n" . ' aspect-ratio: 4 / 3;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .gallery-item.is-loading figcaption,' . "\n" . ' .gallery-css-pending.fon-gallery-widget .slider-nav-btn {' . "\n" . ' display: none;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .gallery-item.is-loading img {' . "\n" . ' opacity: 0;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .gallery-item img {' . "\n" . ' display: block;' . "\n" . ' width: 100%;' . "\n" . ' height: auto;' . "\n" . ' transition: opacity 0.35s ease;' . "\n" . ' }' . "\n" . ' @media (min-width: 576px) {' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] {' . "\n" . ' column-count: 2;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="metro"] {' . "\n" . ' grid-template-columns: repeat(2, minmax(0, 1fr));' . "\n" . ' }' . "\n" . ' }' . "\n" . ' @media (min-width: 768px) {' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] {' . "\n" . ' column-count: 2;' . "\n" . ' }' . "\n" . ' }' . "\n" . ' @media (min-width: 992px) {' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] {' . "\n" . ' column-count: 3;' . "\n" . ' }' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="metro"] {' . "\n" . ' grid-template-columns: repeat(4, minmax(0, 1fr));' . "\n" . ' }' . "\n" . ' }' . "\n" . ' @media (min-width: 1200px) {' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] {' . "\n" . ' column-count: 4;' . "\n" . ' }' . "\n" . ' }' . "\n" . ' @media (min-width: 1400px) {' . "\n" . ' .gallery-css-pending.fon-gallery-widget .js-gallery-wrap[data-gallery-layout="masonry"] {' . "\n" . ' column-count: 4;' . "\n" . ' }' . "\n" . ' }';
if ($content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$this->addAsset('fon-gallery');
$output = '';
if ($images) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container gallery-css-pending fon-gallery-widget ' . ($content->fon_class ?? '') . '" data-gallery-widget data-widget-id="' . $widgetId . '">';
$output .= '<div class="horizontal-slider js-horizontal-slider ' . ($layout === 'slide' ? 'is-active' : '') . '">';
if ($layout === 'slide') {
$output .= '<button type="button" class="btn btn-circle btn-default align-items-center justify-content-center slider-nav-btn slider-prev-btn js-horizontal-prev-btn" aria-label="Onceki" style="' . ($layout === 'slide' ? '' : 'display:none;') . '">';
$output .= '<i class="fa-solid fa-chevron-left"></i>';
$output .= '</button>';
}
$output .= '<div class="horizontal-slider-viewport js-horizontal-viewport">';
$output .= '<div' . "\n" . ' class="gallery-layout js-gallery-wrap ' . $layout . ' ' . (($layout === 'bootstrap') || $layout === 'slide' ? $gridRowClasses : '') . '" ' . "\n" . ' data-gallery-layout="' . $layout . '"' . "\n" . ' style="' . ($layout === 'masonry' ? $masonryColumnCounts : '') . '"' . "\n" . ' >';
foreach ($images as $index => $image) {
$path = (string) ($image['path'] ?? '');
$title = (string) ($image['title'] ?? '');
$thumbCrop = (string) ($image['thumb_crop'] ?? '');
$thumbFit = (string) ($image['thumb_fit'] ?? '');
$useFitThumb = in_array($layout, ['masonry' => true, 'justified' => true]);
$thumbPath = ($useFitThumb ? $thumbFit : $thumbCrop);
if (($layout === 'bootstrap') || $layout === 'slide') {
$output .= '<div class="col">';
}
$output .= ' <figure class="gallery-item is-loading" style="' . (0 < $border_radius ? 'border-radius:' . (int) $border_radius . 'px;' : '') . '">';
$output .= '<a' . "\n" . ' href="' . $path . '"' . "\n" . ' class="gallery-link js-gallery-link"' . "\n" . ' data-index="' . (int) $index . '"' . "\n" . ' data-title="' . $title . '"' . "\n" . ' style="' . (0 < $border_radius ? 'border-radius:' . (int) $border_radius . 'px;' : '') . '"' . "\n" . ' >';
$output .= '<img' . "\n" . ' src="' . $thumbPath . '"' . "\n" . ' alt="' . ($title !== '' ? $title : 'Galeri gorseli') . '"' . "\n" . ' class="img-fluid rounded shadow-sm"' . "\n" . ' data-fallback="' . $fallbackImage . '"' . "\n" . ' onerror="this.onerror=null;this.src=this.dataset.fallback;"' . "\n" . ' ' . (0 < $thumb_width ? 'width="' . (int) $thumb_width . '"' : '') . ' ' . "\n" . ' ' . (0 < $thumb_height ? 'height="' . (int) $thumb_height . '"' : '') . ' ' . "\n" . ' loading="lazy"' . "\n" . ' >';
$output .= '</a>';
if ($title !== '') {
$output .= '<figcaption>' . $title . '</figcaption>';
}
$output .= '</figure>';
if (($layout === 'bootstrap') || $layout === 'slide') {
$output .= '</div>';
}
}
$output .= '</div>';
$output .= '</div>';
if ($layout === 'slide') {
$output .= '<button type="button" class="btn btn-circle btn-default align-items-center justify-content-center slider-nav-btn slider-next-btn js-horizontal-next-btn" aria-label="Sonraki">';
$output .= '<i class="fa-solid fa-chevron-right"></i>';
$output .= '</button>';
}
$output .= '</div>';
$output .= '<div class="modal fade gallery-modal js-gallery-modal" id="' . $widgetId . '-modal" tabindex="-1" aria-hidden="true">';
$output .= '<div class="modal-dialog modal-xl modal-dialog-centered">';
$output .= '<div class="modal-content bg-dark text-white">';
$output .= '<div class="modal-header border-0">';
$output .= '<h5 class="modal-title js-gallery-modal-title text-white" id="' . $widgetId . '-modal-title"></h5>';
$output .= '<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Kapat"></button>';
$output .= '</div>';
$output .= '<div class="modal-body text-center position-relative">';
$output .= '<button type="button" class="btn btn-light modal-nav-btn prev-btn js-prev-image-btn">';
$output .= '<i class="fa-solid fa-chevron-left"></i>';
$output .= '</button>';
$output .= '<img src="" alt="" class="img-fluid rounded gallery-modal-image js-modal-image">';
$output .= '<button type="button" class="btn btn-light modal-nav-btn next-btn js-next-image-btn">';
$output .= '<i class="fa-solid fa-chevron-right"></i>';
$output .= '</button>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
private function heading_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$title = '';
if (is_object($content->title)) {
$title = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
}
else if (is_string($content->title)) {
$title = $content->title;
}
$title_link = '';
if (is_object($content->title_link)) {
$title_link = (isset($content->title_link->{$this->lang}) && $content->title_link->{$this->lang} ? $content->title_link->{$this->lang} : array_values((array) $content->title_link)[0] ?? '');
}
else if (is_string($content->title_link)) {
$title_link = $content->title_link;
}
$title_link_target = (isset($content->title_link_target) && $content->title_link_target ? $content->title_link_target : '_self');
$title_link_rel = (isset($content->title_link_rel) && $content->title_link_rel ? $content->title_link_rel : []);
$title_link_rel = ($title_link_rel ? ' rel="' . implode(' ', $title_link_rel) . '" ' : '');
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$show_icon = (isset($content->show_icon) && $content->show_icon == 'yes' ? true : false);
$icon_type = (isset($content->icon_type) && $content->icon_type ? $content->icon_type : 'icon');
$title_icon = (isset($content->title_icon) && $content->title_icon ? $content->title_icon : '');
$title_svg = (isset($content->title_svg) && $content->title_svg ? $content->title_svg : '');
$title_icon_position = (isset($content->title_icon_position) && $content->title_icon_position ? $content->title_icon_position : 'before');
$title_icon_color = (isset($content->title_icon_color) && $content->title_icon_color ? $content->title_icon_color : '');
$scroll_effect = (isset($content->scroll_effect) && $content->scroll_effect == 'yes' ? true : false);
$title_color = (isset($content->title_color) && $content->title_color ? $content->title_color : '');
$title_font = (isset($content->title_font) && $content->title_font ? $content->title_font : '');
$title_text_shadow = (isset($content->title_text_shadow) && $content->title_text_shadow ? $content->title_text_shadow : '');
$title_margin = (isset($content->title_margin) && $content->title_margin ? $content->title_margin : (object) ['xl' => '', 'lg' => '', 'md' => '', 'sm' => '', 'xs' => '']);
$title_padding = (isset($content->title_padding) && $content->title_padding ? $content->title_padding : (object) ['xl' => '', 'lg' => '', 'md' => '', 'sm' => '', 'xs' => '']);
$aligns = (isset($content->align) && $content->align ? $content->align : (object) ['xl' => 'left', 'lg' => 'left', 'md' => 'left', 'sm' => 'left', 'xs' => 'left']);
$alignClass = [];
if ($aligns) {
foreach ($aligns as $key => $align) {
$map = ['left' => 'start', 'right' => 'end', 'center' => 'center'];
$val = $map[$align] ?? 'start';
$prefix = ($key === 'xs' ? '' : '-' . $key);
$alignClass[] = 'text' . $prefix . '-' . $val;
}
}
$alignClass = implode(' ', $alignClass);
$isScrolled = false;
$scrollAlignsClass = [];
if ($scroll_effect && is_string($title) && strpos($title, ':') !== false) {
$title = explode(':', $title);
$isScrolled = true;
foreach ($aligns as $key => $align) {
$prefix = ($key === 'xs' ? '' : '-' . $key);
switch ($align) {
case 'center':
$scrollAlignsClass[] = 'mx' . $prefix . '-auto';
break;
case 'right':
$scrollAlignsClass[] = 'ms' . $prefix . '-auto';
$scrollAlignsClass[] = 'me' . $prefix . '-0';
break;
case 'left':
$scrollAlignsClass[] = 'me' . $prefix . '-auto';
$scrollAlignsClass[] = 'ms' . $prefix . '-0';
break;
}
}
}
$scrollAlignsClass = implode(' ', $scrollAlignsClass);
$style = '';
if ($title) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
if ($title_color) {
$style .= 'color: ' . $title_color . ';';
}
if ($title_text_shadow) {
$style .= 'text-shadow: ' . $title_text_shadow . ';';
}
if ($title_font) {
$style .= self::parseFontProperties($title_font);
}
$style .= '}';
$style .= '#' . $widgetId . ' .fon-widget-title a{';
if ($title_color) {
$style .= 'color: ' . $title_color . ';';
}
$style .= '}';
if ($isScrolled && $title_color) {
$style .= '#' . $widgetId . ' .scrolling-sector{';
$style .= '--title-color: ' . $title_color . ';';
$style .= '}';
}
}
if ($show_icon && $title_icon) {
$style .= '#' . $widgetId . ' .fon-widget-title i{';
if ($title_icon_color) {
$style .= 'color: ' . $title_icon_color . ';';
}
$style .= '}';
}
$responsiveItems = [
'.fon-widget-title' => [
['type' => 'margin', 'unit' => '', 'value' => $title_margin],
['type' => 'padding', 'unit' => '', 'value' => $title_padding]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
if ($content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-heading-widget ' . ($content->fon_class ?? '') . '">';
$output .= '<div class="fon-widget-content ' . ($isScrolled ? 'scrolling-sector-wrapper ' . $scrollAlignsClass : '') . '">';
if ($title) {
$output .= '<' . $heading_selector . ' class="fon-widget-title ' . ($isScrolled ? 'scrolling-sector-inner' : $alignClass) . '">';
if ($title_link && !$scroll_effect) {
$output .= '<a href="' . $title_link . '" target="' . $title_link_target . '" ' . $title_link_rel . '>';
}
if ($show_icon && $title_icon_position == 'before') {
if ($icon_type == 'icon') {
$output .= '<i class="' . $title_icon . '"></i> ';
}
else if ($icon_type == 'svg') {
$output .= '<span class="me-2">' . $title_svg . '</span>';
}
}
if ($isScrolled) {
$output .= '<div class="scrolling-sector"><span>' . implode('</span><span>', $title) . '</span></div>';
}
else {
$output .= self::getPriceHolders($title);
}
if ($show_icon && $title_icon_position == 'after') {
if ($icon_type == 'icon') {
$output .= '<i class="' . $title_icon . ' me-2"></i>';
}
else if ($icon_type == 'svg') {
$output .= '<span class="me-2">' . $title_svg . '</span>';
}
}
if ($title_link && !$scroll_effect) {
$output .= '</a>';
}
$output .= '</' . $heading_selector . '>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function hosting_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetProducts($content, $moduleId, $pageData, $row, 'hosting');
}
private function image_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$title = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
$show_title = (isset($content->name_widget_status) && $content->name_widget_status == 'yes' ? true : false);
$title_position = (isset($content->title_position) && $content->title_position ? $content->title_position : 'top');
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$alt_text = (isset($content->alt_text->{$this->lang}) && $content->alt_text->{$this->lang} ? $content->alt_text->{$this->lang} : array_values((array) $content->alt_text)[0] ?? '');
$title_text = (isset($content->title_text->{$this->lang}) && $content->title_text->{$this->lang} ? $content->title_text->{$this->lang} : (isset($content->title_text) ? array_values((array) $content->title_text)[0] ?? '' : ''));
$open_lightbox = (isset($content->open_lightbox) && $content->open_lightbox == 'yes' ? true : false);
$overlay_type = (isset($content->overlay_type) && $content->overlay_type ? $content->overlay_type : 'none');
$image_overlay = ($overlay_type != 'none' ? true : false);
$link = (isset($content->link) && $content->link ? $content->link : '');
$link_target = (isset($content->link_target) && $content->link_target ? $content->link_target : '_blank');
$link_rel = (isset($content->link_rel) && $content->link_rel ? $content->link_rel : []);
$link_rel = ($link_rel ? ' rel="' . implode(' ', $link_rel) . '" ' : '');
$image = '';
if (is_object($content->image)) {
$image = (isset($content->image->{$this->lang}) && $content->image->{$this->lang} ? $content->image->{$this->lang} : array_values((array) $content->image)[0] ?? '');
}
else if (is_string($content->image)) {
$image = $content->image;
}
$image_src = ($image ? static::assetLinkDetermine($image) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($image_src, $pageData['badress']);
$image_width = (isset($content->image_width) && $content->image_width ? $content->image_width : false);
$image_height = (isset($content->image_height) && $content->image_height ? $content->image_height : false);
$align = (isset($content->align) && $content->align ? $content->align : 'center');
$use_border = (isset($content->use_border) && $content->use_border == 'yes' ? true : false);
$border = (isset($content->border) && $content->border ? $content->border : '');
$padding = (isset($content->padding) && $content->padding ? $content->padding : '');
$border_radius = (isset($content->border_radius) && $content->border_radius ? $content->border_radius : 0);
$shadow = (isset($content->shadow) && $content->shadow ? $content->shadow : '');
$disable_lazy = (isset($content->disable_lazy) && $content->disable_lazy == 'yes' ? true : false);
if (empty($alt_text)) {
if (!empty($title)) {
$alt_text = $title;
}
else if (!empty($title_text)) {
$alt_text = $title_text;
}
else {
$alt_text = basename($image_src);
}
}
if (empty($title_text)) {
if (!empty($title)) {
$title_text = $title;
}
else if (!empty($alt_text)) {
$title_text = $alt_text;
}
else {
$title_text = basename($image_src);
}
}
if ($align == 'left') {
$align = 'start';
}
else if ($align == 'right') {
$align = 'end';
}
$style = '';
if ($image) {
$style .= '#' . $widgetId . ' .fon-image-widget-container img{';
$style .= ($border && $use_border ? 'border:' . $border . ';' : '');
$style .= ($padding && $use_border ? 'padding:' . $padding . 'px;' : '');
$style .= ($border_radius ? 'border-radius:' . $border_radius . 'px;' : '');
$style .= ($shadow ? 'box-shadow:' . $shadow . ';' : '');
$style .= '}';
$responsiveValues = [];
if ($image_height) {
$responsiveValues[] = ['type' => 'height', 'unit' => 'px', 'value' => $image_height];
}
if ($image_width) {
$responsiveValues[] = ['type' => 'width', 'unit' => 'px', 'value' => $image_width];
}
$responsiveItems = ['#' . $widgetId . ' .fon-image-widget-container img' => $responsiveValues];
$style .= self::parseResponsiveItems($responsiveItems);
}
if ($image_overlay && $open_lightbox) {
$style .= '#' . $widgetId . ' .fon-image-widget-overlay{';
if ($overlay_type == 'color') {
$style .= (isset($content->color_overlay) && $content->color_overlay ? 'background-color:' . $content->color_overlay . ';' : '');
}
if ($overlay_type == 'gradient') {
$style .= (isset($content->gradient_overlay) && $content->gradient_overlay ? self::parseGradient($content->gradient_overlay) : '');
}
if ($padding && $use_border) {
$style .= ($image_width ? 'width:calc(100% - ' . ($padding * 2) . 'px);' : '');
$style .= ($image_height ? 'height:calc(100% - ' . ($padding * 2) . 'px);' : '');
$style .= 'left:' . $padding . 'px;';
$style .= 'right:' . $padding . 'px;';
$style .= 'top:' . $padding . 'px;';
$style .= 'bottom:' . $padding . 'px;';
$style .= ($border_radius ? 'border-radius:' . round($border_radius / 2) . 'px;' : '');
}
else {
$style .= ($image_width ? 'width:100%;' : '');
$style .= ($image_height ? 'height:100%;' : '');
$style .= ($border_radius ? 'border-radius:' . $border_radius . 'px;' : '');
}
$style .= '}';
}
if ($show_title && $title) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
$style .= self::parseFontProperties($content->title_font);
$style .= ($content->title_color ? 'color:' . $content->title_color . ';' : '');
$style .= ($content->title_margin->top ? 'margin-top:' . $content->title_margin->top . 'px;' : '');
$style .= ($content->title_margin->bottom ? 'margin-bottom:' . $content->title_margin->bottom . 'px;' : '');
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
if ($isLCPCandidate && $image) {
$this->addPreloadLink($image, $pageData['page']);
self::$lcpHandled = true;
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-image-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content text-' . $align . '">';
$output .= ($show_title && $title && $title_position != 'bottom' ? '<' . $heading_selector . ' class="fon-widget-title d-block">' . $title . '</' . $heading_selector . '>' : '');
$output .= '<div class="fon-image-widget-container text-' . $align . '">';
if ($image_overlay && $open_lightbox) {
$output .= '<div class="fon-image-widget-overlay">';
$output .= '</div>';
}
if ($open_lightbox) {
$this->addAsset('magnific');
$output .= '<a class="fon-magnific-popup fon-image-widget-overlay-icon" data-popuptype="image" data-mainclass="mfp-no-margins mfp-with-zoom" href="' . $image_src . '">+</a>';
}
if (!$open_lightbox) {
$output .= (!empty($link) ? '<a href="' . $link . '" target="' . $link_target . '" ' . $link_rel . '>' : '');
}
$loadingAttr = 'loading="lazy" decoding="async"';
$fetchPriority = 'low';
if (($isLCPCandidate && $image_src) || $disable_lazy) {
$loadingAttr = 'loading="eager"';
$fetchPriority = 'high';
}
else if (!$enableLazyLoading) {
$loadingAttr = 'loading="eager"';
$fetchPriority = 'auto';
}
$output .= '<img class="img-fluid" src="' . $image_src . '" alt="' . $alt_text . '" title="' . $title_text . '" ' . $imageDimensions . ' ' . $loadingAttr . ' fetchpriority="' . $fetchPriority . '"/>';
if (!$open_lightbox) {
$output .= (!empty($link) ? '</a>' : '');
}
$output .= '</div>';
$output .= ($show_title && $title && $title_position === 'bottom' ? '<' . $heading_selector . ' class="fon-widget-title d-block">' . $title . '</' . $heading_selector . '>' : '');
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function modal_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$modalUniqueId = 'fon-modal-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$modal_selector = (isset($content->modal_selector) && $content->modal_selector ? $content->modal_selector : 'image');
$name_widget = '';
if (is_object($content->name_widget)) {
$name_widget = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
}
else if (is_string($content->name_widget)) {
$name_widget = $content->name_widget;
}
$image = '';
if (is_object($content->image)) {
$image = (isset($content->image->{$this->lang}) && $content->image->{$this->lang} ? $content->image->{$this->lang} : array_values((array) $content->image)[0] ?? '');
}
else if (is_string($content->image)) {
$image = $content->image;
}
$image_src = ($image ? static::assetLinkDetermine($image) : static::assetLinkDetermine(self::$imagePlaceholder));
$image_width = (isset($content->image_width) && $content->image_width ? $content->image_width : (object) ['xxl' => '100', 'xl' => '100', 'lg' => '100', 'md' => '100', 'sm' => '100', 'xs' => '100']);
$image_height = (isset($content->image_height) && $content->image_height ? $content->image_height : (object) ['xxl' => '100', 'xl' => '100', 'lg' => '100', 'md' => '100', 'sm' => '100', 'xs' => '100']);
$image_use_border = (isset($content->image_use_border) && $content->image_use_border == 'yes' ? true : false);
$image_border = (isset($content->image_border) && $content->image_border ? $content->image_border : '2px solid #ffffff');
$image_radius = (isset($content->image_radius) && $content->image_radius ? $content->image_radius : '');
$image_show_icon = (isset($content->image_show_icon) && $content->image_show_icon == 'yes' ? true : false);
$image_icon = (isset($content->image_icon) && $content->image_icon ? $content->image_icon : 'fa-solid fa-play');
$image_icon_size = (isset($content->image_icon_size) && $content->image_icon_size ? $content->image_icon_size : '14');
$image_icon_color = (isset($content->image_icon_color) && $content->image_icon_color ? $content->image_icon_color : '#fff');
$button = ['button_text' => $content->button_text ?? '', 'button_target' => '', 'button_type' => $content->button_type ?? 'default', 'button_style' => $content->button_style ?? 'default', 'button_custom_style' => $content->button_custom_style ?? 'default', 'button_shape' => $content->button_shape ?? '', 'button_size' => $content->button_size ?? '', 'button_padding' => $content->button_padding ?? '', 'button_color_normal' => $content->button_color->normal ?? '', 'button_color_hover' => $content->button_color->hover ?? '', 'button_background_normal' => $content->button_background->normal ?? '', 'button_background_hover' => $content->button_background->hover ?? '', 'button_gradient_normal' => $content->button_gradient->normal ?? '', 'button_gradient_hover' => $content->button_gradient->hover ?? '', 'show_button_icon' => $content->show_button_icon ?? 'no', 'button_icon' => $content->button_icon ?? '', 'button_icon_position' => $content->button_icon_position ?? '', 'scroll_button' => 'no', 'block_button' => 'no', 'button_font' => $content->button_font ?? ''];
$icon = (isset($content->icon) && $content->icon ? $content->icon : 'fa-solid fa-play');
$icon_size = (isset($content->icon_size) && $content->icon_size ? $content->icon_size : (object) ['xxl' => '36', 'xl' => '36', 'lg' => '36', 'md' => '36', 'sm' => '36', 'xs' => '36']);
$icon_color = (isset($content->icon_color) && $content->icon_color ? $content->icon_color : '#ffffff');
$icon_bg_color = (isset($content->icon_bg_color) && $content->icon_bg_color ? $content->icon_bg_color : 'var(--theme-secondary)');
$icon_width = (isset($content->icon_width) && $content->icon_width ? $content->icon_width : (object) ['xxl' => '100', 'xl' => '100', 'lg' => '100', 'md' => '100', 'sm' => '100', 'xs' => '100']);
$icon_height = (isset($content->icon_height) && $content->icon_height ? $content->icon_height : (object) ['xxl' => '100', 'xl' => '100', 'lg' => '100', 'md' => '100', 'sm' => '100', 'xs' => '100']);
$icon_use_border = (isset($content->icon_use_border) && $content->icon_use_border == 'yes' ? true : false);
$icon_border = (isset($content->icon_border) && $content->icon_border ? $content->icon_border : '1px solid var(--theme-primary)');
$icon_border_radius = (isset($content->icon_border_radius) && $content->icon_border_radius ? $content->icon_border_radius : '');
$icon_shadow = (isset($content->icon_shadow) && $content->icon_shadow ? $content->icon_shadow : '');
$selector_position_type = (isset($content->selector_position_type) && $content->selector_position_type ? $content->selector_position_type : 'none');
$selector_position = (isset($content->selector_position) && $content->selector_position ? $content->selector_position : (object) ['left' => '', 'right' => '', 'top' => '', 'bottom' => '']);
$center_selector = (isset($content->center_selector) && $content->center_selector == 'yes' ? true : false);
$show_ripple_effect = (isset($content->show_ripple_effect) && $content->show_ripple_effect == 'yes' ? true : false);
$ripple_effect_color = (isset($content->ripple_effect_color) && $content->ripple_effect_color ? $content->ripple_effect_color : '#000000');
$ripple_effect_color = self::validateAndNormalizeColor($ripple_effect_color);
$content_type = (isset($content->content_type) && $content->content_type ? $content->content_type : 'video');
$video_source = (isset($content->video_source) && $content->video_source ? $content->video_source : 'youtube');
$video_url = '';
if (is_object($content->video_url)) {
$video_url = (isset($content->video_url->{$this->lang}) && $content->video_url->{$this->lang} ? $content->video_url->{$this->lang} : array_values((array) $content->video_url)[0] ?? '');
}
else if (is_string($content->video_url)) {
$video_url = $content->video_url;
}
$mp4_video = '';
if (is_object($content->mp4_video)) {
$mp4_video = (isset($content->mp4_video->{$this->lang}) && $content->mp4_video->{$this->lang} ? $content->mp4_video->{$this->lang} : array_values((array) $content->mp4_video)[0] ?? '');
}
else if (is_string($content->mp4_video)) {
$mp4_video = $content->mp4_video;
}
if ($mp4_video) {
$mp4_video = static::assetLinkDetermine($mp4_video);
}
$show_control = (isset($content->show_control) && $content->show_control == 'yes' ? true : false);
$video_loop = (isset($content->video_loop) && $content->video_loop == 'yes' ? true : false);
$video_mute = (isset($content->video_mute) && $content->video_mute == 'yes' ? true : false);
$autoplay_video = (isset($content->autoplay_video) && $content->autoplay_video == 'yes' ? true : false);
$text_content = '';
if (is_object($content->text_content)) {
$text_content = (isset($content->text_content->{$this->lang}) && $content->text_content->{$this->lang} ? $content->text_content->{$this->lang} : array_values((array) $content->text_content)[0] ?? '');
}
else if (is_string($content->text_content)) {
$text_content = $content->text_content;
}
$image_content = '';
if (is_object($content->image_content)) {
$image_content = (isset($content->image_content->{$this->lang}) && $content->image_content->{$this->lang} ? $content->image_content->{$this->lang} : array_values((array) $content->image_content)[0] ?? '');
}
else if (is_string($content->image_content)) {
$image_content = $content->image_content;
}
$image_content_src = ($image ? static::assetLinkDetermine($image_content) : static::assetLinkDetermine(self::$imagePlaceholder));
$image_content_alt = '';
if (is_object($content->image_content_alt)) {
$image_content_alt = (isset($content->image_content_alt->{$this->lang}) && $content->image_content_alt->{$this->lang} ? $content->image_content_alt->{$this->lang} : array_values((array) $content->image_content_alt)[0] ?? '');
}
else if (is_string($content->image_content_alt)) {
$image_content_alt = $content->image_content_alt;
}
$modal_popup_sizes = (isset($content->modal_popup_sizes) && $content->modal_popup_sizes ? $content->modal_popup_sizes : (object) ['width' => '760', 'height' => '400']);
$modal_popup_overflow = (isset($content->modal_popup_overflow) && $content->modal_popup_overflow ? $content->modal_popup_overflow : 'auto');
$style = '';
if (($modal_selector == 'image') && $image) {
if ($image_use_border) {
$style .= '#' . $widgetId . ' .fon-modal-selector .fon-modal-image{';
$style .= ($image_border ? 'border:' . $image_border . ';' : '');
$style .= '}';
}
$style .= '#' . $widgetId . ' .fon-modal-selector, #' . $widgetId . ' .fon-modal-image, #' . $widgetId . ' .fon-ripple-effect{';
$style .= ($image_radius ? 'border-radius:' . $image_radius . ';' : '');
$style .= '}';
$responsiveValues = [];
if ($image_height) {
$responsiveValues[] = ['type' => 'height', 'unit' => 'px', 'value' => $image_height];
}
if ($image_width) {
$responsiveValues[] = ['type' => 'width', 'unit' => 'px', 'value' => $image_width];
}
$responsiveItems = ['#' . $widgetId . ' .fon-modal-selector, #' . $widgetId . ' .fon-modal-image, #' . $widgetId . ' .fon-modal-image img' => $responsiveValues];
$style .= self::parseResponsiveItems($responsiveItems);
if ($image_show_icon && $image_icon) {
$style .= '#' . $widgetId . ' .fon-modal-image .fon-modal-image-icon{';
$style .= ($image_icon_size ? 'font-size:' . $image_icon_size . 'px;' : '');
$style .= ($image_icon_color ? 'color:' . $image_icon_color . ';' : '');
$style .= 'position: absolute;';
$style .= 'top: 50%;';
$style .= 'left: 50%;';
$style .= 'transform: translate(-50%, -50%);';
if ($icon_shadow) {
$style .= 'text-shadow:' . $icon_shadow . ';';
}
$style .= '}';
}
}
else if (($modal_selector == 'icon') && $icon) {
$style .= '#' . $widgetId . ' .fon-modal-icon{';
$style .= ($icon_color ? 'color:' . $icon_color . ';' : '');
$style .= ($icon_bg_color ? 'background:' . $icon_bg_color . ';' : '');
$style .= ($icon_border_radius ? 'border-radius:' . $icon_border_radius . ';' : '');
$style .= ($icon_shadow ? 'box-shadow:' . $icon_shadow . ';' : '');
$style .= ($icon_use_border && $icon_border ? 'border:' . $icon_border . ';' : '');
$style .= 'aspect-ratio: 1 / 1;';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-ripple-effect{';
$style .= ($icon_border_radius ? 'border-radius:' . $icon_border_radius . ';' : '');
$style .= '}';
$responsiveValues = [];
if ($icon_size) {
$responsiveValues[] = ['type' => 'font-size', 'unit' => 'px', 'value' => $icon_size];
}
if ($icon_height) {
$responsiveValues[] = ['type' => 'height', 'unit' => 'px', 'value' => $icon_height];
}
if ($icon_width) {
$responsiveValues[] = ['type' => 'width', 'unit' => 'px', 'value' => $icon_width];
}
$responsiveItems = ['#' . $widgetId . ' .fon-modal-icon' => $responsiveValues];
$style .= self::parseResponsiveItems($responsiveItems);
}
if ($selector_position_type != 'none') {
$style .= '#' . $widgetId . '{';
if (in_array($selector_position_type, ['absolute' => true, 'relative' => true]) && $center_selector) {
$style .= 'transform: translate(-50%, -50%);';
}
$style .= '}';
$responsiveValues = [
['type' => 'left', 'unit' => '', 'value' => $selector_position->left],
['type' => 'right', 'unit' => '', 'value' => $selector_position->right],
['type' => 'top', 'unit' => '', 'value' => $selector_position->top],
['type' => 'bottom', 'unit' => '', 'value' => $selector_position->bottom]
];
$responsiveItems = ['#' . $widgetId => $responsiveValues];
$style .= self::parseResponsiveItems($responsiveItems);
}
if ($content_type != 'video') {
$style .= '#' . $modalUniqueId . ' .fon-modal-inner-block {';
$style .= 'width:' . $modal_popup_sizes->width . 'px;';
$style .= 'height:' . $modal_popup_sizes->height . 'px;';
$style .= 'max-width:100%!important;';
if ($content_type != 'image') {
$style .= 'overflow-y:' . $modal_popup_overflow . ';';
}
$style .= '}';
}
if ($show_ripple_effect && isset($ripple_effect_color['color']) && $ripple_effect_color['color']) {
$style .= '#' . $widgetId . ' .fon-ripple-effect{';
$style .= '--fon-effect-rgb:' . $ripple_effect_color['color'] . ';';
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$this->addAsset('magnific');
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-modal-widget ' . ($content->fon_class ?? '') . ' position-' . $selector_position_type . '">';
if ($content_type === 'text') {
$url = '#' . $modalUniqueId;
$output .= '<div id="' . $modalUniqueId . '" class="mfp-hide fon-modal-text-popup-block position-relative mx-auto" style="width:min-content;max-width:90%!important">';
$output .= '<div class="fon-modal-inner-block position-relative p-4 rounded-3 overflow-x-hidden bg-white">';
$output .= $text_content;
$output .= '</div>';
$output .= '</div>';
$attribs = 'data-popup_type="inline" data-mainclass="mfp-no-margins mfp-with-zoom"';
}
else if ($content_type === 'video') {
if ($video_source == 'mp4') {
$url = $mp4_video;
$attribs = 'data-popup_type="video" data-mainclass="mfp-no-margins mfp-with-zoom" data-show-control="' . $show_control . '" data-video-loop="' . $video_loop . '" data-video-mute="' . $video_mute . '" data-autoplay-video="' . $autoplay_video . '"';
}
else {
$url = $video_url;
$attribs = 'data-popup_type="iframe" data-mainclass="mfp-no-margins mfp-with-zoom"';
}
}
else {
if (empty($image_content_alt)) {
$url_part_of_content = explode('/', $image_content_src);
$modal_content_image_alt_text = end($url_part_of_content);
}
$url = '#' . $modalUniqueId;
$imageDimensions = static::getImageDimensions($image_content_src, $pageData['badress']);
$output .= '<div id="' . $modalUniqueId . '" class="mfp-hide fon-modal-popup-image-block position-relative mx-auto" style="width:fit-content; height:fit-content;">';
$output .= '<div class="fon-modal-inner-block">';
$output .= '<img class="mfp-img" src="' . $image_content_src . '" alt="' . $modal_content_image_alt_text . '" ' . $imageDimensions . '>';
$output .= '</div>';
$output .= '</div>';
$attribs = 'data-popup_type="inline" data-mainclass="mfp-no-margins mfp-with-zoom"';
}
if ($modal_selector === 'image') {
if ($image_src) {
$imageDimensions = static::getImageDimensions($image_src, $pageData['badress']);
$output .= '<a class="fon-modal-selector fon-magnific-popup d-inline-block position-relative" ' . $attribs . ' href="' . $url . '" id="' . $modalUniqueId . '-selector">';
if ($show_ripple_effect) {
$output .= '<span class="fon-ripple-effect"></span>';
}
$output .= '<span class="fon-modal-image overflow-hidden d-block position-relative z-1">';
$output .= '<img src="' . $image_src . '" class="img img-fluid object-fit-cover" alt="' . $name_widget . '" ' . $imageDimensions . '/>';
$output .= ($image_show_icon ? '<span class="fon-modal-image-icon"><i class="' . $image_icon . '"></i></span>' : '');
$output .= '</span>';
$output .= '</a>';
}
}
else if ($modal_selector === 'icon') {
if ($icon) {
$select_icon = explode(' ', $icon);
if (count($select_icon) === 1) {
$icon = 'fa-solid ' . $icon;
}
$output .= '<a class="fon-modal-selector fon-magnific-popup d-inline-block position-relative" href="' . $url . '" ' . $attribs . ' id="' . $modalUniqueId . '-selector">';
if ($show_ripple_effect) {
$output .= '<span class="fon-ripple-effect"></span>';
}
$output .= '<span class="fon-modal-icon d-inline-flex align-items-center justify-content-center position-relative z-1">';
$output .= '<i class="' . $icon . '" aria-hidden="true"></i>';
$output .= '</span>';
$output .= '</a>';
}
}
else {
$button['button_link'] = $url;
$modalButton = $this->parseButton((object) $button, $moduleId, $pageData, ['class' => 'fon-magnific-popup fon-modal-selector position-relative z-1', 'attributes' => $attribs, 'id' => $modalUniqueId . '-selector']);
$output .= '<span class="fon-modal-button d-inline-block position-relative">';
if ($show_ripple_effect) {
$output .= '<span class="fon-ripple-effect rounded-4"></span>';
}
$output .= $modalButton;
$output .= '</span>';
}
$output .= '</div>';
return $output;
}
private function news_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetPages($content, $moduleId, $pageData, 'news');
}
private function number_box_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
$style .= '#' . $widgetId . ' .number-box .number{';
if (isset($content->number_size) && $content->number_size) {
$style .= 'font-size:' . $content->number_size . 'px;';
}
if (isset($content->number_weight) && $content->number_weight) {
$style .= 'font-weight:' . $content->number_weight . ';';
}
$style .= 'width:' . $content->number_size . 'px;';
$style .= 'height:' . $content->number_size . 'px;';
$style .= 'line-height:' . $content->number_size . 'px;';
if (isset($content->number_color_type) && $content->number_color_type == 'flat') {
$style .= '--bs-normal-color:' . $content->number_color->normal . ';';
$style .= '--bs-hover-color:' . $content->number_color->hover . ';';
}
else if (isset($content->number_color_type) && $content->number_color_type == 'gradient') {
$style .= self::parseGradient($content->number_gradient->normal, 'normal-color');
$style .= self::parseGradient($content->number_gradient->hover, 'hover-color');
}
$style .= '}';
$style .= '#' . $widgetId . ' .number-container{';
if (isset($content->number_size) && $content->number_size) {
$style .= 'width:' . ($content->number_size + 30) . 'px;';
$style .= 'height:' . ($content->number_size + 30) . 'px;';
}
if (isset($content->number_border->normal) && $content->number_border->normal) {
$style .= '--bs-normal-border:' . $content->number_border->normal . ';';
}
if (isset($content->number_border->hover) && $content->number_border->hover) {
$style .= '--bs-hover-border:' . $content->number_border->hover . ';';
}
if (isset($content->number_radius->normal) && $content->number_radius->normal) {
$style .= '--bs-normal-radius:' . $content->number_radius->normal . 'px;';
}
if (isset($content->number_radius->hover) && $content->number_radius->hover) {
$style .= '--bs-hover-radius:' . $content->number_radius->hover . 'px;';
}
if (isset($content->number_shadow->normal) && $content->number_shadow->normal) {
$style .= '--bs-normal-shadow:' . $content->number_shadow->normal . ';';
}
if (isset($content->number_shadow->hover) && $content->number_shadow->hover) {
$style .= '--bs-hover-shadow:' . $content->number_shadow->hover . ';';
}
if (isset($content->number_background_type) && $content->number_background_type == 'flat') {
$style .= '--bs-normal-bg:' . $content->number_bg->normal . ';';
$style .= '--bs-hover-bg:' . $content->number_bg->hover . ';';
}
else if (isset($content->number_background_type) && $content->number_background_type == 'gradient') {
$style .= self::parseGradient($content->number_bg_gradient->normal, 'normal-bg');
$style .= self::parseGradient($content->number_bg_gradient->hover, 'hover-bg');
}
$style .= '}';
$style .= '#' . $widgetId . ' .number-box-title{';
if (isset($content->title_color->normal) && $content->title_color->normal) {
$style .= '--bs-normal-color:' . $content->title_color->normal . ';';
}
if (isset($content->title_color->hover) && $content->title_color->hover) {
$style .= '--bs-hover-color:' . $content->title_color->hover . ';';
}
if (isset($content->title_font)) {
$style .= self::parseFontProperties($content->title_font);
}
$style .= '}';
$style .= '#' . $widgetId . ' .number-box-desc{';
if (isset($content->content_color->normal) && $content->content_color->normal) {
$style .= '--bs-normal-color:' . $content->content_color->normal . ';';
}
if (isset($content->content_color->hover) && $content->content_color->hover) {
$style .= '--bs-hover-color:' . $content->content_color->hover . ';';
}
$style .= '}';
$style .= '#' . $widgetId . ' .number-box{';
if (isset($content->background_type) && $content->background_type == 'flat') {
$style .= '--bs-normal-bg:' . $content->background->normal . ';';
$style .= '--bs-hover-bg:' . $content->background->hover . ';';
}
else if (isset($content->background_type) && $content->background_type == 'gradient') {
$style .= self::parseGradient($content->background_gradient->normal, 'normal-bg');
$style .= self::parseGradient($content->background_gradient->hover, 'hover-bg');
}
if (isset($content->shadow->normal) && $content->shadow->normal) {
$style .= '--bs-normal-shadow:' . $content->shadow->normal . ';';
}
if (isset($content->shadow->hover) && $content->shadow->hover) {
$style .= '--bs-hover-shadow:' . $content->shadow->hover . ';';
}
if (isset($content->border_radius->normal) && $content->border_radius->normal) {
$style .= '--bs-normal-radius:' . $content->border_radius->normal . 'px;';
}
if (isset($content->border_radius->hover) && $content->border_radius->hover) {
$style .= '--bs-hover-radius:' . $content->border_radius->hover . 'px;';
}
if (isset($content->use_border) && $content->use_border == 'yes') {
if (isset($content->border->normal) && $content->border->normal) {
$style .= '--bs-normal-border:' . $content->border->normal . ';';
}
if (isset($content->border->hover) && $content->border->hover) {
$style .= '--bs-hover-border:' . $content->border->hover . ';';
}
}
if (isset($content->padding) && $content->padding) {
$style .= 'padding:' . $content->padding . 'px;';
}
$style .= '}';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$attributes = '';
if ($content->number_position == 'top') {
$attributes .= 'align-items-center ';
switch ($content->align) {
case 'left':
$attributes .= 'justify-content-start text-start';
break;
case 'right':
$attributes .= 'justify-content-end text-end';
break;
case 'center':
$attributes .= 'justify-content-center text-center';
break;
}
}
else {
if ($content->number_position == 'left') {
$attributes .= 'justify-content-start text-start ';
}
else if ($content->number_position == 'right') {
$attributes .= 'justify-content-end text-end ';
}
if (isset($content->vertical_align) && $content->vertical_align) {
switch ($content->vertical_align) {
case 'top':
$attributes .= 'align-items-start';
break;
case 'bottom':
$attributes .= 'align-items-end';
break;
case 'center':
$attributes .= 'align-items-bottom';
break;
}
}
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-number-box-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$output .= '<div class="number-box number-' . $content->number_position . ' ' . $attributes . ' ' . $content->background_type . '">';
$output .= '<div class="number-box-number">';
$output .= '<div class="number-container ' . $content->number_background_type . '">';
$output .= '<div class="number ' . $content->number_color_type . '">';
$output .= trim($content->number);
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="number-box-content">';
$contentTitle = (isset($content->title->{$this->lang}) && $content->title->{$this->lang} ? $content->title->{$this->lang} : array_values((array) $content->title)[0] ?? '');
$contentDesc = (isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : array_values((array) $content->content)[0] ?? '');
if ($contentTitle) {
$output .= '<' . $content->heading_selector . ' class="number-box-title">';
$output .= $contentTitle;
$output .= '</' . $content->heading_selector . '>';
}
if ($contentDesc) {
$output .= '<div class="number-box-desc">';
$output .= $contentDesc;
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function page_menu_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$items = (isset($content->items) && $content->items ? $content->items : []);
$enable_fixed = (isset($content->enable_fixed) && $content->enable_fixed == 'yes' ? true : false);
$menu_type = (isset($content->menu_type) && $content->menu_type ? $content->menu_type : 'menu');
$menu_align = (isset($content->menu_align) && $content->menu_align ? $content->menu_align : 'start');
$menu_position = (isset($content->menu_position) && $content->menu_position ? $content->menu_position : 'right');
$menu_seperate = (isset($content->menu_seperate) && $content->menu_seperate == 'yes' ? true : false);
$disable = (isset($content->disable) && $content->disable ? $content->disable : (object) ['xl' => 'block', 'lg' => 'block', 'md' => 'block', 'sm' => 'none', 'xs' => 'none']);
$style = '';
$style .= '#' . $widgetId . ' .nav-link{';
if (isset($content->link_color->normal) && $content->link_color->normal) {
$style .= '--link-color:' . $content->link_color->normal . ';';
}
if (isset($content->link_color->hover) && $content->link_color->hover) {
$style .= '--link-color-hover:' . $content->link_color->hover . ';';
}
if (isset($content->link_backround->normal) && $content->link_backround->normal) {
$style .= '--background-color:' . $content->link_backround->normal . ';';
}
if (isset($content->link_backround->hover) && $content->link_backround->hover) {
$style .= '--background-color-hover:' . $content->link_backround->hover . ';';
}
if (isset($content->icon_color->normal) && $content->icon_color->normal) {
$style .= '--icon-color:' . $content->icon_color->normal . ';';
}
if (isset($content->icon_color->hover) && $content->icon_color->hover) {
$style .= '--icon-color-hover:' . $content->icon_color->hover . ';';
}
if (isset($content->link_font) && $content->link_font) {
$style .= self::parseFontProperties($content->link_font);
}
$style .= '}';
if (isset($content->link_padding) && $content->link_padding) {
$responsiveItems = [
'.nav-link' => [
['type' => 'padding', 'value' => $content->link_padding]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$menuClasses = ['page-inner-nav', 'gumshoe'];
if ($enable_fixed && $menu_type != 'float') {
$menuClasses[] = 'nav-fixed';
}
if ($menu_type == 'menu') {
$menuClasses[] = 'nav-' . $menu_align;
}
if ($menu_type == 'float') {
$menuClasses[] = 'nav-' . $menu_position;
}
if ($menu_type) {
$menuClasses[] = 'nav-' . $menu_type;
}
if ($menu_type == 'menu') {
$menuClasses[] = 'navbar navbar-expand-sm p-sm-0';
}
if ($menu_seperate && $menu_align != 'center') {
$menuClasses[] = 'nav-seperate';
}
if (isset($content->fon_class) && $content->fon_class) {
$menuClasses[] = $content->fon_class;
}
foreach ($disable as $k => $d) {
if ($k == 'xs') {
$menuClasses[] = 'd-' . $d;
}
else {
$menuClasses[] = 'd-' . $k . '-' . $d;
}
}
$this->addAsset('gumshoe');
$output = '';
if ($items) {
$output .= '<div id="' . $widgetId . '" class="' . implode(' ', $menuClasses) . '">';
if ($menu_type == 'menu') {
$output .= '<div class="container">';
$output .= '<a class="navbar-brand d-inline-block d-sm-none fs-16 fw-bold" href="javascript:void(0)">' . __('theme/quick_access') . '</a>';
$output .= '<button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#' . $widgetId . 'navbar" aria-controls="navbarsExample03" aria-expanded="false" aria-label="Toggle navigation">' . "\n" . ' <i class="fa-solid fa-bars"></i>';
$output .= '</button>';
$output .= '<div class="navbar-collapse collapse w-100" id="' . $widgetId . 'navbar" style="">';
}
$output .= '<ul class="nav ' . ($menu_type != 'menu' ? 'list-group' : 'w-100 flex-column flex-sm-row') . '">';
foreach ($items as $key => $item) {
if ($item) {
$menu_title = (isset($item->menu_title->{$this->lang}) && $item->menu_title->{$this->lang} ? $item->menu_title->{$this->lang} : array_values((array) $item->menu_title)[0] ?? '');
$menu_external = (isset($item->menu_external) && $item->menu_external == 'yes' ? true : false);
$menu_link = (isset($item->menu_link) && $item->menu_link ? $item->menu_link : '#');
$menu_external_link = (isset($item->menu_external_link->{$this->lang}) && $item->menu_external_link->{$this->lang} ? $item->menu_external_link->{$this->lang} : '#');
$menu_target = (isset($item->menu_target) && $item->menu_target ? $item->menu_target : '_self');
$show_icon = (isset($item->show_icon) && $item->show_icon == 'yes' ? true : false);
$menu_icon = (isset($item->menu_icon) && $item->menu_icon ? $item->menu_icon : '');
if ($menu_external) {
$menu_external_link = self::checkLink($menu_external_link);
}
$output .= '<li class="nav-item ' . (($key == 0) && !$menu_external ? 'active' : '') . ' ' . ($menu_type == 'list' ? 'list-group-item' : '') . '">';
$output .= '<a class="nav-link ' . ($menu_external ? 'external-link' : 'fon-scroll-button') . '" ' . (($key == 0) && !$menu_external ? 'aria-current="page"' : '') . ' href="' . ($menu_external ? $menu_external_link : $menu_link) . '" ' . ($menu_external ? 'target="' . $menu_target . '"' : '') . '>';
if ($menu_type == 'float') {
$output .= '<span class="nav-link-icon">';
if ($show_icon && $menu_icon) {
$output .= '<i class="' . $menu_icon . '"></i>';
}
else {
$output .= '<i class="fa-solid fa-circle"></i>';
}
$output .= '</span>';
$output .= '<span class="nav-link-text">';
$output .= $menu_title;
$output .= '</span>';
}
else {
$output .= ($show_icon && $menu_icon ? '<i class="' . $menu_icon . '"></i> ' : '');
$output .= $menu_title;
}
$output .= '</a>';
$output .= '</li>';
}
}
$output .= '</ul>';
if ($menu_type == 'menu') {
$output .= '</div>';
$output .= '</div>';
}
$output .= '</div>';
}
return $output;
}
private function product_wizard_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
require_once __DIR__ . '/builder/widget-styles/product_wizard.php';
$widgetId = 'fon-widget-' . $moduleId;
$scriptId = 'fon-widget-' . $moduleId . '-data';
$display_mode = (isset($content->display_mode) && $content->display_mode ? $content->display_mode : 'inline');
$trigger_class = (isset($content->trigger_class) && $content->trigger_class ? $content->trigger_class : 'btn btn-default btn-lg');
$trigger_align = (isset($content->trigger_align) && $content->trigger_align ? $content->trigger_align : 'center');
$container_width = (isset($content->container_width) && $content->container_width ? $content->container_width : '');
$container_width = ProductWizardHelper::getValidatedMaxWidth($container_width);
$accent_color = (isset($content->accent_color) && $content->accent_color ? $content->accent_color : '#4f46e5');
$trigger_text = self::getFieldMultilingualText($content->trigger_text ?? NULL, $this->lang, 'Ürün Sihirbazı');
$back_btn_text = self::getFieldMultilingualText($content->back_btn_text ?? NULL, $this->lang, 'Geri');
$next_btn_text = self::getFieldMultilingualText($content->next_btn_text ?? NULL, $this->lang, 'Devam Et');
$result_btn_text = self::getFieldMultilingualText($content->result_btn_text ?? NULL, $this->lang, 'Sonucu Görüntüle');
$restart_btn_text = self::getFieldMultilingualText($content->restart_btn_text ?? NULL, $this->lang, 'Testi Yeniden Başlat');
$result_badge_text = self::getFieldMultilingualText($content->result_badge_text ?? NULL, $this->lang, 'Analiz Tamamlandı');
$result_title_text = self::getFieldMultilingualText($content->result_title_text ?? NULL, $this->lang, 'Sizin için en uygun plan');
$result_subtitle_text = self::getFieldMultilingualText($content->result_subtitle_text ?? NULL, $this->lang, 'Verdiğiniz yanıtlara göre aşağıdaki paketi öneriyoruz.');
$planIds = (isset($content->plans) && $content->plans ? $content->plans : 'none');
$plans = [];
$finalPlans = [];
$scoresMap = [];
if ($planIds != 'none') {
$planIds = ProductWizardHelper::parsePlanSource($planIds);
if ($planIds) {
$plans = $this->getProducts('', $planIds, count($planIds), true);
}
}
if ($plans) {
$colorMap = ProductWizardHelper::generateColorClasses($plans);
foreach ($plans as $k => $plan) {
$scoresMap[$plan['id']] = 0;
$id = $plan['id'];
$type = $plan['type'] ?? '';
$features = $plan['features'] ?? NULL;
$options = $plan['options'] ?? [];
$prices = $plan['prices'] ?? [];
$currency_symbols = self::getCurrencySymbols();
$productPrice = self::calculatePrices($prices, $currency_symbols, $plan['override_usrcurrency'], $type);
$desc = '';
$featuresArr = ProductWizardHelper::maybeJsonToArray($features);
if ($featuresArr !== null && isset($featuresArr['slogan'])) {
$desc = $featuresArr['slogan'];
}
$featuresList = [];
if ($type === 'server') {
$featuresList = ProductWizardHelper::parseFeaturesServer($options);
}
else if ($type === 'special') {
if ($featuresArr !== null) {
if (isset($featuresArr['features'])) {
$featuresList = ProductWizardHelper::parseFeaturesArray($featuresArr);
}
else {
$clOptions = ProductWizardHelper::maybeJsonToArray($plan['cl_options'] ?? NULL) ?? [];
$featuresList = ProductWizardHelper::parseFeaturesSpecialColumns($featuresArr, $clOptions);
}
}
else {
$featuresList = ProductWizardHelper::parseFeaturesString((string) $features);
}
}
else if ($featuresArr !== null) {
if (isset($featuresArr['features'])) {
$featuresList = ProductWizardHelper::parseFeaturesArray($featuresArr);
}
}
else if (is_string($features) && trim($features) !== '') {
$featuresList = ProductWizardHelper::parseFeaturesString($features);
}
if (isset($plan['options_lang']['external_link']) && $plan['options_lang']['external_link'] != '') {
$buy_link = $plan['options_lang'];
}
else if (isset($plan['options']['external_link']) && $plan['options']['external_link'] != '') {
$buy_link = $plan['options']['external_link'];
}
else {
$buy_link = Controllers::$init->CRLink('order-steps', [$type, $id]);
}
if (isset($plan['options_lang']['buy_button_name']) && $plan['options_lang']['buy_button_name'] != '') {
$buy_button_name = $plan['options_lang']['buy_button_name'];
}
else if (isset($plan['options']['buy_button_name']) && $plan['options']['buy_button_name'] != '') {
$buy_button_name = $plan['options']['buy_button_name'];
}
else {
$buy_button_name = __('website/index/add-basket-button');
}
$finalPlans[$id] = ['colorClass' => $colorMap[$id], 'name' => $plan['title'] ?? '', 'desc' => $desc, 'price' => (isset($productPrice['price']) && $productPrice['price'] ? strip_tags($productPrice['price']) : ''), 'period' => $productPrice['period'] ?? '', 'features' => $featuresList, 'buyLink' => $buy_link, 'buyButtonName' => $buy_button_name];
}
}
$steps = (isset($content->questions) && $content->questions ? $content->questions : []);
$finalSteps = [];
$countSteps = count($steps);
if ($steps) {
foreach ($steps as $k => $step) {
$title = self::getFieldMultilingualText($step->title ?? NULL, $this->lang, 'Soru ' . ($k + 1));
$desc = self::getFieldMultilingualText($step->desc ?? NULL, $this->lang, '');
$options = [];
if (isset($step->options) && is_array($step->options) && 0 < count($step->options)) {
foreach ($step->options as $option) {
$optionTitle = self::getFieldMultilingualText($option->title ?? NULL, $this->lang, '');
$optionDesc = self::getFieldMultilingualText($option->desc ?? NULL, $this->lang, '');
$optionIcon = $option->icon ?? '';
$optionScores = $option->scores ?? '';
if (!empty($optionScores) && is_string($optionScores)) {
$optionScores = ProductWizardHelper::parseScores($optionScores);
}
$options[] = ['icon' => $optionIcon, 'title' => $optionTitle, 'desc' => $optionDesc, 'score' => $optionScores];
}
}
if ($title && $options) {
$finalSteps[] = ['question' => $title, 'desc' => $desc, 'options' => $options];
}
}
}
$payload = [
'scriptId' => $scriptId,
'widgetId' => $widgetId,
'labels' => ['resultBtn' => $result_btn_text, 'restartBtn' => $restart_btn_text, 'resultBadge' => $result_badge_text, 'resultTitle' => $result_title_text, 'resultSubtitle' => $result_subtitle_text, 'triggerText' => $trigger_text, 'triggerClass' => $trigger_class, 'backBtn' => $back_btn_text, 'nextBtn' => $next_btn_text, 'accentColor' => $accent_color],
'steps' => $finalSteps,
'plans' => $finalPlans,
'scoresMap' => $scoresMap
];
$encoded = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (!is_string($encoded)) {
$encoded = '{}';
}
$style = '';
if ($content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$this->addAsset('fon-product-wizard');
$output = '';
if ($steps) {
$modalUid = 'fonPWModal_' . md5($widgetId);
if ($display_mode === 'modal') {
$output .= '<p class="text-' . $trigger_align . '">';
$output .= '<button type="button" class="' . htmlspecialchars($trigger_class) . '" data-bs-toggle="modal" data-bs-target="#' . $modalUid . '">';
$output .= '<i class="fa-solid fa-wand-magic-sparkles me-2"></i>' . $trigger_text;
$output .= '</button>';
$output .= '</p>';
$output .= '<div class="modal fade" id="' . $modalUid . '" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-hidden="true">';
$output .= ' <div class="modal-dialog modal-dialog-centered fon-wz-dialog">';
$output .= ' <div class="modal-content border-0 p-0 rounded-4 overflow-hidden position-relative">';
$output .= ' <button type="button" class="fon-wz-modal-close" data-bs-dismiss="modal" aria-label="Kapat">✕</button>';
}
$maxWidthStyle = ($display_mode === 'modal' ? '' : 'max-width:' . $container_width . ';');
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-product-wizard-widget ' . ($content->fon_class ?? '') . '" data-display="' . $display_mode . '" data-script-id="' . $scriptId . '" style="--fpw-accent:' . $accent_color . '; ' . $maxWidthStyle . '" ' . ($display_mode === 'modal' ? 'data-modal-id="' . $modalUid . '"' : '') . '>';
$output .= ' <div class="fon-wizard-progress">';
$output .= ' <div class="fon-wizard-progress-fill" style="width:25%"></div>';
$output .= ' </div>';
$output .= ' <div class="fon-wizard-header">';
$output .= ' <div class="fon-wizard-step-label">' . __('theme/wizard-step') . ' <span class="fon-current-step">1</span> / ' . $countSteps . '</div>';
$output .= ' <p class="fon-wizard-question"></p>';
$output .= ' <p class="fon-wizard-desc"></p>';
$output .= ' </div>';
$output .= ' <div class="fon-wizard-body">';
$output .= ' <div class="fon-wizard-options fon-step-panel"></div>';
$output .= ' </div>';
$output .= ' <div class="fon-wizard-footer">';
$output .= ' <button type="button" class="fon-btn-back" disabled><i class="fa-solid fa-angle-left"></i> ' . $back_btn_text . '</button>';
$output .= ' <div class="fon-wizard-dots"></div>';
$output .= ' <button type="button" class="fon-btn-next" disabled>' . $next_btn_text . ' <i class="fa-solid fa-angle-right"></i> </button>';
$output .= ' </div>';
$output .= '</div>';
if ($display_mode === 'modal') {
$output .= ' </div>';
$output .= ' </div>';
$output .= '</div>';
}
$output .= '<script type="application/json" id="' . $scriptId . '">' . htmlspecialchars($encoded, ENT_NOQUOTES, 'UTF-8') . '</script>';
}
return $output;
}
private function progress_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$type = (isset($content->type) && $content->type ? $content->type : 'bar');
$striped = (isset($content->striped) && $content->striped == 'yes' ? true : false);
$animated = (isset($content->animated) && $content->animated == 'yes' ? true : false);
$column = (isset($content->column) && $content->column ? (array) $content->column : ['xl' => 4, 'lg' => 4, 'md' => 3, 'sm' => 2, 'xs' => 1]);
$width = (isset($content->width) && $content->width ? $content->width : '160');
$items = (isset($content->items) && $content->items ? $content->items : []);
$xs = min(6, max(1, (int) ($column['xs'] ?? 1)));
$sm = min(6, max(1, (int) ($column['sm'] ?? 2)));
$md = min(6, max(1, (int) ($column['md'] ?? 3)));
$lg = min(6, max(1, (int) ($column['lg'] ?? 4)));
$xl = min(6, max(1, (int) ($column['xl'] ?? 4)));
$rowClasses = sprintf('row g-3 row-cols-%d row-cols-sm-%d row-cols-md-%d row-cols-lg-%d row-cols-xl-%d', $xs, $sm, $md, $lg, $xl);
$style = '';
if ($content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
if ($items) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-progress-widget ' . ($content->fon_class ?? '') . '">';
if ($type == 'circle') {
$output .= '<div class="fon-progress-circle-wrapper ' . $rowClasses . '">';
}
foreach ($items as $index => $item) {
$title = '';
if (is_object($item->title)) {
$title = (isset($item->title->{$this->lang}) && $item->title->{$this->lang} ? $item->title->{$this->lang} : array_values((array) $item->title)[0] ?? '');
}
else if (is_string($item->title)) {
$title = $item->title;
}
$subtitle = '';
if (is_object($item->subtitle)) {
$subtitle = (isset($item->subtitle->{$this->lang}) && $item->subtitle->{$this->lang} ? $item->subtitle->{$this->lang} : array_values((array) $item->subtitle)[0] ?? '');
}
else if (is_string($item->subtitle)) {
$subtitle = $item->subtitle;
}
$description = '';
if (is_object($item->description)) {
$description = (isset($item->description->{$this->lang}) && $item->description->{$this->lang} ? $item->description->{$this->lang} : array_values((array) $item->description)[0] ?? '');
}
else if (is_string($item->description)) {
$description = $item->description;
}
$value = (isset($item->value) && $item->value ? $item->value : '0');
$color = (isset($item->color) && $item->color ? $item->color : 'var(--theme-primary)');
if ($type == 'bar') {
$output .= '<div class="fon-progress-wrapper" data-value="' . $value . '">';
$output .= '<div class="fon-progress-info">';
$output .= '<h3 class="fon-progress-title">' . $title . '</h3>';
if ($subtitle) {
$output .= '<span class="fon-progress-percent"><span class="fon-progress-sub me-1 fw-normal">' . $subtitle . '</span><span class="fon-progress-rate" style="color: ' . $color . ';">0%</span></span>';
}
else {
$output .= '<span class="fon-progress-percent"><span class="fon-progress-rate" style="color: ' . $color . ';">0%</span></span>';
}
$output .= '</div>';
$output .= '<div class="progress fon-custom-progress">';
$output .= '<div class="progress-bar ' . ($striped ? 'progress-bar-striped' : '') . ' ' . ($striped && $animated ? 'progress-bar-animated' : '') . '" ' . "\n" . ' role="progressbar" ' . "\n" . ' style="width: 0%; background-color: ' . $color . ';"' . "\n" . ' aria-valuenow="' . $value . '" ' . "\n" . ' aria-valuemin="0" ' . "\n" . ' aria-valuemax="100">';
$output .= '</div>';
$output .= '</div>';
if ($description) {
$output .= '<p class="fon-progress-description mt-2">' . $description . '</p>';
}
$output .= '</div>';
}
else if ($type == 'circle') {
$output .= '<div class="col">';
$output .= '<div class="fon-circle-progress-wrapper text-center" data-value="' . $value . '">';
$output .= '<div class="fon-circle-progress-container mx-auto mb-3 position-relative" style="width: ' . $width . 'px;">';
$output .= '<svg viewBox="0 0 100 100">';
$output .= '<circle class="fon-circle-progress-bg" cx="50" cy="50" r="45"></circle>';
$output .= '<circle class="fon-circle-progress-bar is-striped is-animated" cx="50" cy="50" r="45" style="stroke: ' . $color . '"></circle>';
$output .= '</svg>';
$output .= '<div class="fon-circle-progress-info">';
$output .= '<span class="fon-circle-progress-percent">0%</span>';
if ($subtitle) {
$output .= '<span class="fon-progress-sub mx-auto">' . $subtitle . '</span>';
}
$output .= '</div>';
$output .= '</div>';
if ($title) {
$output .= '<h3 class="fon-progress-title d-inline-block my-2">' . $title . '</h3>';
}
if ($description) {
$output .= '<p class="fon-progress-description px-3">' . $description . '</p>';
}
$output .= '</div>';
$output .= '</div>';
}
}
if ($type == 'circle') {
$output .= '</div>';
}
$output .= '</div>';
}
return $output;
}
private function raw_content_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$raw_code = (isset($content->raw_code->{$this->lang}) && $content->raw_code->{$this->lang} ? $content->raw_code->{$this->lang} : array_values((array) $content->raw_code)[0] ?? '');
if ($raw_code) {
$raw_code = self::parseShortcodesToHtml($raw_code);
}
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="' . $content->fon_class . '">';
$output .= $raw_code;
$output .= '</div>';
return $output;
}
private function references_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetPages($content, $moduleId, $pageData, 'references');
}
private function review_badge_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'micro_button');
$value_display = (isset($content->value_display) && $content->value_display ? $content->value_display : 'both');
$review_provider = (isset($content->review_provider) && $content->review_provider ? $content->review_provider : 'google');
$review_title = (isset($content->review_title->{$this->lang}) && $content->review_title->{$this->lang} ? $content->review_title->{$this->lang} : $this->language['review_badge']['default_title']);
$review_score = (isset($content->review_score) && $content->review_score ? $content->review_score : 0);
$review_count = (isset($content->review_count) && $content->review_count ? $content->review_count : 0);
$review_link = (isset($content->review_link) && $content->review_link ? $content->review_link : '');
$review_link_rel = (isset($content->review_link_rel) && $content->review_link_rel ? $content->review_link_rel : []);
$review_link_rel = ($review_link_rel ? ' rel="' . implode(' ', $review_link_rel) . '" ' : '');
$color = ($review_provider == 'trustpilot' ? '#00B67A' : '#fbb004');
$svgStyle = 'height: 25px;';
$starSize = 18;
$ticonfill = '#00b67a';
$ticon2fill = '#005128';
$ttextfill = '#191919';
switch ($widget_style) {
case 'micro_button':
$ticonfill = $ttextfill = '#fff';
$ticon2fill = '#00b67a';
break;
case 'micro_horizontal':
break;
case 'mini_box':
$svgStyle = 'height: 35px;';
$starSize = 25;
break;
case 'flex_box':
$svgStyle = 'height: 35px;';
$starSize = 20;
$ttextfill = '#fff';
break;
case 'flex_mini':
$svgStyle = 'height: 20px;';
$starSize = 12;
$ttextfill = '#fff';
break;
}
$stars = self::getStarRating($review_score, $color, $starSize);
$trustpilot = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1132.8 278.2" style="' . $svgStyle . '" preserveAspectRatio="xMidYMid" ><path d="M297.7 98.6h114.7V120h-45.1v120.3h-24.8V120h-44.9V98.6zm109.8 39.1h21.2v19.8h.4c.7-2.8 2-5.5 3.9-8.1 1.9-2.6 4.2-5.1 6.9-7.2 2.7-2.2 5.7-3.9 9-5.3 3.3-1.3 6.7-2 10.1-2 2.6 0 4.5.1 5.5.2s2 .3 3.1.4v21.8c-1.6-.3-3.2-.5-4.9-.7-1.7-.2-3.3-.3-4.9-.3-3.8 0-7.4.8-10.8 2.3-3.4 1.5-6.3 3.8-8.8 6.7-2.5 3-4.5 6.6-6 11s-2.2 9.4-2.2 15.1v48.8h-22.6V137.7zm164 102.6h-22.2V226h-.4c-2.8 5.2-6.9 9.3-12.4 12.4-5.5 3.1-11.1 4.7-16.8 4.7-13.5 0-23.3-3.3-29.3-10s-9-16.8-9-30.3v-65.1H504v62.9c0 9 1.7 15.4 5.2 19.1 3.4 3.7 8.3 5.6 14.5 5.6 4.8 0 8.7-.7 11.9-2.2 3.2-1.5 5.8-3.4 7.7-5.9 2-2.4 3.4-5.4 4.3-8.8.9-3.4 1.3-7.1 1.3-11.1v-59.5h22.6v102.5zm38.5-32.9c.7 6.6 3.2 11.2 7.5 13.9 4.4 2.6 9.6 4 15.7 4 2.1 0 4.5-.2 7.2-.5s5.3-1 7.6-1.9c2.4-.9 4.3-2.3 5.9-4.1 1.5-1.8 2.2-4.1 2.1-7-.1-2.9-1.2-5.3-3.2-7.1-2-1.9-4.5-3.3-7.6-4.5-3.1-1.1-6.6-2.1-10.6-2.9-4-.8-8-1.7-12.1-2.6-4.2-.9-8.3-2.1-12.2-3.4-3.9-1.3-7.4-3.1-10.5-5.4-3.1-2.2-5.6-5.1-7.4-8.6-1.9-3.5-2.8-7.8-2.8-13 0-5.6 1.4-10.2 4.1-14 2.7-3.8 6.2-6.8 10.3-9.1 4.2-2.3 8.8-3.9 13.9-4.9 5.1-.9 10-1.4 14.6-1.4 5.3 0 10.4.6 15.2 1.7 4.8 1.1 9.2 2.9 13.1 5.5 3.9 2.5 7.1 5.8 9.7 9.8 2.6 4 4.2 8.9 4.9 14.6h-23.6c-1.1-5.4-3.5-9.1-7.4-10.9-3.9-1.9-8.4-2.8-13.4-2.8-1.6 0-3.5.1-5.7.4-2.2.3-4.2.8-6.2 1.5-1.9.7-3.5 1.8-4.9 3.2-1.3 1.4-2 3.2-2 5.5 0 2.8 1 5 2.9 6.7 1.9 1.7 4.4 3.1 7.5 4.3 3.1 1.1 6.6 2.1 10.6 2.9 4 .8 8.1 1.7 12.3 2.6 4.1.9 8.1 2.1 12.1 3.4 4 1.3 7.5 3.1 10.6 5.4 3.1 2.3 5.6 5.1 7.5 8.5 1.9 3.4 2.9 7.7 2.9 12.7 0 6.1-1.4 11.2-4.2 15.5-2.8 4.2-6.4 7.7-10.8 10.3-4.4 2.6-9.4 4.6-14.8 5.8-5.4 1.2-10.8 1.8-16.1 1.8-6.5 0-12.5-.7-18-2.2-5.5-1.5-10.3-3.7-14.3-6.6-4-3-7.2-6.7-9.5-11.1-2.3-4.4-3.5-9.7-3.7-15.8H610zm74.6-69.7h17.1v-30.8h22.6v30.8h20.4v16.9h-20.4v54.8c0 2.4.1 4.4.3 6.2.2 1.7.7 3.2 1.4 4.4.7 1.2 1.8 2.1 3.3 2.7 1.5.6 3.4.9 6 .9 1.6 0 3.2 0 4.8-.1 1.6-.1 3.2-.3 4.8-.7v17.5c-2.5.3-5 .5-7.3.8-2.4.3-4.8.4-7.3.4-6 0-10.8-.6-14.4-1.7-3.6-1.1-6.5-2.8-8.5-5-2.1-2.2-3.4-4.9-4.2-8.2-.7-3.3-1.2-7.1-1.3-11.3v-60.5h-17.1v-17.1zm76.1 0h21.4v13.9h.4c3.2-6 7.6-10.2 13.3-12.8 5.7-2.6 11.8-3.9 18.5-3.9 8.1 0 15.1 1.4 21.1 4.3 6 2.8 11 6.7 15 11.7 4 5 6.9 10.8 8.9 17.4 2 6.6 3 13.7 3 21.2 0 6.9-.9 13.6-2.7 20-1.8 6.5-4.5 12.2-8.1 17.2-3.6 5-8.2 8.9-13.8 11.9-5.6 3-12.1 4.5-19.7 4.5-3.3 0-6.6-.3-9.9-.9-3.3-.6-6.5-1.6-9.5-2.9-3-1.3-5.9-3-8.4-5.1-2.6-2.1-4.7-4.5-6.5-7.2h-.4v51.2h-22.6V137.7zm79 51.4c0-4.6-.6-9.1-1.8-13.5-1.2-4.4-3-8.2-5.4-11.6-2.4-3.4-5.4-6.1-8.9-8.1-3.6-2-7.7-3.1-12.3-3.1-9.5 0-16.7 3.3-21.5 9.9-4.8 6.6-7.2 15.4-7.2 26.4 0 5.2.6 10 1.9 14.4 1.3 4.4 3.1 8.2 5.7 11.4 2.5 3.2 5.5 5.7 9 7.5 3.5 1.9 7.6 2.8 12.2 2.8 5.2 0 9.5-1.1 13.1-3.2 3.6-2.1 6.5-4.9 8.8-8.2 2.3-3.4 4-7.2 5-11.5.9-4.3 1.4-8.7 1.4-13.2zm39.9-90.5h22.6V120h-22.6V98.6zm0 39.1h22.6v102.6h-22.6V137.7zm42.8-39.1H945v141.7h-22.6V98.6zm91.9 144.5c-8.2 0-15.5-1.4-21.9-4.1-6.4-2.7-11.8-6.5-16.3-11.2-4.4-4.8-7.8-10.5-10.1-17.1-2.3-6.6-3.5-13.9-3.5-21.8 0-7.8 1.2-15 3.5-21.6 2.3-6.6 5.7-12.3 10.1-17.1 4.4-4.8 9.9-8.5 16.3-11.2 6.4-2.7 13.7-4.1 21.9-4.1s15.5 1.4 21.9 4.1c6.4 2.7 11.8 6.5 16.3 11.2 4.4 4.8 7.8 10.5 10.1 17.1 2.3 6.6 3.5 13.8 3.5 21.6 0 7.9-1.2 15.2-3.5 21.8-2.3 6.6-5.7 12.3-10.1 17.1-4.4 4.8-9.9 8.5-16.3 11.2-6.4 2.7-13.7 4.1-21.9 4.1zm0-17.9c5 0 9.4-1.1 13.1-3.2 3.7-2.1 6.7-4.9 9.1-8.3 2.4-3.4 4.1-7.3 5.3-11.6 1.1-4.3 1.7-8.7 1.7-13.2 0-4.4-.6-8.7-1.7-13.1s-2.9-8.2-5.3-11.6c-2.4-3.4-5.4-6.1-9.1-8.2-3.7-2.1-8.1-3.2-13.1-3.2s-9.4 1.1-13.1 3.2c-3.7 2.1-6.7 4.9-9.1 8.2-2.4 3.4-4.1 7.2-5.3 11.6-1.1 4.4-1.7 8.7-1.7 13.1 0 4.5.6 8.9 1.7 13.2 1.1 4.3 2.9 8.2 5.3 11.6 2.4 3.4 5.4 6.2 9.1 8.3 3.7 2.2 8.1 3.2 13.1 3.2zm58.4-87.5h17.1v-30.8h22.6v30.8h20.4v16.9h-20.4v54.8c0 2.4.1 4.4.3 6.2.2 1.7.7 3.2 1.4 4.4.7 1.2 1.8 2.1 3.3 2.7 1.5.6 3.4.9 6 .9 1.6 0 3.2 0 4.8-.1 1.6-.1 3.2-.3 4.8-.7v17.5c-2.5.3-5 .5-7.3.8-2.4.3-4.8.4-7.3.4-6 0-10.8-.6-14.4-1.7-3.6-1.1-6.5-2.8-8.5-5-2.1-2.2-3.4-4.9-4.2-8.2-.7-3.3-1.2-7.1-1.3-11.3v-60.5h-17.1v-17.1z" fill="' . $ttextfill . '"/><path fill="' . $ticonfill . '" d="M271.3 98.6H167.7L135.7 0l-32.1 98.6L0 98.5l83.9 61L51.8 258l83.9-60.9 83.8 60.9-32-98.5 83.8-60.9z"/><path fill="' . $ticon2fill . '" d="M194.7 181.8l-7.2-22.3-51.8 37.6z"/></svg>';
$google = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 168" style="' . $svgStyle . '" preserveAspectRatio="xMidYMid"><g>' . "\n" . ' <path d="M496.052455,102.672055 L510.255737,112.140909 C505.6459,118.931075 494.619668,130.580258 475.557368,130.580258 C451.885231,130.580258 434.255719,112.2655 434.255719,88.967133 C434.255719,64.1736841 452.072116,47.3540078 473.563925,47.3540078 C495.180323,47.3540078 505.77049,64.5474546 509.19672,73.8294242 L511.065574,78.5638516 L455.373756,101.613038 C459.609823,109.960581 466.213103,114.196648 475.557368,114.196648 C484.901633,114.196648 491.380323,109.586811 496.052455,102.672055 L496.052455,102.672055 Z M452.383592,87.6589359 L489.573765,72.2097517 C487.518026,67.0392586 481.413107,63.3638478 474.124581,63.3638478 C464.842612,63.3638478 451.947526,71.5868007 452.383592,87.6589359 L452.383592,87.6589359 Z" fill="#FF302F"/>' . "\n" . ' <path d="M407.406531,4.93104632 L425.347519,4.93104632 L425.347519,126.780257 L407.406531,126.780257 L407.406531,4.93104632 L407.406531,4.93104632 Z" fill="#20B15A"/>' . "\n" . ' <path d="M379.124557,50.5933528 L396.442594,50.5933528 L396.442594,124.599929 C396.442594,155.311412 378.314721,167.957316 356.885207,167.957316 C336.701596,167.957316 324.554051,154.376986 320.00651,143.350753 L335.891759,136.747473 C338.757334,143.537639 345.67209,151.573706 356.885207,151.573706 C370.652424,151.573706 379.124557,143.039278 379.124557,127.091732 L379.124557,121.111404 L378.501606,121.111404 C374.39013,126.095011 366.540947,130.580258 356.573731,130.580258 C335.767169,130.580258 316.704869,112.452385 316.704869,89.0917231 C316.704869,65.6064713 335.767169,47.2917126 356.573731,47.2917126 C366.478652,47.2917126 374.39013,51.7146646 378.501606,56.5736822 L379.124557,56.5736822 L379.124557,50.5933528 L379.124557,50.5933528 Z M380.370459,89.0917231 C380.370459,74.3900801 370.590128,63.6753233 358.131109,63.6753233 C345.547499,63.6753233 334.957333,74.3900801 334.957333,89.0917231 C334.957333,103.606481 345.547499,114.134352 358.131109,114.134352 C370.590128,114.196648 380.370459,103.606481 380.370459,89.0917231 L380.370459,89.0917231 Z" fill="#3686F7"/>' . "\n" . ' <path d="M218.21632,88.7802476 C218.21632,112.763861 199.527791,130.393373 176.603195,130.393373 C153.678599,130.393373 134.990069,112.701565 134.990069,88.7802476 C134.990069,64.6720448 153.678599,47.1048274 176.603195,47.1048274 C199.527791,47.1048274 218.21632,64.6720448 218.21632,88.7802476 L218.21632,88.7802476 Z M200.026151,88.7802476 C200.026151,73.8294242 189.186804,63.5507331 176.603195,63.5507331 C164.019585,63.5507331 153.180238,73.8294242 153.180238,88.7802476 C153.180238,103.606481 164.019585,114.009763 176.603195,114.009763 C189.186804,114.009763 200.026151,103.606481 200.026151,88.7802476 L200.026151,88.7802476 Z" fill="#FF302F"/>' . "\n" . ' <path d="M309.104867,88.967133 C309.104867,112.950746 290.416338,130.580258 267.491742,130.580258 C244.567146,130.580258 225.878617,112.950746 225.878617,88.967133 C225.878617,64.8589302 244.567146,47.3540078 267.491742,47.3540078 C290.416338,47.3540078 309.104867,64.796635 309.104867,88.967133 L309.104867,88.967133 Z M290.852404,88.967133 C290.852404,74.0163095 280.013057,63.7376184 267.429447,63.7376184 C254.845837,63.7376184 244.00649,74.0163095 244.00649,88.967133 C244.00649,103.793366 254.845837,114.196648 267.429447,114.196648 C280.075352,114.196648 290.852404,103.731071 290.852404,88.967133 L290.852404,88.967133 Z" fill="#FFBA40"/>' . "\n" . ' <path d="M66.5900525,112.327794 C40.4884066,112.327794 20.0556146,91.2720515 20.0556146,65.1704056 C20.0556146,39.0687598 40.4884066,18.0130168 66.5900525,18.0130168 C80.6687446,18.0130168 90.9474357,23.5572805 98.5474373,30.6589216 L111.068752,18.137607 C100.478585,7.98350613 86.3375984,0.258913997 66.5900525,0.258913997 C30.8326666,0.258913997 0.744134408,29.4130196 0.744134408,65.1704056 C0.744134408,100.927792 30.8326666,130.081897 66.5900525,130.081897 C85.9015328,130.081897 100.478585,123.727797 111.878588,111.891729 C123.590067,100.180251 127.203183,83.7343447 127.203183,70.4031939 C127.203183,66.2294223 126.704822,61.9310606 126.144166,58.7540106 L66.5900525,58.7540106 L66.5900525,76.0720477 L109.013014,76.0720477 C107.767112,86.9113947 104.340882,94.3245113 99.2949785,99.3704142 C93.1900592,105.537629 83.534319,112.327794 66.5900525,112.327794 L66.5900525,112.327794 L66.5900525,112.327794 Z" fill="#3686F7"/>' . "\n" . ' </g>' . "\n" . ' </svg>';
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-review-badge ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
if ($widget_style == 'micro_button') {
$output .= '<div class="fon-review-badge-micro-button position-relative d-flex align-items-center">';
$output .= '<div class="fon-review-badge-logo py-2 px-3 rounded-start-3 d-flex align-items-center justify-content-center border flex-shrink-0" style="background-color:' . ($review_provider == 'trustpilot' ? $color : 'var(--bs-theme-light)') . '; border-color:' . ($review_provider == 'trustpilot' ? $color : 'var(--bs-theme-light-100)') . '; height:40px;min-width:135px;">';
if ($review_provider == 'google') {
$output .= $google;
}
else if ($review_provider == 'trustpilot') {
$output .= $trustpilot;
}
$output .= '</div>';
$output .= '<div class="fon-review-badge-review py-2 px-3 rounded-end d-flex align-items-center bg-white border-end border-top border-bottom" style="height:40px;">';
if ($value_display == 'score') {
$output .= '<span class="fon-review-badge-score fs-6 text-dark strong">' . sprintf($this->language['review_badge']['score_short'], $review_score) . '</span>';
}
else if ($value_display == 'count') {
$output .= '<span class="fon-review-badge-score fs-6 text-dark strong">' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
else if ($value_display == 'both') {
$output .= '<span class="fon-review-badge-score fs-6 text-dark"><strong>' . sprintf($this->language['review_badge']['score_short'], $review_score) . '</strong> | ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
$output .= '</div>';
$output .= '<a href="' . $review_link . '" class="fon-review-badge-link stretched-link" target="_blank" ' . $review_link_rel . ' aria-label="' . $review_provider . '"></a>';
$output .= '</div>';
}
else if ($widget_style == 'micro_horizontal') {
$output .= '<div class="fon-review-badge-micro-horizontal position-relative d-flex align-items-' . ($review_provider == 'trustpilot' ? 'end' : 'center') . ' gap-3">';
$output .= '<span class="fon-review-badge-logo">';
if ($review_provider == 'google') {
$output .= $google;
}
else if ($review_provider == 'trustpilot') {
$output .= $trustpilot;
}
$output .= '</span>';
$output .= '<strong class="fon-review-badge-title text-dark">';
$output .= $review_title;
$output .= '</strong>';
$output .= '<span class="fon-review-badge-review">';
if ($value_display == 'score') {
$output .= '<span class="fon-review-badge-score">' . sprintf($this->language['review_badge']['score_short'], $review_score) . '</span>';
}
else if ($value_display == 'count') {
$output .= '<span class="fon-review-badge-score">' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
else if ($value_display == 'both') {
$output .= '<span class="fon-review-badge-score">' . sprintf($this->language['review_badge']['score_short'], $review_score) . ' | ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
$output .= '</span>';
$output .= '<span class="fon-review-badge-stars position-relative">';
$output .= '<span class="fon-review-badge-stars-empty d-flex gap-1">';
$output .= str_repeat('<span class="d-inline-flex align-items-center justify-content-center rounded bg-theme-light-200 text-white" style="width:' . ($starSize + 8) . 'px;height:' . ($starSize + 8) . 'px;"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>', 5);
$output .= '</span>';
$output .= '<span class="fon-review-badge-stars-fill d-flex gap-1 position-absolute start-0 top-0">' . $stars . '</span>';
$output .= '</span>';
$output .= '<a href="' . $review_link . '" class="fon-review-badge-link stretched-link" target="_blank" ' . $review_link_rel . ' aria-label="' . $review_provider . '"></a>';
$output .= '</div>';
}
else if ($widget_style == 'mini_box') {
$output .= '<div class="fon-review-badge-mini-box d-flex flex-column align-items-center justify-content-center position-relative">';
$output .= '<div class="fon-review-badge-logo mb-3">';
if ($review_provider == 'google') {
$output .= $google;
}
else if ($review_provider == 'trustpilot') {
$output .= $trustpilot;
}
$output .= '</div>';
$output .= '<span class="fon-review-badge-stars position-relative mb-2">';
$output .= '<span class="fon-review-badge-stars-empty d-flex gap-1">';
$output .= str_repeat('<span class="d-inline-flex align-items-center justify-content-center rounded bg-theme-light-200 text-white" style="width:' . ($starSize + 8) . 'px;height:' . ($starSize + 8) . 'px;"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>', 5);
$output .= '</span>';
$output .= '<span class="fon-review-badge-stars-fill d-flex gap-1 position-absolute start-0 top-0">' . $stars . '</span>';
$output .= '</span>';
$output .= '<div class="fon-review-badge-review fs-18 fw-semibold text-dark">';
if ($value_display == 'score') {
$output .= '<span class="fon-review-badge-score">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['score_short'], $review_score) . '</span>';
}
else if ($value_display == 'count') {
$output .= '<span class="fon-review-badge-score">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
else if ($value_display == 'both') {
$output .= '<span class="fon-review-badge-score">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['score_short'], $review_score) . ' | ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</span>';
}
$output .= '</div>';
$output .= '<a href="' . $review_link . '" class="fon-review-badge-link stretched-link" target="_blank" ' . $review_link_rel . ' aria-label="' . $review_provider . '"></a>';
$output .= '</div>';
}
else if ($widget_style == 'flex_box') {
$output .= '<div class="fon-review-badge-flex-box d-flex flex-column align-items-stretch justify-content-between position-relative bg-dark rounded-4 p-4 bg-theme-light-800 overflow-hidden" style="min-height:250px;max-width: 450px;">';
$output .= '<div class="fon-review-badge-header d-flex align-items-center justify-content-between position-relative">';
$output .= '<h5 class="fon-review-badge-score flex-shrink-1 w-50 text-white fw-light">' . sprintf($this->language['review_badge']['score_long'], $review_score) . '</h5>';
$output .= '<span class="fon-review-badge-icon text-white me-4 mt-4"><i class="fa-solid fa-laptop fa-3x"></i></span>';
$output .= '</div>';
$output .= '<div class="flex-grow-1"></div>';
$output .= '<div class="fon-review-badge-footer d-flex align-items-end justify-content-between position-relative">';
$output .= '<div class="fon-review-badge-review d-flex flex-column align-items-start justify-content-start">';
$output .= '<h6 class="fon-review-badge-score text-white fw-normal mb-0">' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</h6>';
$output .= '<div class="fon-review-badge-stars position-relative my-2">';
$output .= '<span class="fon-review-badge-stars-empty d-flex gap-1">';
$output .= str_repeat('<span class="d-inline-flex align-items-center justify-content-center rounded bg-theme-light-200 text-white" style="width:' . ($starSize + 8) . 'px;height:' . ($starSize + 8) . 'px;"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>', 5);
$output .= '</span>';
$output .= '<span class="fon-review-badge-stars-fill d-flex gap-1 position-absolute start-0 top-0">' . $stars . '</span>';
$output .= '</div>';
$output .= '<div class="fon-review-badge-title text-white">';
$output .= $review_title;
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="fon-review-badge-logo position-absolute end-0 bottom-0">';
if ($review_provider == 'google') {
$output .= $google;
}
else if ($review_provider == 'trustpilot') {
$output .= $trustpilot;
}
$output .= '</div>';
$output .= '</div>';
$output .= '<a href="' . $review_link . '" class="fon-review-badge-link stretched-link" target="_blank" ' . $review_link_rel . ' aria-label="' . $review_provider . '"></a>';
$output .= '</div>';
}
else if ($widget_style == 'flex_mini') {
$output .= '<div class="fon-review-badge-flex-mini d-flex align-items-center justify-content-start position-relative bg-theme-light-800 rounded-4 p-3 overflow-hidden" style="min-height:50px;">';
$output .= '<div class="fon-review-badge-icon text-white me-5 position-relative"><i class="fa-solid fa-laptop fa-2x"></i></div>';
$output .= '<div class="fon-review-badge-review d-flex flex-column align-items-start justify-content-start position-relative">';
if ($value_display == 'score') {
$output .= '<h6 class="fon-review-badge-score fs-14 mb-1 text-white">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['score_short'], $review_score) . '</h6>';
}
else if ($value_display == 'count') {
$output .= '<h6 class="fon-review-badge-score fs-14 mb-1 text-white">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</h6>';
}
else if ($value_display == 'both') {
$output .= '<h6 class="fon-review-badge-score fs-14 mb-1 text-white">' . $this->language['review_badge']['score'] . ' ' . sprintf($this->language['review_badge']['score_short'], $review_score) . ' | ' . sprintf($this->language['review_badge']['review_count'], $review_count) . '</h6>';
}
$output .= '<div class="fon-review-badge-stars position-relative">';
$output .= '<span class="fon-review-badge-stars-empty d-flex gap-1">';
$output .= str_repeat('<span class="d-inline-flex align-items-center justify-content-center rounded bg-theme-light-200 text-white" style="width:' . ($starSize + 8) . 'px;height:' . ($starSize + 8) . 'px;"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>', 5);
$output .= '</span>';
$output .= '<span class="fon-review-badge-stars-fill d-flex gap-1 position-absolute start-0 top-0">' . $stars . '</span>';
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="fon-review-badge-logo ms-auto position-relative">';
if ($review_provider == 'google') {
$output .= $google;
}
else if ($review_provider == 'trustpilot') {
$output .= $trustpilot;
}
$output .= '</div>';
$output .= '<a href="' . $review_link . '" class="fon-review-badge-link stretched-link" target="_blank" ' . $review_link_rel . ' aria-label="' . $review_provider . '"></a>';
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function server_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetProducts($content, $moduleId, $pageData, $row, 'server');
}
private function sidebar_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
if ($pageData['sidebar'] && 0 < count($pageData['sidebar'])) {
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-sidebar-widget sidebar-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="list-group ' . ($content->widget_style == 'horizontal' ? 'list-group-horizontal-md align-items-center justify-content-' . $content->align : '') . '">';
foreach ($pageData['sidebar'] as $sidebar) {
$output .= '<a href="' . $sidebar['link'] . '" class="list-group-item list-group-item-action">' . $sidebar['title'] . '</a>';
}
$output .= '</div>';
$output .= '</div>';
}
return $output;
}
private function slideshow_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$autoplay = (isset($content->autoplay) && $content->autoplay == 'yes' ? 1 : 0);
$pause_on_hover = (isset($content->pause) && $content->pause == 'yes' ? 1 : 0);
$interval = (isset($content->interval) && $content->interval ? $content->interval : 5);
$speed = (isset($content->speed) && $content->speed ? $content->speed : '800');
$content_container_option = (isset($content->content_width) && $content->content_width ? $content->content_width : '');
$slider_animation = (isset($content->animation_style) && $content->animation_style ? $content->animation_style : '');
$content_vertical_center = (isset($content->content_vertical_center) && $content->content_vertical_center = 'yes' ? 1 : 0);
$height = (isset($content->height) && $content->height ? $content->height : '');
$custom_height = (isset($content->custom_height) && $content->custom_height ? $content->custom_height : (object) ['xl' => '750', 'lg' => '700', 'md' => '600', 'sm' => '500', 'xs' => '450']);
$dot_controllers = (isset($content->dot_controllers) && $content->dot_controllers == 'yes' ? 1 : 0);
$dot_position = (isset($content->dot_controllers_position) && $content->dot_controllers_position ? 'dot-' . $content->dot_controllers_position : 'dot-bottom_center');
$arrow_controllers = (isset($content->arrow_controllers) && $content->arrow_controllers = 'yes' ? 1 : 0);
$arrow_position = (isset($content->arrow_controllers_position) && $content->arrow_controllers_position ? 'arrow-' . $content->arrow_controllers_position : 'arrow-center');
$arrow_on_hover = (isset($content->arrow_controllers_hover) && $content->arrow_controllers_hover = 'yes' ? 1 : 0);
$arrow_class = $arrow_position;
if ($arrow_on_hover) {
$arrow_class .= ' arrow-show-on-hover';
}
$this->addAsset(['slick', 'slick-animate']);
$style = '';
$style .= '#' . $widgetId . '.fon-slider .fon-item:not(:first-child) { display: none; }';
$style .= '#' . $widgetId . '.fon-slider.slick-initialized .fon-item { display: flex; }';
if ($height == 'full') {
$style .= '#' . $widgetId . '.fon-slider,#' . $widgetId . '.fon-slider .fon-item{';
$style .= 'height: 100vh;';
$style .= '}';
}
else {
$responsiveItems = [
'#' . $widgetId . ' .fon-item' => [
['type' => 'height', 'unit' => 'px!important', 'value' => $custom_height]
],
'#' . $widgetId . '.fon-slider' => [
['type' => 'height', 'unit' => 'px!important', 'value' => $custom_height]
]
];
$style .= self::parseResponsiveItems($responsiveItems);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-slideshow-widget fon-slider ' . $content->fon_class . ' ' . $dot_position . ' ' . $arrow_class . '"' . "\n\t\t" . ' data-id="fon-widget-slideshow-' . $moduleId . '"' . "\n\t\t" . ' data-effect="' . $slider_animation . '"' . "\n\t\t" . ' data-autoplay="' . ($autoplay ? 'true' : 'false') . '"' . "\n\t\t" . ' data-autoplay-speed="' . ($interval ? $interval * 1000 : '4000') . '"' . "\n\t\t" . ' data-speed="' . $speed . '"' . "\n\t\t" . ' data-dots="' . ($dot_controllers ? 'true' : 'false') . '"' . "\n\t\t" . ' data-arrows="' . ($arrow_controllers ? 'true' : 'false') . '"' . "\n\t\t" . ' data-pause="' . ($pause_on_hover && $autoplay ? 'true' : 'false') . '" style="overflow:hidden; ' . ($height != 'full' ? 'height:' . $custom_height->xl . 'px;' : '') . '">';
if (isset($content->items) && is_array($content->items)) {
foreach ($content->items as $item_key => $item_value) {
$isFirstSlide = $item_key === 0;
$uniqid = 'fon-slider-item-' . $moduleId . '-num-' . $item_key . '-key';
$content_class = (isset($item_value->slide_class) && $item_value->slide_class ? ' ' . $item_value->slide_class : '');
$patternStyle = $this->handlePatternImages($content_class, $pageData['page'], $pageData['tadress'], $isFirstSlide && $isLCPCandidate);
$image_in_column = (isset($item_value->use_slide_image) && $item_value->use_slide_image == 'yes' ? 1 : 0);
$image_column_width = (isset($item_value->slide_image_column) && $item_value->slide_image_column ? $item_value->slide_image_column : (object) []);
$image_column_width_xl = (isset($image_column_width->xl) && $image_column_width->xl ? (int) $image_column_width->xl : 6);
$image_column_width_lg = (isset($image_column_width->lg) && $image_column_width->lg ? (int) $image_column_width->lg : 6);
$image_column_width_md = (isset($image_column_width->md) && $image_column_width->md ? (int) $image_column_width->md : 6);
$image_column_width_sm = (isset($image_column_width->sm) && $image_column_width->sm ? (int) $image_column_width->sm : 6);
$image_column_width_xs = (isset($image_column_width->xs) && $image_column_width->xs ? (int) $image_column_width->xs : 6);
$slide_image_order = (isset($item_value->slide_image_order) && $item_value->slide_image_order ? $item_value->slide_image_order : (object) []);
$slide_image_order_xl = (isset($slide_image_order->xl) && $slide_image_order->xl ? (int) $slide_image_order->xl : 2);
$slide_image_order_lg = (isset($slide_image_order->lg) && $slide_image_order->lg ? (int) $slide_image_order->lg : 2);
$slide_image_order_md = (isset($slide_image_order->md) && $slide_image_order->md ? (int) $slide_image_order->md : 2);
$slide_image_order_sm = (isset($slide_image_order->sm) && $slide_image_order->sm ? (int) $slide_image_order->sm : 2);
$slide_image_order_xs = (isset($slide_image_order->xs) && $slide_image_order->xs ? (int) $slide_image_order->xs : 2);
$slide_content_order_xl = ($slide_image_order_xl == 2 ? 1 : 2);
$slide_content_order_lg = ($slide_image_order_lg == 2 ? 1 : 2);
$slide_content_order_md = ($slide_image_order_md == 2 ? 1 : 2);
$slide_content_order_sm = ($slide_image_order_sm == 2 ? 1 : 2);
$slide_content_order_xs = ($slide_image_order_xs == 2 ? 1 : 2);
$slide_image_text_align = '';
$slide_image_text_align .= ($slide_image_order_xl == 2 ? ' text-xl-end' : ' text-xl-start');
$slide_image_text_align .= ($slide_image_order_lg == 2 ? ' text-lg-end' : ' text-lg-start');
$slide_image_text_align .= ($slide_image_order_md == 2 ? ' text-md-end' : ' text-md-start');
$slide_image_text_align .= ($slide_image_order_sm == 2 ? ' text-sm-end' : ' text-sm-start');
$slide_image_text_align .= ($slide_image_order_xs == 2 ? ' text-end' : ' text-start');
$aligns = (isset($item_value->slide_content_align) && $item_value->slide_content_align ? $item_value->slide_content_align : '');
$alignClass = '';
if ($aligns) {
foreach ($aligns as $ak => $av) {
if ($av) {
$alignClass .= ($ak == 'xs' ? 'text-' : 'text-' . $ak . '-');
if ($av == 'left') {
$alignClass .= 'start ';
}
else if ($av == 'right') {
$alignClass .= 'end ';
}
else {
$alignClass .= 'center ';
}
}
}
}
$slide_bg_color = (isset($item_value->slide_bg_color) && $item_value->slide_bg_color ? $item_value->slide_bg_color : '');
$slide_bg_type = (isset($item_value->slide_bg_type) && $item_value->slide_bg_type ? $item_value->slide_bg_type : '');
$slide_bg_image = '';
if (is_object($item_value->slide_bg_image)) {
$slide_bg_image = (isset($item_value->slide_bg_image->{$this->lang}) && $item_value->slide_bg_image->{$this->lang} ? $item_value->slide_bg_image->{$this->lang} : array_values((array) $item_value->slide_bg_image)[0] ?? '');
}
else if (is_string($item_value->slide_bg_image)) {
$slide_bg_image = $item_value->slide_bg_image;
}
$slide_bg_color_code = '';
$hasColor = $slide_bg_color && $slide_bg_type != 'none';
if ($hasColor || $patternStyle) {
$slide_bg_color_code = 'style="';
if ($hasColor) {
$slide_bg_color_code .= 'background-color: ' . $slide_bg_color . '; ';
}
if ($patternStyle) {
$slide_bg_color_code .= $patternStyle;
}
$slide_bg_color_code .= '"';
}
$title = (isset($item_value->slide_title->{$this->lang}) && $item_value->slide_title->{$this->lang} ? $item_value->slide_title->{$this->lang} : array_values((array) $item_value->slide_title)[0] ?? '');
$title = self::getPriceHolders($title);
$title_heading_selector = (isset($item_value->slide_title_heading) && $item_value->slide_title_heading ? $item_value->slide_title_heading : 'h3');
$title_font = (isset($item_value->slide_title_font) && $item_value->slide_title_font ? self::parseFontProperties($item_value->slide_title_font, false) : '');
$title_color = (isset($item_value->slide_title_color) && $item_value->slide_title_color ? $item_value->slide_title_color : '');
$title_animation = (isset($item_value->slide_title_animation) && $item_value->slide_title_animation ? $item_value->slide_title_animation : 'none');
$subtitle = (isset($item_value->slide_subtitle->{$this->lang}) && $item_value->slide_subtitle->{$this->lang} ? $item_value->slide_subtitle->{$this->lang} : array_values((array) $item_value->slide_subtitle)[0] ?? '');
$subtitle = self::getPriceHolders($subtitle);
$subtitle_heading_selector = (isset($item_value->slide_subtitle_heading) && $item_value->slide_subtitle_heading ? $item_value->slide_subtitle_heading : 'h2');
$subtitle_font = (isset($item_value->slide_subtitle_font) && $item_value->slide_subtitle_font ? self::parseFontProperties($item_value->slide_subtitle_font, false) : '');
$subtitle_color = (isset($item_value->slide_subtitle_color) && $item_value->slide_subtitle_color ? $item_value->slide_subtitle_color : '');
$subtitle_animation = (isset($item_value->slide_subtitle_animation) && $item_value->slide_subtitle_animation ? $item_value->slide_subtitle_animation : 'none');
$content_text = (isset($item_value->slide_description->{$this->lang}) && $item_value->slide_description->{$this->lang} ? $item_value->slide_description->{$this->lang} : array_values((array) $item_value->slide_description)[0] ?? '');
$content_text = self::getPriceHolders($content_text);
$content_color = (isset($item_value->slide_description_color) && $item_value->slide_description_color ? $item_value->slide_description_color : '');
$content_animation = (isset($item_value->slide_description_animation) && $item_value->slide_description_animation ? $item_value->slide_description_animation : 'none');
$use_slide_features = (isset($item_value->use_slide_features) && $item_value->use_slide_features == 'yes' ? true : false);
$slide_features = (isset($item_value->slide_features) && $item_value->slide_features ? $item_value->slide_features : []);
$slide_features_type = (isset($item_value->slide_features_type) && $item_value->slide_features_type ? $item_value->slide_features_type : 'list');
$slide_features_icon_color = (isset($item_value->slide_features_icon_color) && $item_value->slide_features_icon_color ? $item_value->slide_features_icon_color : '');
$slide_features_title_color = (isset($item_value->slide_features_title_color) && $item_value->slide_features_title_color ? $item_value->slide_features_title_color : '');
$slide_features_desc_color = (isset($item_value->slide_features_desc_color) && $item_value->slide_features_desc_color ? $item_value->slide_features_desc_color : '');
$slide_features_animation = (isset($item_value->slide_features_animation) && $item_value->slide_features_animation ? $item_value->slide_features_animation : 'none');
$output .= '<div class="' . $uniqid . ' fon-item ' . $content_class . ' ' . ($item_key == 0 ? ' active d-flex' : '') . ' ' . ($content_vertical_center ? 'slider-content-vertically-center' : '') . ' ' . ($image_in_column ? 'image-in-column' : '') . '" ' . $slide_bg_color_code . '>';
if ($slide_bg_type == 'video') {
$videoType = '';
$videoSrc = '';
$slider_video = (isset($item_value->slider_video) && $item_value->slider_video ? $item_value->slider_video : '');
if (strpos($slider_video, 'http://') === false || strpos($slider_video, 'https://') === false) {
$slider_video = static::assetLinkDetermine($slider_video);
}
if ($slider_video && strpos($slider_video, 'http://') !== false || strpos($slider_video, 'https://') !== false && isset($item_value->use_youtube_vimeo) && $item_value->use_youtube_vimeo == 'no') {
$videoType = 'video';
$videoSrc = $slider_video;
}
else if (isset($item_value->youtube_vimeo_url) && $item_value->youtube_vimeo_url && $item_value->use_youtube_vimeo == 'yes' && strpos($item_value->youtube_vimeo_url, 'http://') !== false || strpos($item_value->youtube_vimeo_url, 'https://') !== false) {
$video = parse_url($item_value->youtube_vimeo_url);
if (strpos($video['host'], 'youtube.com') !== false || strpos($video['host'], 'youtu.be') !== false) {
$videoType = 'youtube';
$videoId = '';
switch ($video['host']) {
case 'www.youtu.be':
case 'youtu.be':
$videoId = trim($video['path'], '/');
break;
case 'www.youtube.com':
case 'youtube.com':
parse_str($video['query'], $query);
$videoId = $query['v'];
break;
}
$videoSrc = '//www.youtube-nocookie.com/embed/' . $videoId . '?enablejsapi=1&controls=0&fs=0&iv_load_policy=3&rel=0&showinfo=0&loop=1&playlist=' . $videoId . '&start=1';
}
else {
if (strpos($video['host'], 'vimeo.com') !== false) {
$videoType = 'vimeo';
$videoId = trim($video['path'], '/');
$videoSrc = '//player.vimeo.com/video/' . $videoId . '?api=1&byline=0&portrait=0&title=0&background=1&mute=1&loop=1&autoplay=0&id=' . $videoId;
}
else {
$videoType = 'unknown';
$videoSrc = $item_value->youtube_vimeo_url;
}
}
}
}
if ($slide_bg_image && $slide_bg_type == 'image') {
$slide_bg_image = static::assetLinkDetermine($slide_bg_image);
$isBgLcp = false;
if ($isFirstSlide && $isLCPCandidate && self::$lcpHandled === false) {
$this->addPreloadLink($slide_bg_image, $pageData['page']);
self::$lcpHandled = true;
$isBgLcp = true;
}
$output .= '<div class="fon-background image">';
$bg_attrs = 'src="' . $slide_bg_image . '" class="d-block w-100 h-100" style="object-fit: cover; position: absolute; top:0; left:0; z-index:0;" alt="' . $title . '"';
if ($isBgLcp) {
$bg_attrs .= ' fetchpriority="high" loading="eager" decoding="sync"';
}
else {
$bg_attrs .= ' loading="lazy" decoding="async"';
}
$output .= '<img ' . $bg_attrs . '>';
$output .= '</div>';
}
if ($slide_bg_type == 'video') {
if ($videoType == 'video') {
$output .= '<div class="fon-background video">';
$output .= '<video class="slide-video " autoplay muted loop playsinline preload="metadata">';
$output .= '<source src="' . $videoSrc . '" type="video/mp4" />';
$output .= '</video>';
$output .= '</div>';
}
else {
$output .= '<div class="fon-background ' . $videoType . '">';
$output .= '<iframe class="embed-player " width="980" height="520" src="' . $videoSrc . '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
$output .= '</div>';
}
}
if ($content_container_option === 'bootstrap') {
$output .= '<div class="container">';
if (!$image_in_column) {
$columnClass = 'col-12';
if ($aligns) {
foreach ($aligns as $ak => $av) {
if (!in_array($ak, ['xs' => true, 'sm' => true])) {
$columnClass .= (($av == 'left') || $av == 'right' ? ' col-' . $ak . '-' . ($ak == 'md' ? '7' : '6') : '');
}
}
}
$output .= '<div class="row">';
$output .= '<div class="' . $columnClass . '">';
}
}
else {
$output .= '<div class="fon-slider-content-wrap">';
}
$inner_uniqid = 'fon-slider-inner-item-' . $moduleId . '-num-' . $item_key;
if ($image_in_column) {
$output .= '<div class="row align-items-center">';
$output .= '<div class="col-' . ($image_column_width_xs === 12 ? 12 : 12 - $image_column_width_xs) . ' col-sm-' . ($image_column_width_sm === 12 ? 12 : 12 - $image_column_width_sm) . ' col-md-' . ($image_column_width_md === 12 ? 12 : 12 - $image_column_width_md) . ' col-lg-' . ($image_column_width_lg === 12 ? 12 : 12 - $image_column_width_lg) . ' col-xl-' . ($image_column_width_xl === 12 ? 12 : 12 - $image_column_width_xl) . ' order-' . $slide_content_order_xs . ' order-sm-' . $slide_content_order_sm . ' order-md-' . $slide_content_order_md . ' order-lg-' . $slide_content_order_lg . ' order-xl-' . $slide_content_order_xl . '">';
}
$output .= '<div class="fon-slider-content-align ' . $alignClass . '">';
$primarySlideButton = '';
if (is_object($item_value->slide_link)) {
$primarySlideButton = (isset($item_value->slide_link->{$this->lang}) && $item_value->slide_link->{$this->lang} ? $item_value->slide_link->{$this->lang} : array_values((array) $item_value->slide_link)[0] ?? '');
}
else if (is_string($item_value->slide_link)) {
$primarySlideButton = $item_value->slide_link;
}
if ($primarySlideButton) {
$button = ['button_text' => $item_value->button_text ?? '', 'button_link' => $item_value->slide_link ?? '', 'button_rel' => $item_value->button_rel ?? [], 'button_target' => $item_value->slide_link_target ?? '', 'button_type' => $item_value->button_type ?? 'default', 'button_style' => $item_value->button_style ?? 'default', 'button_custom_style' => $item_value->button_custom_style ?? 'default', 'button_shape' => $item_value->button_shape ?? '', 'button_size' => $item_value->button_size ?? '', 'button_padding' => $item_value->button_padding ?? '', 'button_color_normal' => $item_value->button_color_normal ?? '', 'button_color_hover' => $item_value->button_color_hover ?? '', 'button_background_normal' => $item_value->button_background_normal ?? '', 'button_background_hover' => $item_value->button_background_hover ?? '', 'button_gradient_normal' => $item_value->button_gradient_normal ?? '', 'button_gradient_hover' => $item_value->button_gradient_hover ?? '', 'show_button_icon' => $item_value->show_button_icon ?? 'no', 'button_icon' => $item_value->button_icon ?? '', 'button_icon_position' => $item_value->button_icon_position ?? '', 'scroll_button' => $item_value->scroll_button ?? 'no', 'block_button' => 'no'];
$button_animation = (isset($item_value->button_animation) && $item_value->button_animation ? $item_value->button_animation : 'none');
}
$showSecondaryButton = (isset($item_value->show_secondary_button) && $item_value->show_secondary_button == 'yes' ? true : false);
if ($showSecondaryButton) {
$secondaryButton = ['button_text' => $item_value->secondary_button_text ?? '', 'button_link' => $item_value->secondary_slide_link ?? '', 'button_rel' => $item_value->secondary_button_rel ?? [], 'button_target' => $item_value->secondary_slide_link_target ?? '', 'button_type' => $item_value->secondary_button_type ?? 'default', 'button_style' => $item_value->secondary_button_style ?? 'default', 'button_custom_style' => $item_value->secondary_button_custom_style ?? 'default', 'button_shape' => $item_value->secondary_button_shape ?? '', 'button_size' => $item_value->secondary_button_size ?? '', 'button_padding' => $item_value->secondary_button_padding ?? '', 'button_color_normal' => $item_value->secondary_button_color_normal ?? '', 'button_color_hover' => $item_value->secondary_button_color_hover ?? '', 'button_background_normal' => $item_value->secondary_button_background_normal ?? '', 'button_background_hover' => $item_value->secondary_button_background_hover ?? '', 'button_gradient_normal' => $item_value->secondary_button_gradient_normal ?? '', 'button_gradient_hover' => $item_value->secondary_button_gradient_hover ?? '', 'show_button_icon' => $item_value->secondary_show_button_icon ?? 'no', 'button_icon' => $item_value->secondary_button_icon ?? '', 'button_icon_position' => $item_value->secondary_button_icon_position ?? '', 'scroll_button' => $item_value->secondary_scroll_button ?? 'no', 'block_button' => 'no'];
$secondary_button_animation = (isset($item_value->secondary_button_animation) && $item_value->secondary_button_animation ? $item_value->secondary_button_animation : 'none');
}
$output .= '<' . $title_heading_selector . ' class="fon-slider-title ' . ($title_animation != 'none' ? 'animated' : '') . ' ' . $inner_uniqid . '-title" ' . ($title_animation != 'none' ? 'data-animation-in="' . $title_animation . '" data-delay-in="0"' : '') . '>';
$output .= $title;
$output .= '</' . $title_heading_selector . '>';
$output .= '<' . $subtitle_heading_selector . ' class="fon-slider-title fon-slider-subtitle ' . ($subtitle_animation != 'none' ? 'animated' : '') . ' ' . $inner_uniqid . '-subtitle" ' . ($subtitle_animation != 'none' ? 'data-animation-in="' . $subtitle_animation . '" data-delay-in="0.1"' : '') . '>';
$output .= $subtitle;
$output .= '</' . $subtitle_heading_selector . '>';
$output .= '<div class="fon-slider-text ' . $inner_uniqid . '-description ' . ($content_animation != 'none' ? 'animated' : '') . '" ' . ($content_animation != 'none' ? 'data-animation-in="' . $content_animation . '" data-delay-in="0.2"' : '') . '>';
$output .= $content_text;
$output .= '</div>';
if ($slide_features && $use_slide_features) {
$output .= '<div id="' . $inner_uniqid . '-features" class="fon-slider-features ' . ($slide_features_animation != 'none' ? 'animated' : '') . ' d-none d-md-block" ' . ($slide_features_animation != 'none' ? 'data-animation-in="' . $slide_features_animation . '" data-delay-in="0.3"' : '') . '>';
$output .= '<ul class="list-unstyled ' . ($slide_features_type == 'column' ? 'row align-items-start' : '') . '">';
foreach ($slide_features as $sfkey => $slide_feature) {
$slide_feature_icon = (isset($slide_feature->icon) && $slide_feature->icon ? $slide_feature->icon : '');
$slide_feature_title = (isset($slide_feature->title->{$this->lang}) && $slide_feature->title->{$this->lang} ? $slide_feature->title->{$this->lang} : array_values((array) $slide_feature->title)[0] ?? '');
$slide_feature_desc = (isset($slide_feature->desc->{$this->lang}) && $slide_feature->desc->{$this->lang} ? $slide_feature->desc->{$this->lang} : array_values((array) $slide_feature->desc)[0] ?? '');
$output .= '<li class="' . ($slide_features_type == 'column' ? 'col-md-6' : '') . '">';
$output .= '<div class="fon-slider-feature">';
if ($slide_feature_icon) {
$output .= '<div class="fon-slider-feature-icon" style="' . ($slide_features_icon_color ? 'color:' . $slide_features_icon_color : '') . '"><i class="' . $slide_feature_icon . ' fa-fw"></i></div>';
}
$output .= '<div class="fon-slider-feature-text">';
if ($slide_feature_title) {
$output .= '<h4 class="fon-slider-feature-title fw-semibold mb-1" style="' . ($slide_features_title_color ? 'color:' . $slide_features_title_color : '') . '">' . $slide_feature_title . '</h4>';
}
if ($slide_feature_desc) {
$output .= '<p class="fon-slider-feature-desc" style="' . ($slide_features_desc_color ? 'color:' . $slide_features_desc_color : '') . '">' . $slide_feature_desc . '</span>';
}
$output .= '</div>';
$output .= '</div>';
$output .= '</li>';
}
$output .= '</ul>';
$output .= '</div>';
}
if ($primarySlideButton || $showSecondaryButton) {
$output .= '<div class="fon-slide-button-container ' . ($showSecondaryButton ? 'd-flex gap-3 justify-content-center justify-content-md-start' : '') . ' ' . ($use_slide_features ? 'mt-3' : 'mt-3 mt-lg-5') . ' ' . ($button_animation != 'none' ? 'animated' : '') . '" ' . ($button_animation != 'none' ? 'data-animation-in="' . $button_animation . '" data-delay-in="0.4"' : '') . '>';
if ($primarySlideButton) {
$output .= self::parseButton((object) $button, $moduleId . '-' . $inner_uniqid, $pageData);
}
if ($showSecondaryButton) {
$output .= self::parseButton((object) $secondaryButton, $moduleId . '-' . $inner_uniqid . '-secondary', $pageData);
}
$output .= '</div>';
}
$output .= '</div>';
if ($image_in_column) {
$output .= '</div>';
$image_content = '';
if (is_object($item_value->slide_image)) {
$image_content = (isset($item_value->slide_image->{$this->lang}) && $item_value->slide_image->{$this->lang} ? $item_value->slide_image->{$this->lang} : array_values((array) $item_value->slide_image)[0] ?? '');
}
else if (is_string($item_value->slide_image)) {
$image_content = $item_value->slide_image;
}
$image_content_src = ($image_content ? static::assetLinkDetermine($image_content) : $lazyPlaceholder);
$imageDimensions = static::getImageDimensions($image_content_src, $pageData['badress']);
$isContentLcp = false;
if ($image_content && $isFirstSlide && $isLCPCandidate && self::$lcpHandled === false) {
$this->addPreloadLink($image_content, $pageData['page']);
self::$lcpHandled = true;
$isContentLcp = true;
}
$image_height = (isset($item_value->slide_image_height) && $item_value->slide_image_height ? $item_value->slide_image_height : false);
$image_animation = (isset($item_value->slide_image_animation) && $item_value->slide_image_animation ? $item_value->slide_image_animation : 'none');
$img_attrs = 'class="img-fluid fon-slider-image-entity d-inline" src="' . $image_content_src . '" alt="' . strip_tags($title) . '" ' . $imageDimensions;
if ($isFirstSlide) {
$img_attrs .= ' loading="eager" ';
if ($isContentLcp) {
$img_attrs .= ' fetchpriority="high" decoding="sync" ';
}
else {
$img_attrs .= ' fetchpriority="auto" decoding="async" ';
}
}
else {
$img_attrs .= ' loading="lazy" decoding="async" ';
}
$output .= '<div class="col-' . $image_column_width_xs . ' col-sm-' . $image_column_width_sm . ' col-md-' . $image_column_width_md . ' col-lg-' . $image_column_width_lg . ' col-xl-' . $image_column_width_xl . ' order-' . $slide_image_order_xs . ' order-sm-' . $slide_image_order_sm . ' order-md-' . $slide_image_order_md . ' order-lg-' . $slide_image_order_lg . ' order-xl-' . $slide_image_order_xl . '">';
$output .= '<div class="fon-slider-image-align">';
$output .= '<div class="fon-slider-image text-center ' . ($image_animation != 'none' ? 'animated' : '') . ' ' . $inner_uniqid . '-image" ' . ($image_animation != 'none' ? 'data-animation-in="' . $image_animation . '" data-delay-in="0.5"' : '') . '>';
$output .= '<img ' . $img_attrs . '>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
}
if ($content_container_option === 'bootstrap') {
if (!$image_in_column) {
$output .= '</div>';
$output .= '</div>';
}
$output .= '</div>';
}
else {
$output .= '</div>';
}
if (isset($item_value->slider_overlay_type) && $item_value->slider_overlay_type == 'color') {
if (isset($item_value->slider_color_overlay) && $item_value->slider_color_overlay) {
$style .= '.fon-item.' . $uniqid . ' .fon-background:after{';
$style .= 'background-color:' . $item_value->slider_color_overlay . ';';
$style .= '}';
}
}
if (isset($item_value->slider_overlay_type) && $item_value->slider_overlay_type == 'gradient') {
if (isset($item_value->slider_gradient_overlay) && $item_value->slider_gradient_overlay) {
$item_value->slider_gradient_overlay = self::parseGradient($item_value->slider_gradient_overlay);
$style .= '.fon-item.' . $uniqid . ' .fon-background:after{';
$style .= $item_value->slider_gradient_overlay;
$style .= '}';
}
}
if ($title_font || $title_color) {
$style .= '.' . $inner_uniqid . '-title{';
if ($title_font) {
$style .= $title_font;
}
if ($title_color) {
$style .= 'color: ' . $title_color . ';';
}
$style .= '}';
}
if ($subtitle_font || $subtitle_color) {
$style .= '.' . $inner_uniqid . '-subtitle{';
if ($subtitle_font) {
$style .= $subtitle_font;
}
if ($subtitle_color) {
$style .= 'color: ' . $subtitle_color . ';';
}
$style .= '}';
}
if ($content_color) {
$style .= '.fon-slider .fon-slider-text.' . $inner_uniqid . '-description{';
$style .= 'color: ' . $content_color . ';';
$style .= '}';
}
if ($image_in_column && $image_content) {
if (isset($image_height) && $image_height) {
$responsiveItems = [
'.' . $inner_uniqid . '-image img' => [
['type' => 'max-height', 'unit' => 'px', 'value' => $image_height]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
}
else {
$style .= '.' . $inner_uniqid . '-image img{';
$style .= 'max-height: 90%;';
$style .= '}';
}
}
$output .= '</div>';
}
}
$output .= '</div>';
if ($content_container_option !== 'bootstrap') {
$style .= '#' . $widgetId . '.fon-slider .fon-slider-content-wrap{';
$style .= 'margin: 0 auto;';
$style .= 'width: ' . $content->content_custom_width . '%;';
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
return $output;
}
private function sms_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetProducts($content, $moduleId, $pageData, $row, 'sms');
}
private function software_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetPages($content, $moduleId, $pageData, 'software');
}
private function social_share_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$social_networks = [
'facebook' => [
'url' => 'https://www.facebook.com/sharer.php?u={url}',
'icon' => 'fa-brands fa-facebook-f',
'label' => 'Facebook',
'popup' => ['width' => 600, 'height' => 300],
'color' => ['normal' => '#306199', 'hover' => '#244872']
],
'twitter' => [
'url' => 'https://twitter.com/share?url={url}&text={title}',
'icon' => 'fa-brands fa-x-twitter',
'label' => 'X (Twitter)',
'popup' => ['width' => 600, 'height' => 300],
'color' => ['normal' => '#000000c7', 'hover' => '#000']
],
'linkedin' => [
'url' => 'https://www.linkedin.com/shareArticle?mini=true&url={url}',
'icon' => 'fa-brands fa-linkedin',
'label' => 'LinkedIn',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#007bb6', 'hover' => '#005983']
],
'pinterest' => [
'url' => 'https://pinterest.com/pin/create/button/?url={url}&description={title}',
'icon' => 'fa-brands fa-pinterest',
'label' => 'Pinterest',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#b81621', 'hover' => '#8a1119']
],
'tumblr' => [
'url' => 'https://tumblr.com/share?s=&v=3&t={title}&u={url}',
'icon' => 'fa-brands fa-tumblr',
'label' => 'Tumblr',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#32506d', 'hover' => '#22364a']
],
'getpocket' => [
'url' => 'https://getpocket.com/save?url={url}',
'icon' => 'fa-brands fa-get-pocket',
'label' => 'Pocket',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#ed4054', 'hover' => '#e4162d']
],
'reddit' => [
'url' => 'https://www.reddit.com/submit?url={url}',
'icon' => 'fa-brands fa-reddit',
'label' => 'Reddit',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#ff4500', 'hover' => '#e83f00']
],
'vk' => [
'url' => 'https://vk.com/share.php?url={url}',
'icon' => 'fa-brands fa-vk',
'label' => 'VK',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#597ba5', 'hover' => '#3d5f88']
],
'xing' => [
'url' => 'https://www.xing.com/spi/shares/new?cb=0&url={url}',
'icon' => 'fa-brands fa-xing',
'label' => 'Xing',
'popup' => ['width' => 585, 'height' => 666],
'color' => ['normal' => '#005658', 'hover' => '#004748']
],
'whatsapp' => [
'url' => 'https://api.whatsapp.com/send?text={url}',
'icon' => 'fa-brands fa-whatsapp',
'label' => 'WhatsApp',
'popup' => false,
'color' => ['normal' => '#00d66e', 'hover' => '#00b55d']
],
'telegram' => [
'url' => 'https://t.me/share/url?url={url}&text={title}',
'icon' => 'fa-brands fa-telegram',
'label' => 'Telegram',
'popup' => false,
'color' => ['normal' => '#54a9eb', 'hover' => '#4998d5']
],
'bluesky' => [
'url' => 'https://bsky.app/intent/compose?text={url}',
'icon' => 'fa-brands fa-bluesky',
'label' => 'Bluesky',
'popup' => false,
'color' => ['normal' => '#0285ff', 'hover' => '#2566a4']
],
'email' => [
'url' => 'mailto:?subject={title}&body={url}',
'icon' => 'fa-solid fa-envelope',
'label' => 'E-Mail',
'popup' => false,
'color' => ['normal' => '#7d7d7d', 'hover' => '#4d4d4d']
]
];
$widgetId = 'fon-widget-' . $moduleId;
$social_media = (isset($content->social_media) && $content->social_media ? $content->social_media : []);
$widget_style = (isset($content->widget_style) && $content->widget_style ? $content->widget_style : 'button');
$dropdown_title = (isset($content->dropdown_title) && isset($content->dropdown_title->{$this->lang}) && $content->dropdown_title->{$this->lang} ? $content->dropdown_title->{$this->lang} : (isset($content->dropdown_title) ? array_values((array) $content->dropdown_title)[0] ?? '' : ''));
$show_label = (isset($content->show_label) && $content->show_label == 'yes' ? true : false);
$color_scheme = (isset($content->color_scheme) && $content->color_scheme ? $content->color_scheme : 'default');
$text_color_normal = (isset($content->text_color) && isset($content->text_color->normal) && $content->text_color->normal ? $content->text_color->normal : '#000000');
$text_color_hover = (isset($content->text_color) && isset($content->text_color->hover) && $content->text_color->hover ? $content->text_color->hover : '#ffffff');
$background_color_normal = (isset($content->background_color) && isset($content->background_color->normal) && $content->background_color->normal ? $content->background_color->normal : '#f9f9f9');
$background_color_hover = (isset($content->background_color) && isset($content->background_color->hover) && $content->background_color->hover ? $content->background_color->hover : '#000000');
$border_radius = (isset($content->border_radius) && $content->border_radius ? $content->border_radius : 0);
$fon_class = (isset($content->fon_class) && $content->fon_class ? $content->fon_class : '');
$align = (isset($content->align) && $content->align ? $content->align : 'center');
switch ($align) {
case 'left':
$align = 'start';
break;
case 'right':
$align = 'end';
break;
case 'center':
$align = 'center';
break;
}
$style = '';
if ($widget_style != 'dropdown') {
$style .= '#' . $widgetId . ' .fon-social-share-list > li > a{';
if ($widget_style == 'button') {
$style .= 'color:#fff;';
if ($show_label) {
$style .= 'padding: .375rem .75rem;';
}
else {
$style .= 'padding: .75rem;';
}
$style .= 'font-size: .875rem;';
if ($color_scheme == 'default') {
$style .= '--normal-color:var(--fon-link-color);';
$style .= '--hover-color:var(--fon-hover-color);';
}
else if ($color_scheme == 'primary') {
$style .= '--normal-color:var(--theme-primary);';
$style .= '--hover-color:var(--theme-secondary);';
}
else if ($color_scheme == 'secondary') {
$style .= '--normal-color:var(--theme-secondary);';
$style .= '--hover-color:var(--theme-primary);';
}
else if ($color_scheme == 'custom') {
$style .= '--normal-color:' . $background_color_normal . ';';
$style .= '--hover-color:' . $background_color_hover . ';';
$style .= 'color:' . $text_color_normal . ';';
}
$style .= 'background-color:var(--normal-color);';
}
else if ($widget_style == 'list') {
$style .= 'color:var(--fon-link-color);';
}
$style .= 'cursor:pointer;';
$style .= 'border-radius: ' . $border_radius . 'px;';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-social-share-list > li > a:hover{';
if ($widget_style == 'button') {
$style .= 'background-color:var(--hover-color);';
if ($color_scheme == 'custom') {
$style .= 'color:' . $text_color_hover . ';';
}
}
else if ($widget_style == 'list') {
$style .= 'color:var(--fon-hover-color);';
}
$style .= '}';
}
else {
if (!$show_label) {
$style .= '#' . $widgetId . ' .dropdown-menu{';
$style .= 'text-align: center;';
$style .= 'min-width: 56px;';
$style .= '--bs-dropdown-item-padding-x: 0.5rem;';
$style .= '}';
}
$style .= '#' . $widgetId . ' .fon-social-share-list > li > a{';
$style .= 'cursor:pointer;';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-social-share-list > li > a > i{';
$style .= 'color:var(--fon-link-color);';
$style .= '}';
$style .= '#' . $widgetId . ' .fon-social-share-list > li > a:hover > i{';
$style .= 'color:var(--fon-hover-color);';
$style .= '}';
if ($color_scheme == 'default') {
$dropdownBtnClass = 'btn-outline-dark';
}
else if ($color_scheme == 'primary') {
$dropdownBtnClass = 'btn-default';
}
else if ($color_scheme == 'secondary') {
$dropdownBtnClass = 'btn-secondary';
}
else if ($color_scheme == 'custom') {
$dropdownBtnClass = 'btn-custom';
$style .= '#' . $widgetId . ' .btn-custom.dropdown-toggle{';
$style .= 'color:' . $text_color_normal . ';';
$style .= 'background-color:' . $background_color_normal . ';';
$style .= 'border-color:' . $background_color_normal . ';';
$style .= '}';
$style .= '#' . $widgetId . ' .btn-custom.dropdown-toggle:hover{';
$style .= 'color:' . $text_color_hover . ';';
$style .= 'background-color:' . $background_color_hover . ';';
$style .= 'border-color:' . $background_color_hover . ';';
$style .= '}';
}
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-social-share-widget ' . $fon_class . '">';
$output .= '<script>var socialSharePageTitle=encodeURIComponent(document.title); var socialSharepageLink = encodeURIComponent(window.location.href);</script>';
$output .= '<div class="fon-widget-content ' . ($widget_style == 'dropdown' ? 'text-' . $align : '') . '">';
if ($widget_style == 'dropdown') {
$output .= '<div class="btn-group position-relative">';
$output .= '<button class="btn ' . $dropdownBtnClass . ' dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa-solid fa-share-nodes"></i>' . ($show_label ? ' ' . $dropdown_title : '') . '</button>';
}
$output .= '<ul class="fon-social-share-list ' . ($widget_style != 'dropdown' ? 'list-unstyled d-flex flex-wrap align-item-center justify-content-' . $align . ' gap-3' : 'dropdown-menu dropdown-menu-' . $align) . '">';
foreach ($social_media as $network_key) {
if (isset($social_networks[$network_key])) {
$network = $social_networks[$network_key];
$link_action = '';
if ($network_key == 'email') {
$url_template = str_replace(['{title}', '{url}'], ['\' + socialSharePageTitle + \'', '\' + socialSharepageLink + \''], $network['url']);
$link_action = 'onClick="window.location.href = \'' . $url_template . '\'; return false"';
}
else if (isset($network['popup']) && $network['popup']) {
$url_template = str_replace(['{title}', '{url}'], ['\' + socialSharePageTitle + \'', '\' + socialSharepageLink + \''], $network['url']);
$w = $network['popup']['width'];
$h = $network['popup']['height'];
$link_action = 'onClick="window.open(\'' . $url_template . '\', \'' . $network['label'] . '\', \'width=' . $w . ',height=' . $h . ',left=\'+(screen.availWidth/2-' . ($w / 2) . ')+\',top=\'+(screen.availHeight/2-' . ($h / 2) . ')+\'\'); return false;"';
}
else {
$url_template = str_replace(['{title}', '{url}'], ['\' + socialSharePageTitle + \'', '\' + socialSharepageLink + \''], $network['url']);
$link_action = 'onClick="window.open(\'' . $url_template . '\'); return false;"';
}
$output .= '<li class="fon-social-share-' . htmlspecialchars($network_key) . '">';
$output .= '<a ' . $link_action . ' style="--fon-link-color:' . $social_networks[$network_key]['color']['normal'] . ';--fon-hover-color:' . $social_networks[$network_key]['color']['hover'] . ';--fon-active-color:' . $social_networks[$network_key]['color']['hover'] . ';" ' . ($widget_style == 'dropdown' ? 'class="dropdown-item"' : '') . '>';
$output .= '<i class="' . htmlspecialchars($network['icon']) . ' fa-fw" aria-hidden="true" title="' . htmlspecialchars($network['label']) . '"></i>';
if ($show_label) {
$output .= '<span class="fon-social-share-title ms-1">' . htmlspecialchars($network['label']) . '</span>';
}
$output .= '</a>';
$output .= '</li>';
}
}
$output .= '</ul>';
if ($widget_style == 'dropdown') {
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function special_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
return $this->getWidgetProducts($content, $moduleId, $pageData, $row, 'special');
}
private function tabs_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$align = '';
if (isset($content->direction) && $content->direction == 'horizontal') {
if (isset($content->align) && $content->align == 'right') {
$align = 'justify-content-end';
}
else if (isset($content->align) && $content->align == 'center') {
$align = 'justify-content-center';
}
else if (isset($content->align) && $content->align == 'justify') {
$align = 'nav-justified';
}
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-tabs-widget ' . ($content->dark_container == 'yes' ? 'dark-container' : '') . ' ' . $content->direction . ' style-' . $content->widget_style . ' ' . $content->fon_class . '">';
if (isset($content->items) && is_array($content->items)) {
$output .= '<ul class="nav nav-tabs widget-tabs ' . $align . '">';
foreach ($content->items as $tbkey => $tbitem) {
$title = (isset($tbitem->tab_title->{$this->lang}) && $tbitem->tab_title->{$this->lang} ? $tbitem->tab_title->{$this->lang} : array_values((array) $tbitem->tab_title)[0] ?? '');
$subtitle = (isset($tbitem->tab_subtitle->{$this->lang}) && $tbitem->tab_subtitle->{$this->lang} ? $tbitem->tab_subtitle->{$this->lang} : array_values((array) $tbitem->tab_subtitle)[0] ?? '');
if ($title) {
$output .= '<li class="nav-item">';
$output .= '<a class="nav-link widget-nav-link ' . ($tbkey == 0 ? 'active' : '') . '" data-bs-toggle="tab" href="#' . $moduleId . '-tab-' . $tbkey . '">';
if (isset($content->show_icon) && $content->show_icon == 'yes') {
$output .= '<i class="' . $tbitem->tab_icon . ' fa-fw ' . (isset($content->show_subtitle) && $content->show_subtitle == 'yes' && $subtitle ? 'subtitle' : '') . '"></i>';
}
$output .= '<span class="tab-titles">';
$output .= "\t" . '<span class="tab-title">' . $title . '</span>';
if (isset($content->show_subtitle) && $content->show_subtitle == 'yes' && $subtitle) {
$output .= '<span class="tab-subtitle">' . $subtitle . '</span>';
}
$output .= '</span>';
$output .= '</a>';
$output .= '</li>';
}
}
$output .= '</ul>';
$output .= '<div class="tab-content">';
foreach ($content->items as $tckey => $tcitem) {
$tabContent = (isset($tcitem->tab_content->{$this->lang}) && $tcitem->tab_content->{$this->lang} ? $tcitem->tab_content->{$this->lang} : array_values((array) $tcitem->tab_content)[0] ?? '');
$output .= '<div id="' . $moduleId . '-tab-' . $tckey . '" class="tab-pane fade ' . ($tckey == 0 ? 'active show' : '') . '">';
if ($tabContent) {
$output .= $tabContent;
}
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
private function team_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$style = '';
if (isset($content->image_overlay_type)) {
$style .= '#' . $widgetId . ' .team{';
if ($content->image_overlay_type == 'color') {
$style .= '--bs-bg-overlay-color: ' . $content->image_color_overlay . ';';
}
else {
$style .= self::parseGradient($content->image_gradient_overlay, 'bg-overlay');
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$carouselData = '';
$columns = [];
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" data-row="' . $content->use_row . '" data-rows="' . htmlspecialchars(Utility::jencode($content->row, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel team-carousel';
}
else {
$columns = $content->column;
$containerClass = (1 < count($content->items) ? 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl : '');
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-team-widget overlay-' . $content->image_overlay_type . ' style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content ' . $containerClass . '" ' . $carouselData . '>';
if (isset($content->items) && is_array($content->items)) {
foreach ($content->items as $item) {
if ($item->team_image) {
$item->team_image = static::assetLinkDetermine($item->team_image);
}
else {
$item->team_image = $lazyPlaceholder;
}
$imageDimensions = static::getImageDimensions($item->team_image, $pageData['badress']);
if (!$isCarousel) {
$output .= '<div class="col">';
}
if (self::isJSON($item->team_socials)) {
$item->team_socials = Utility::jdecode($item->team_socials);
}
$team_position = (isset($item->team_position->{$this->lang}) && $item->team_position->{$this->lang} ? $item->team_position->{$this->lang} : array_values((array) $item->team_position)[0] ?? '');
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'team' . DS . 'style_' . $content->widget_style . '.php';
if (!$isCarousel) {
$output .= '</div>';
}
}
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function testimonial_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$source = (isset($content->source) && $content->source ? $content->source : 'manuel');
$show_form = (isset($content->show_form) && $content->show_form == 'yes' ? true : false);
$form_style = (isset($content->form_style) && $content->form_style ? $content->form_style : 'modal');
$form_title = (isset($content->form_title) && isset($content->form_title->{$this->lang}) && $content->form_title->{$this->lang} ? $content->form_title->{$this->lang} : (isset($content->form_title) ? array_values((array) $content->form_title)[0] ?? '' : ''));
$form_desc = (isset($content->form_desc) && isset($content->form_desc->{$this->lang}) && $content->form_desc->{$this->lang} ? $content->form_desc->{$this->lang} : (isset($content->form_desc) ? array_values((array) $content->form_desc)[0] ?? '' : ''));
$form_button = (isset($content->form_button) && isset($content->form_button->{$this->lang}) && $content->form_button->{$this->lang} ? $content->form_button->{$this->lang} : (isset($content->form_button) ? array_values((array) $content->form_button)[0] ?? '' : ''));
$form_position = (isset($content->form_position) && $content->form_position ? $content->form_position : 'after');
$limit = (isset($content->limit) && $content->limit ? $content->limit : 8);
$feedbackConfig = ___('blocks/customer-feedback');
$form_action = Controllers::$init->CRLink('cfeedback-send');
if ($source == 'wisecp') {
$contentItems = self::getTestimonials($limit);
$content->items = [];
if ($contentItems) {
foreach ($contentItems as $contentItem) {
$tci = new stdClass();
$tci->testimonial_author = $contentItem['full_name'];
$tci->testimonial_avatar = ($contentItem['image'] ? 'resources/uploads/customer-feedback/' . $contentItem['image'] : '');
$tci->testimonial_position = new stdClass();
$tci->testimonial_position->{$this->lang} = $contentItem['company_name'];
$tci->testimonial_message = new stdClass();
$tci->testimonial_message->{$this->lang} = $contentItem['message'];
$tci->testimonial_star = 5;
$tci->testimonial_star_style = 'google';
$content->items[] = $tci;
}
}
}
$carouselData = '';
$columns = [];
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" data-row="' . $content->use_row . '" data-rows="' . htmlspecialchars(Utility::jencode($content->row, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
$containerClass = 'fon-content-carousel testimonial-carousel';
}
else {
$columns = $content->column;
$containerClass = (1 < count($content->items) ? 'row g-4 row-cols-' . $columns->xs . ' row-cols-sm-' . $columns->sm . ' row-cols-md-' . $columns->md . ' row-cols-lg-' . $columns->lg . ' row-cols-xl-' . $columns->xl : '');
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-testimonial-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
if (($source == 'wisecp') && $show_form && $form_style != 'inline' && $form_position == 'before') {
$output .= '<p class="text-center"><button class="btn btn-default" type="button" data-bs-toggle="' . $form_style . '" data-bs-target="#' . $widgetId . '-feedback-form" ' . ($form_style == 'collapse' ? 'aria-expanded="false" aria-controls="collapseExample"' : '') . '><i class="fa-solid fa-comment"></i> ' . $form_button . '</button></p>';
}
$output .= '<div class="fon-widget-content ' . $containerClass . '" ' . $carouselData . '>';
if (isset($content->items) && is_array($content->items)) {
$even = true;
foreach ($content->items as $item) {
$testimonial_position = (isset($item->testimonial_position->{$this->lang}) && $item->testimonial_position->{$this->lang} ? $item->testimonial_position->{$this->lang} : array_values((array) $item->testimonial_position)[0] ?? '');
$testimonial_message = (isset($item->testimonial_message->{$this->lang}) && $item->testimonial_message->{$this->lang} ? $item->testimonial_message->{$this->lang} : array_values((array) $item->testimonial_message)[0] ?? '');
if ($content->display_avatar == 'yes') {
if ($item->testimonial_avatar) {
$item->testimonial_avatar = static::assetLinkDetermine($item->testimonial_avatar);
}
else {
$item->testimonial_avatar = $lazyPlaceholder;
}
$imageDimensions = static::getImageDimensions($item->testimonial_avatar, $pageData['badress']);
}
if (!$isCarousel) {
$output .= '<div class="col">';
}
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'testimonial' . DS . 'style_' . $content->widget_style . '.php';
if (!$isCarousel) {
$output .= '</div>';
}
$even = !$even;
}
}
$output .= '</div>';
if (($source == 'wisecp') && $show_form && $form_style != 'inline' && $form_position == 'after') {
$output .= '<p class="text-center"><button class="btn btn-default" type="button" data-bs-toggle="' . $form_style . '" data-bs-target="#' . $widgetId . '-feedback-form" ' . ($form_style == 'collapse' ? 'aria-expanded="false" aria-controls="collapseExample"' : '') . '><i class="fa-solid fa-comment"></i> ' . $form_button . '</button></p>';
}
$output .= '</div>';
if (($source == 'wisecp') && $show_form) {
$captcha_status = (Config::get('options/captcha/status') == 1) && Config::get('options/captcha/customer-feedback') == 1;
if (!$captcha_status && Config::get('options/BotShield/status')) {
if (!class_exists('BotShield')) {
Helper::Load('BotShield');
}
$captcha_status = BotShield::is_blocked('customer-feedback');
}
if ($captcha_status) {
if (!class_exists('Captcha')) {
Helper::Load('Captcha');
}
$feedbackCaptcha = Helper::get('Captcha');
}
$output .= '<div id="' . $widgetId . '-feedback-form" class="' . $form_style . '" ' . ($form_style == 'modal' ? 'tabindex="-1" aria-labelledby="' . $widgetId . 'ModalLabel" aria-hidden="true"' : '') . '>';
if ($form_style == 'modal') {
$output .= '<div class="modal-dialog modal-dialog-centered">';
$output .= '<div class="modal-content">';
$output .= '<div class="modal-header">';
$output .= '<h3 class="modal-title fs-5" id="' . $widgetId . 'ModalLabel">' . $form_title . '</h3>';
$output .= '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>';
$output .= '</div>';
}
$output .= '<div class="modal-body ' . ($form_style != 'modal' ? 'rounded-4 bg-theme-light p-3 p-lg-4' : '') . '">';
if (($form_style != 'modal') && $form_title) {
$output .= '<h3 class="text-center my-3">' . $form_title . '</h3>';
}
if ($form_desc) {
$output .= '<p class="text-center">' . $form_desc . '</p>';
}
$output .= '<form action="' . $form_action . '" method="POST" id="' . $widgetId . 'FeedbackForm" enctype="multipart/form-data" class="cFeedBackForm">';
$output .= Validation::get_csrf_token('cfeedback');
$output .= '<div class="row g-3 mb-3">';
$output .= '<div class="col-12 col-lg-' . ($form_style == 'modal' ? '6' : '4') . '">';
$output .= '<input type="text" class="form-control" name="full_name" placeholder="' . __('website/cfeedback/form-fullname') . '" aria-label="' . __('website/cfeedback/form-fullname') . '" id="' . $widgetId . '-full-name">';
$output .= '</div>';
$output .= '<div class="col-12 col-lg-' . ($form_style == 'modal' ? '6' : '4') . '">';
$output .= '<input type="text" class="form-control" name="company_name" placeholder="' . __('website/cfeedback/form-company_name') . '" aria-label="' . __('website/cfeedback/form-company_name') . '" id="' . $widgetId . '-company-name">';
$output .= '</div>';
$output .= '<div class="col-12 col-lg-' . ($form_style == 'modal' ? '12' : '4') . '">';
$output .= '<input type="text" class="form-control" name="email" placeholder="' . __('website/cfeedback/form-email') . '" aria-label="' . __('website/cfeedback/form-email') . '" id="' . $widgetId . '-email">';
$output .= '</div>';
$output .= '</div>';
$output .= '<div class="mb-3">';
$output .= '<textarea class="form-contol w-100" rows="5" style="resize: none;" maxlength="425" name="message" placeholder="' . __('website/cfeedback/form-message') . '" id="' . $widgetId . '-message"></textarea>';
$output .= '</div>';
$output .= '<div class="mb-3">';
$output .= '<label for="' . $widgetId . '-file" class="form-label">' . __('website/cfeedback/form-image') . '</label>';
$output .= '<input class="form-control" type="file" name="image" id="' . $widgetId . '-file" accept=".jpg,.jpeg,.png">';
$output .= '</div>';
if (isset($feedbackCaptcha) && $feedbackCaptcha) {
$output .= '<div class="input-group mb-3">';
$output .= '<span class="input-group-text p-0 bg-white">' . $feedbackCaptcha->getOutput() . '</span>';
if ($feedbackCaptcha->input) {
$output .= '<input id="requiredinput" name="' . $feedbackCaptcha->input_name . '" type="text" class="form-control form-control-lg" aria-label="' . ___('needs/form-captcha-label') . '" placeholder="' . ___('needs/form-captcha-label') . '">';
}
$output .= '</div>';
}
$output .= '<p class="text-end">';
$output .= '<a class="btn btn-success" id="' . $widgetId . 'FeedbackForm_submit" href="javascript:void(0);"><i class="fa-solid fa-paper-plane"></i> ' . $form_button . '</a>';
$output .= '</p>';
$output .= '<div id="' . $widgetId . 'FeedbackForm_output" class="text-danger fw-bold" style="display:none"></div>';
$output .= '</form>';
$output .= '<div id="' . $widgetId . 'FeeadbackForm_Successful" style="display: none">';
$output .= '<div class="text-center my-5">';
$output .= '<i class="fa-solid fa-check-circle fa-5x mb-3 text-success"></i>';
$output .= '<h4 class="text-success fw-bold">' . __('website/cfeedback/successful-text1') . '</h4>';
$output .= '<h5>' . __('website/cfeedback/successful-text2') . '</h5>';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
if ($form_style == 'modal') {
$output .= '</div>';
$output .= '</div>';
}
$output .= '</div>';
$output .= '<script type="text/javascript">' . "\n" . ' $(document).ready(function(){' . "\n" . ' $("#' . $widgetId . 'FeedbackForm_submit").on("click",function(){' . "\n" . ' MioAjaxElement($(this),{' . "\n" . ' waiting_text: \'' . __('website/others/button1-pending') . '\',' . "\n" . ' progress_text: \'' . __('website/others/button1-upload') . '\',' . "\n" . ' result:"' . $moduleId . 'feedback_result",' . "\n" . ' });' . "\n" . ' });' . "\n" . ' $("#' . $widgetId . '-feedback-form").on("shown.bs.collapse", function () {' . "\n" . ' this.scrollIntoView({ behavior: "smooth", block: "start" });' . "\n" . ' });' . "\n" . ' });' . "\n" . ' function ' . $moduleId . 'feedback_result(result) {';
if (isset($feedbackCaptcha)) {
$output .= $feedbackCaptcha->submit_after_js();
}
$output .= 'if(result != ""){' . "\n" . ' var solve = getJson(result);' . "\n" . ' if(solve !== false){' . "\n" . ' if(solve.status == "error"){' . "\n" . ' if(solve.for != undefined && solve.for != ""){' . "\n" . ' $("#' . $widgetId . 'FeedbackForm "+solve.for).focus();' . "\n" . ' $("#' . $widgetId . 'FeedbackForm "+solve.for).addClass("is-invalid");' . "\n" . ' $("#' . $widgetId . 'FeedbackForm "+solve.for).change(function(){' . "\n" . ' $(this).removeClass("is-invalid");' . "\n" . ' });' . "\n" . ' }' . "\n" . ' ' . "\n" . ' if(solve.message != undefined && solve.message != ""){' . "\n" . ' $("#' . $widgetId . 'FeedbackForm_output").fadeIn(500).html(solve.message);' . "\n" . ' }else{' . "\n" . ' $("#' . $widgetId . 'FeedbackForm_output").fadeOut(500).html("");' . "\n" . ' }' . "\n" . ' }else if(solve.status == "successful"){' . "\n" . ' $("#' . $widgetId . 'FeedbackForm_output").fadeOut(500).html("");' . "\n" . ' $("#' . $widgetId . 'FeedbackForm").slideUp(200,function(){' . "\n" . ' $("#' . $widgetId . 'FeeadbackForm_Successful").slideDown(200);' . "\n" . ' });' . "\n" . ' }' . "\n" . ' }else{' . "\n" . ' console.log(result);' . "\n" . ' }' . "\n" . ' }' . "\n" . ' }' . "\n" . ' </script>';
}
return $output;
}
private function text_html_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$name_widget = (isset($content->name_widget) && isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : (isset($content->name_widget) ? array_values((array) $content->name_widget)[0] ?? '' : ''));
$content_text = (isset($content->content) && isset($content->content->{$this->lang}) && $content->content->{$this->lang} ? $content->content->{$this->lang} : (isset($content->content) ? array_values((array) $content->content)[0] ?? '' : ''));
$show_name = (isset($content->show_name) && $content->show_name == 'yes' ? true : false);
$heading_selector = (isset($content->heading_selector) && $content->heading_selector ? $content->heading_selector : 'h3');
$title_color = (isset($content->title_color) && $content->title_color ? $content->title_color : '');
$title_font = (isset($content->title_font) && $content->title_font ? $content->title_font : []);
$title_margin = (isset($content->title_margin) && $content->title_margin ? $content->title_margin : (object) ['xl' => '', 'lg' => '', 'md' => '', 'sm' => '', 'xs' => '']);
$column_count = (isset($content->column_count) && $content->column_count ? $content->column_count : []);
$column_gap = (isset($content->column_gap) && $content->column_gap ? $content->column_gap : []);
$content_truncation = (isset($content->content_truncation) && $content->content_truncation == 'yes' ? true : false);
$truncation_max_word = (isset($content->truncation_max_word) && $content->truncation_max_word ? $content->truncation_max_word : 50);
$truncation_action_color = (isset($content->truncation_action_color) && $content->truncation_action_color ? $content->truncation_action_color : '#0000ff');
$truncation_action_font = (isset($content->truncation_action_font) && $content->truncation_action_font ? $content->truncation_action_font : []);
$truncation_action_text = (isset($content->truncation_action_text) && isset($content->truncation_action_text->{$this->lang}) && $content->truncation_action_text->{$this->lang} ? $content->truncation_action_text->{$this->lang} : (isset($content->truncation_action_text) ? array_values((array) $content->truncation_action_text)[0] ?? '' : ''));
$dropcap = (isset($content->dropcap) && $content->dropcap == 'yes' ? true : false);
$dropcap_color = (isset($content->dropcap_color) && $content->dropcap_color ? $content->dropcap_color : '');
$dropcap_size = (isset($content->dropcap_size) && $content->dropcap_size ? $content->dropcap_size : []);
$widget_content_classes = '';
if ($column_count) {
$widget_content_classes .= ' fon-widget-content-column';
}
if ($dropcap) {
$widget_content_classes .= ' fon-widget-content-drop-cap';
}
$style = '';
if ($show_name && $name_widget) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
if ($title_color) {
$style .= 'color: ' . $title_color . ';';
}
if ($title_font) {
$style .= self::parseFontProperties($title_font);
}
$style .= '}';
}
if ($title_margin) {
$titleMarginResponsiveItems = [
'.fon-widget-title' => [
['type' => 'margin-bottom', 'unit' => 'px', 'value' => $title_margin]
]
];
$style .= self::parseResponsiveItems($titleMarginResponsiveItems, $widgetId);
}
if ($column_count || $column_gap || $dropcap) {
if ($column_count || $column_gap) {
$widget_content_classes .= ' fon-widget-content-column';
$columnResponsiveItems = [
'.fon-widget-content-column' => [
['type' => 'column-count', 'unit' => false, 'value' => $column_count],
['type' => 'column-gap', 'unit' => 'px', 'value' => $column_gap]
]
];
$style .= self::parseResponsiveItems($columnResponsiveItems, $widgetId);
}
if ($dropcap) {
$widget_content_classes .= ' fon-widget-content-drop-cap';
$style .= '#' . $widgetId . ' .fon-widget-content-drop-cap:first-letter,#' . $widgetId . ' .fon-widget-content-drop-cap>*:first-child:first-letter{';
$style .= 'color: ' . $dropcap_color . ';';
$style .= '}';
$dropcapResponsiveItems = [
'.fon-widget-content-drop-cap:first-letter,.fon-widget-content-drop-cap>*:first-child:first-letter' => [
['type' => 'font-size', 'unit' => 'px', 'value' => $dropcap_size]
]
];
$style .= self::parseResponsiveItems($dropcapResponsiveItems, $widgetId);
}
}
if ($content_truncation) {
$style .= '#' . $widgetId . ' .fon-widget-content-truncation-show{';
$style .= 'color: ' . $truncation_action_color . ';';
if ($truncation_action_font) {
$style .= self::parseFontProperties($truncation_action_font);
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-text-html-widget ' . $content->fon_class . '">';
if ($show_name && $name_widget) {
$output .= '<' . $heading_selector . ' class="fon-widget-title">';
$output .= self::getPriceHolders($name_widget);
$output .= '</' . $heading_selector . '>';
}
$content_text = self::getPriceHolders($content_text);
$plain_text = html_entity_decode($content_text, ENT_QUOTES | ENT_HTML5);
$plain_text = strip_tags($plain_text);
if (trim(str_replace([' ', ' '], '', $plain_text)) === '') {
$content_text = '';
}
if ($content_text) {
$output .= '<div class="fon-widget-content' . $widget_content_classes . '">';
$text_block_text = $content_text;
if ($content_truncation && !empty($truncation_max_word) && (int) $truncation_max_word < (int) self::wordCount($plain_text)) {
$arrayString = explode(' ', $content_text);
$text_block_text = implode(' ', array_slice($arrayString, 0, (int) $truncation_max_word));
$text_block_text .= '<template class="fon-widget-content-full-text">' . $content_text . '</template>';
$text_block_text .= '<div class="fon-widget-content-btn-container fon-widget-content-truncation-show"><div role="button" class="fon-widget-content-btn-show-more"><i class="fa-solid fa-plus"></i> ' . $truncation_action_text . '</div></div>';
}
$output .= $text_block_text;
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
private function timeline_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
if (in_array($content->widget_style, ['5'])) {
$this->addAsset('slick');
}
$mediaType = (isset($content->media_type) && $content->media_type ? $content->media_type : 'icon');
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-timeline-widget style-' . $content->widget_style . ' ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content ' . (in_array($content->widget_style, ['default', '1']) ? 'row' : '') . ' py-4">';
if (isset($content->items) && is_array($content->items)) {
include __DIR__ . DS . 'builder' . DS . 'widget-styles' . DS . 'timeline' . DS . 'style_' . $content->widget_style . '.php';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function vector_map_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$map_type = (isset($content->map_type) && $content->map_type ? $content->map_type : 'world');
$show_zooms = (isset($content->show_zooms) && $content->show_zooms == 'yes' ? 'true' : 'false');
$region_fill = (isset($content->region_fill) && $content->region_fill ? $content->region_fill : '#d1d5db');
$region_stroke = (isset($content->region_stroke) && $content->region_stroke ? $content->region_stroke : '#e5e7eb');
$region_stroke_width = (isset($content->region_stroke_width) && $content->region_stroke_width ? $content->region_stroke_width : 1);
$markerItems = (isset($content->items) && $content->items && is_array($content->items) ? $content->items : []);
$marker_stroke = (isset($content->marker_stroke) && $content->marker_stroke ? $content->marker_stroke : '#ffffff');
$marker_label = (isset($content->marker_label) && $content->marker_label ? $content->marker_label : 13);
$marker_radius = (isset($content->marker_radius) && $content->marker_radius ? $content->marker_radius : 6);
$marker_stroke_width = (isset($content->marker_stroke_width) && $content->marker_stroke_width ? $content->marker_stroke_width : 5);
$hover_marker_radius = $marker_radius + 3;
$hover_marker_stroke_width = $marker_stroke_width + 3;
$show_tooltip = (isset($content->show_tooltip) && $content->show_tooltip == 'yes' ? 'true' : 'false');
$tooltip_bg = (isset($content->tooltip_bg) && $content->tooltip_bg ? $content->tooltip_bg : '#010101');
$tooltip_color = (isset($content->tooltip_color) && $content->tooltip_color ? $content->tooltip_color : '#ffffff');
$show_lines = (isset($content->show_lines) && $content->show_lines == 'yes' ? true : false);
$animate_lines = (isset($content->animate_lines) && $content->animate_lines == 'yes' ? 'true' : 'false');
$curvature_lines = (isset($content->curvature_lines) && $content->curvature_lines == 'yes' ? true : false);
$line_curvature = (isset($content->line_curvature) && $content->line_curvature != '' ? $content->line_curvature : -0.7);
$line_stroke = (isset($content->line_stroke) && $content->line_stroke ? $content->line_stroke : '#818187');
$line_stroke_width = (isset($content->line_stroke_width) && $content->line_stroke_width ? $content->line_stroke_width : 1);
$defaultMarkerFillNormal = '#3b82f6';
$defaultMarkerFillHover = '#ff5050';
if (isset($content->marker_fill) && is_object($content->marker_fill)) {
$marker_fill_normal = (!empty($content->marker_fill->normal) ? $content->marker_fill->normal : $defaultMarkerFillNormal);
$marker_fill_hover = (!empty($content->marker_fill->hover) ? $content->marker_fill->hover : $defaultMarkerFillHover);
}
else if (isset($content->marker_fill) && is_string($content->marker_fill) && !empty($content->marker_fill)) {
$marker_fill_normal = $content->marker_fill;
$marker_fill_hover = $defaultMarkerFillHover;
}
else {
$marker_fill_normal = $defaultMarkerFillNormal;
$marker_fill_hover = $defaultMarkerFillHover;
}
$markers = [];
$lines = [];
if ($markerItems) {
foreach ($markerItems as $mKey => $marker) {
$marker_name = (isset($marker->name) && $marker->name ? $marker->name : '');
$marker_coords = (isset($marker->coords) && $marker->coords ? $marker->coords : [0, 0]);
$marker_coords = (is_string($marker_coords) ? explode(',', $marker_coords) : $marker_coords);
$marker_lineto = (isset($marker->lineto) && $marker->lineto ? $marker->lineto : '');
$marker_tooltip = (isset($marker->tooltip) && isset($marker->tooltip->{$this->lang}) && $marker->tooltip->{$this->lang} ? $marker->tooltip->{$this->lang} : (isset($marker->tooltip) ? array_values((array) $marker->tooltip)[0] ?? '' : ''));
$markers[$mKey] = ['name' => $marker->name ?? '', 'coords' => $marker_coords];
if ($marker_tooltip) {
$markers[$mKey]['tooltip'] = $marker_tooltip;
}
if ($marker_lineto && !empty($marker_name)) {
$lines[] = ['from' => $marker_name, 'to' => $marker_lineto];
}
}
}
$markersJson = json_encode($markers);
$linesJson = ($show_lines && $lines ? 'lines: ' . json_encode($lines) . ',' : '');
$curvature = ($show_lines && $lines && $curvature_lines ? 'curvature: ' . $line_curvature . ',' : '');
$this->addAsset('jsvectormap');
$style = '';
$responsiveItems = [
'#' . $widgetId . '-map' => [
['type' => 'height', 'unit' => 'px', 'value' => $content->map_height]
]
];
$style .= self::parseResponsiveItems($responsiveItems, $widgetId);
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-vector-map-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content position-relative">';
$output .= '<div class="fon-vector-map-container" id="' . $widgetId . '-map">';
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
$js = '<script defer src="' . $pageData['tadress'] . 'js/maps/' . $map_type . '.js"></script>' . PHP_EOL;
$js .= '<script>' . "\n" . 'window.addEventListener("load", function() {' . "\n" . ' setTimeout(function() {' . "\n" . ' var markers' . $moduleId . ' = ' . $markersJson . ';' . "\n" . ' window.map' . $moduleId . ' = new jsVectorMap({' . "\n" . ' selector: document.querySelector("#' . $widgetId . '-map"),' . "\n" . ' map: "' . $map_type . '",' . "\n\t\t\t" . 'backgroundColor: "transparent",' . "\n" . ' showTooltip: ' . $show_tooltip . ',' . "\n\t\t\t" . 'zoomOnScroll: false,' . "\n" . ' zoomButtons: ' . $show_zooms . ',' . "\n\t\t\t" . 'onLoaded(map) {' . "\n" . ' document.querySelectorAll(".jvm-marker, .jvm-label").forEach(i => {' . "\n" . ' i.classList.add("animated");' . "\n\t\t\t\t" . '});' . "\n" . ' window.addEventListener("resize", () => map.updateSize());' . "\n" . ' setTimeout(() => map.updateSize(), 700);' . "\n\t\t\t" . '},' . "\n\t\t\t" . 'regionStyle: {' . "\n\t\t\t\t" . 'initial: {' . "\n" . ' fill: "' . $region_fill . '",' . "\n" . ' stroke: "' . $region_stroke . '",' . "\n" . ' strokeWidth: ' . $region_stroke_width . ',' . "\n\t\t\t\t\t" . 'fillOpacity: 1,' . "\n\t\t\t\t\t" . 'fillRule:"evenodd"' . "\n\t\t\t\t" . '},' . "\n\t\t\t" . '},' . "\n" . ' markers: markers' . $moduleId . ',' . "\n" . ' ' . $linesJson . "\n\t\t\t" . 'markerStyle: {' . "\n\t\t\t\t" . 'initial: {' . "\n" . ' r: ' . $marker_radius . ',' . "\n" . ' fill: "' . $marker_fill_normal . '",' . "\n" . ' stroke: "' . $marker_stroke . '",' . "\n" . ' strokeWidth: ' . $marker_stroke_width . ',' . "\n" . ' strokeOpacity: 0.5' . "\n\t\t\t\t" . ' },' . "\n" . ' hover: {' . "\n" . ' r: ' . $hover_marker_radius . ',' . "\n" . ' fill: "' . $marker_fill_hover . '",' . "\n" . ' strokeWidth: ' . $hover_marker_stroke_width . ',' . "\n" . ' }' . "\n\t\t\t" . '},' . "\n\t\t\t" . 'markerLabelStyle: {' . "\n\t\t\t\t" . 'initial: {' . "\n" . ' fontSize: ' . $marker_label . ',' . "\n" . ' fontWeight: 600,' . "\n" . ' fill: "#35373e",' . "\n\t\t\t\t" . '},' . "\n\t\t\t" . '},' . "\n\t\t\t" . 'labels: {' . "\n" . ' markers: {' . "\n" . ' render: function (marker) {' . "\n" . ' return marker.name;' . "\n" . ' },' . "\n" . ' },' . "\n" . ' },' . "\n" . ' lineStyle: {' . "\n" . ' strokeDasharray: "3 3 3",' . "\n" . ' animation: ' . $animate_lines . ',' . "\n" . ' stroke: "' . $line_stroke . '",' . "\n" . ' strokeWidth: ' . $line_stroke_width . ',' . "\n" . ' ' . $curvature . "\n\t\t\t" . '},' . "\n" . ' onMarkerTooltipShow(event, tooltip, index) {' . "\n" . ' let getMarker = markers' . $moduleId . '[index];' . "\n" . ' if(getMarker && getMarker.tooltip){' . "\n" . ' let markerHTML = \'<h5 class="fs-15">\' + getMarker.name +\'</h5><p class="mb-0 small">\'+ getMarker.tooltip + \'</p>\';' . "\n" . ' tooltip.text(markerHTML,true);' . "\n\t\t\t\t" . '}' . "\n" . ' tooltip.css({ ' . "\n" . ' backgroundColor: "' . $tooltip_bg . '", ' . "\n" . ' color: "' . $tooltip_color . '" ' . "\n" . ' });' . "\n" . ' },' . "\n" . ' onRegionTooltipShow(event, tooltip, index) {' . "\n" . ' tooltip.css({ ' . "\n" . ' backgroundColor: "' . $tooltip_bg . '", ' . "\n" . ' color: "' . $tooltip_color . '" ' . "\n" . ' });' . "\n" . ' }' . "\n" . ' });' . "\n" . ' }, 1500);' . "\n" . '});' . "\n" . '</script>';
$this->addScript('footer', $pageData['page'], $js);
return $output;
}
private function video_widget(object $content, string|int $moduleId, array $pageData, object $row, bool $isLCPCandidate = false): string
{
$widgetId = 'fon-widget-' . $moduleId;
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$nameWidget = (isset($content->name_widget->{$this->lang}) && $content->name_widget->{$this->lang} ? $content->name_widget->{$this->lang} : array_values((array) $content->name_widget)[0] ?? '');
$style = '';
if (($content->name_widget_status == 'yes') && $nameWidget) {
$style .= '#' . $widgetId . ' .fon-widget-title{';
if ($content->title_color) {
$style .= 'color: ' . $content->title_color . ';';
}
if ($content->title_margin->top) {
$style .= 'margin-top: ' . $content->title_margin->top . 'px;';
}
if ($content->title_margin->bottom) {
$style .= 'margin-bottom: ' . $content->title_margin->bottom . 'px;';
}
if ($content->title_font) {
$style .= self::parseFontProperties($content->title_font);
}
$style .= '}';
}
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$output = '';
$src = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-video-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
if (($content->name_widget_status == 'yes') && $nameWidget) {
$output .= '<' . $content->heading_selector . ' class="fon-widget-title">';
$output .= $nameWidget;
$output .= '</' . $content->heading_selector . '>';
}
if ($content->video_source == '2') {
if ($content->mp4_video) {
$show_control = (isset($content->show_control) && $content->show_control == 'yes' ? 1 : 0);
$video_loop = (isset($content->video_loop) && $content->video_loop == 'yes' ? 1 : 0);
$autoplay_video = (isset($content->autoplay_video) && $content->autoplay_video == 'yes' ? 1 : 0);
$video_mute = (isset($content->video_mute) && $content->video_mute == 'yes' ? 1 : 0);
$video_poster = '';
if (is_object($content->video_poster)) {
$video_poster = (isset($content->video_poster->{$this->lang}) && $content->video_poster->{$this->lang} ? $content->video_poster->{$this->lang} : array_values((array) $content->video_poster)[0] ?? '');
}
else if (is_string($content->video_poster)) {
$video_poster = $content->video_poster;
}
$video_poster = ($video_poster ? static::assetLinkDetermine($video_poster) : $lazyPlaceholder);
$mp4_video = '';
if (is_object($content->mp4_video)) {
$mp4_video = (isset($content->mp4_video->{$this->lang}) && $content->mp4_video->{$this->lang} ? $content->mp4_video->{$this->lang} : array_values((array) $content->mp4_video)[0] ?? '');
}
else if (is_string($content->mp4_video)) {
$mp4_video = $content->mp4_video;
}
$mp4_video = static::assetLinkDetermine($mp4_video);
$output .= '<div class="fon-widget-video-local-video-wrap">';
$output .= '<video class="fon-widget-video-local-source"' . ($video_loop != 0 ? ' loop' : '') . '' . ($autoplay_video != 0 ? ' autoplay' : '') . '' . ($show_control != 0 ? ' controls' : '') . '' . ($video_mute ? ' muted' : '') . ' ' . ($video_poster ? 'poster="' . $video_poster . '"' : '') . ' controlsList="nodownload" playsinline>';
$output .= '<source src="' . $mp4_video . '" type="video/mp4">';
$output .= '</video>';
$output .= '</div>';
}
}
else {
if ($content->video_url) {
$videoUrl = '';
if (is_object($content->video_url)) {
$videoUrl = (isset($content->video_url->{$this->lang}) && $content->video_url->{$this->lang} ? $content->video_url->{$this->lang} : array_values((array) $content->video_url)[0] ?? '');
}
else if (is_string($content->video_url)) {
$videoUrl = $content->video_url;
}
$video = parse_url($videoUrl);
$video_title = '';
$aspect_ratio = '16by9';
if ($content->video_source == '0') {
$no_cookie = (isset($content->no_cookie) && $content->no_cookie == 'yes' ? 1 : 0);
$show_rel_video = (isset($content->show_rel_video) && $content->show_rel_video == 'yes' ? '&rel=0' : '&rel=1');
$youtube_no_cookie = ($no_cookie ? '-nocookie' : '');
$youtube_shorts = (isset($content->youtube_shorts) && $content->youtube_shorts == 'yes' ? 1 : 0);
$aspect_ratio = (isset($content->aspect_ratio) && $content->aspect_ratio && $youtube_shorts ? $content->aspect_ratio : '16by9');
switch ($video['host']) {
case 'www.youtu.be':
case 'youtu.be':
$id = trim($video['path'], '/');
$src = '//www.youtube' . $youtube_no_cookie . '.com/embed/' . $id . '?iv_load_policy=3' . $show_rel_video;
$video_title = (isset($content->video_title->{$this->lang}) && $content->video_title->{$this->lang} ? $content->video_title->{$this->lang} : $this->language['widget_video_default_title']);
break;
case 'www.youtube.com':
case 'youtube.com':
parse_str($video['query'], $query);
$id = ($youtube_shorts ? trim($video['path'], '/shorts/') : $query['v']);
$src = '//www.youtube' . $youtube_no_cookie . '.com/embed/' . $id . '?iv_load_policy=3' . $show_rel_video;
$video_title = (isset($content->video_title->{$this->lang}) && $content->video_title->{$this->lang} ? $content->video_title->{$this->lang} : $this->language['widget_video_default_title']);
break;
}
}
else if ($content->video_source == '1') {
$id = trim($video['path'], '/');
$initialSrc = '//player.vimeo.com/video/' . $id;
$vimeo_show_author = (isset($content->vimeo_show_author) && $content->vimeo_show_author == 'yes' ? 'byline=1' : 'byline=0');
$vimeo_mute_video = (isset($content->vimeo_mute_video) && $content->vimeo_mute_video == 'yes' ? 'muted=1' : 'muted=0');
$vimeo_show_video_title = (isset($content->vimeo_show_video_title) && $content->vimeo_show_video_title == 'yes' ? 'title=1' : 'title=0');
$vimeo_show_author_profile = (isset($content->vimeo_show_author_profile) && $content->vimeo_show_author_profile == 'yes' ? 'portrait=1' : 'portrait=0');
$embeddedParameter = [$vimeo_mute_video, $vimeo_show_author, $vimeo_show_author_profile, $vimeo_show_video_title];
$embeddedString = '';
$separator = '&';
foreach ($embeddedParameter as $key => $value) {
$embeddedString .= (0 < $key ? $separator . $value : $value);
}
$src = $initialSrc . '?' . $embeddedString;
}
}
$output .= '<div class="fon-video-block fon-embed-responsive fon-embed-responsive-' . $aspect_ratio . '">';
$output .= '<iframe class="fon-embed-responsive-item" src="' . $src . '" ' . ($video_title ? 'title="' . $video_title . '"' : '') . ' allow="accelerometer" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
$output .= '</div>';
}
$output .= '</div>';
$output .= '</div>';
return $output;
}
private function getWidgetProducts(object $content, string|int $moduleId, array $pageData, object $row, string $widgetName): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if (($content->column->xl <= 3) && $content->use_carousel == 'yes') {
$style .= '@media(min-width:1200px){';
$style .= '#' . $widgetId . '-tabContent .tab-pane .fon-content-carousel{';
$style .= 'max-width: 992px;';
$style .= 'margin-left: auto;';
$style .= 'margin-right: auto;';
$style .= '}';
$style .= '}';
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$carouselData = '';
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-row="no" data-rows="' . htmlspecialchars(Utility::jencode(['xl' => 1, 'lg' => 1, 'md' => 1, 'sm' => 1, 'xs' => 1]), ENT_QUOTES, 'UTF-8') . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '"';
}
$widgetStyle = 'default';
$widgetThemeStyle = Config::get('theme/package_style');
if (($widgetThemeStyle == '0') || !$widgetThemeStyle) {
$widgetThemeStyle = 'default';
}
if ($content && isset($content->widget_style)) {
$widgetStyle = $content->widget_style;
}
$widgetData = ['pageData' => $pageData, 'widget_name' => $widgetName, 'widget_content' => $content, 'carouselData' => $carouselData, 'currency_symbols' => self::getCurrencySymbols(), 'isWidget' => ($content ? true : false), 'widgetStyle' => $widgetStyle, 'widgetId' => $widgetId, 'row' => $row, 'showCoupon' => (isset($content->show_coupon) && $content->show_coupon == 'yes' ? true : false)];
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-' . $widgetName . '-widget ' . $content->fon_class . ' pricing-widget-style-' . $widgetStyle . '">';
if (isset($pageData['items']) && $pageData['items'] && $widgetName == $content->page_type && $content->source == 'none') {
$products = $this->getProductPackages(array_merge($widgetData, $pageData));
$output .= $products;
}
else {
$output .= '<div class="fon-widget-content">';
$widgetItems = $this->getWidgetItems('products', $content->source, $widgetName, $content->limit);
if ($widgetItems) {
if ($widgetItems['type'] == 'cats') {
if (is_array($widgetItems['cats']) && 1 < count($widgetItems['cats'])) {
$output .= '<ul class="product-group-tabs nav nav-pills mb-5 justify-content-center" id="' . $widgetId . '-tab" role="tablist">';
$i = 0;
foreach ($widgetItems['cats'] as $catId => $cat) {
if (!empty($widgetItems['items'][$catId])) {
$output .= '<li class="nav-item" role="presentation">';
$output .= '<a class="nav-link ' . ($i == 0 ? 'active' : '') . '" id="product-tab-' . $catId . '" data-bs-toggle="tab" href="#product-tab-content-' . $catId . '" role="tab" aria-controls="product-tab-content-' . $catId . '" aria-selected="' . ($i == 0 ? 'true' : 'false') . '">';
if (isset($cat['options']['icon']) && $cat['options']['icon']) {
$output .= '<i class="' . $cat['options']['icon'] . '"></i> ';
}
else if (isset($cat['icon']) && $cat['icon']) {
$img_path = 'resources' . DS . 'uploads' . DS . 'category-icon' . DS . $cat['icon'];
if (file_exists($img_path)) {
$output .= '<img class="d-inline me-2" src="' . static::assetLinkDetermine($img_path) . '" width="25" height="25" alt="' . $cat['title'] . '"> ';
}
}
$output .= $cat['title'];
$output .= '</a>';
$output .= '</li>';
++$i;
}
}
$output .= '</ul>';
}
$output .= '<div class="tab-content product-group-tabs-content" id="' . $widgetId . '-tabContent">';
$i = 0;
foreach ($widgetItems['items'] as $catId => $items) {
if (!empty($widgetItems['items'][$catId])) {
if (is_array($widgetItems['cats']) && 1 < count($widgetItems['cats'])) {
$output .= '<div class="tab-pane fade ' . ($i == 0 ? 'show active' : '') . '" id="product-tab-content-' . $catId . '" role="tabpanel" aria-labelledby="product-tab-' . $catId . '" tabindex="0">';
}
$products = $this->getPackagesList($widgetItems['items'][$catId], $widgetItems['cats'][$catId], $widgetData);
$output .= $products;
if (isset($content->show_all_link) && $content->show_all_link == 'yes') {
$output .= '<p class="text-center my-2">' . __('theme/all-products-link', ['{group_link}' => self::parseCanonicalUrl(Controllers::$init->CRLink('products', [$widgetItems['cats'][$catId]['route']])), '{group_title}' => $widgetItems['cats'][$catId]['title']]) . '</p>';
}
if (is_array($widgetItems['cats']) && 1 < count($widgetItems['cats'])) {
$output .= '</div>';
}
++$i;
}
}
$output .= '</div>';
}
else {
foreach ($widgetItems['items'] as $item_key => $item) {
if ($item['type'] != 'sms') {
$category = $this->getCategory($item['category'], 'products', $item['type']);
if ($category) {
$widgetItems['items'][$item_key]['category'] = $category;
}
}
}
$products = $this->getPackagesList($widgetItems['items'], [], $widgetData);
$output .= $products;
if (isset($content->show_all_link) && $content->show_all_link == 'yes' && $widgetName != 'special') {
$output .= '<p class="text-center my-2">' . __('theme/all-products-link', ['{group_link}' => self::parseCanonicalUrl(Controllers::$init->CRLink('products', [$widgetName])), '{group_title}' => $widgetName]) . '</p>';
}
}
}
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
private function getWidgetPages(object $content, string|int $moduleId, array $pageData, string $widgetName): string
{
$widgetId = 'fon-widget-' . $moduleId;
$style = '';
if (isset($content->css_internal) && $content->css_internal) {
$style .= str_replace('@widgetId', '#' . $widgetId, $content->css_internal);
}
if ($style) {
$this->addStyle($pageData['page'], $style);
}
$isCarousel = (isset($content->use_carousel) && $content->use_carousel == 'yes' ? true : false);
$carouselData = '';
if ($isCarousel) {
$this->addAsset('slick');
$carouselData = 'data-pagination="' . $content->pagination . '" data-arrows="' . $content->arrows . '" data-autoplay="' . $content->autoplay . '" data-pause="' . $content->hoverpause . '" data-loop="' . $content->loop . '" data-columns="' . htmlspecialchars(Utility::jencode($content->column, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" data-row="' . $content->use_row . '" data-rows="' . htmlspecialchars(Utility::jencode($content->row, JSON_HEX_QUOT), ENT_QUOTES, 'UTF-8') . '" id="carousel-' . $widgetId . '"';
}
$widgetData = ['name' => $widgetName, 'content' => $content, 'currency_symbols' => self::getCurrencySymbols(), 'carouselData' => $carouselData, 'isWidget' => ($content ? true : false), 'badress' => $pageData['badress']];
$output = '';
$output .= '<div id="' . $widgetId . '" class="fon-widget-container fon-' . $widgetName . '-widget ' . $content->fon_class . '">';
$output .= '<div class="fon-widget-content">';
$widgetItems = $this->getWidgetItems('pages', $content->sources, $widgetName, $content->limit);
$oneCategoryForAllLink = [];
if ($widgetItems) {
if ($widgetItems['type'] == 'cats') {
if (1 < count($widgetItems['cats'] ?? [])) {
$output .= '<ul class="product-group-tabs nav nav-pills mb-3 justify-content-center" id="' . $widgetId . '-tab" role="tablist">';
$i = 0;
foreach ($widgetItems['cats'] as $catId => $cat) {
$output .= '<li class="nav-item" role="presentation">';
$output .= '<a class="nav-link ' . ($i == 0 ? 'active' : '') . '" id="product-tab-' . $catId . '" data-bs-toggle="tab" href="#product-tab-content-' . $catId . '" role="tab" aria-controls="product-tab-content-' . $catId . '" aria-selected="' . ($i == 0 ? 'true' : 'false') . '">';
if (isset($cat['options']['icon']) && $cat['options']['icon']) {
$output .= '<i class="' . $cat['options']['icon'] . '"></i> ';
}
else if (isset($cat['icon']) && $cat['icon']) {
$output .= '<img class="d-inline me-2" src="' . $cat['icon'] . '" width="25" height="25" alt="' . $cat['title'] . '"> ';
}
$output .= $cat['title'];
$output .= '</a>';
$output .= '</li>';
++$i;
}
$output .= '</ul>';
}
$output .= '<div class="tab-content product-group-tabs-content" id="' . $widgetId . '-tabContent">';
$i = 0;
foreach ($widgetItems['items'] as $catId => $items) {
if (1 < count($widgetItems['cats'] ?? [])) {
$output .= '<div class="tab-pane fade ' . ($i == 0 ? 'show active' : '') . '" id="product-tab-content-' . $catId . '" role="tabpanel" aria-labelledby="product-tab-' . $catId . '" tabindex="0">';
}
$oneCategoryForAllLink = $widgetData['category'] = $widgetItems['cats'][$catId];
$pages = $this->getPageList($widgetItems['items'][$catId], $widgetData);
$output .= $pages;
if (1 < count($widgetItems['cats'] ?? [])) {
$output .= '</div>';
}
++$i;
}
$output .= '</div>';
}
else {
foreach ($widgetItems['items'] as $item_key => $item) {
if ($item['type'] != 'news') {
$oneCategoryForAllLink = $category = $this->getCategory($item['category'], $item['type']);
if ($category) {
$widgetItems['items'][$item_key]['category'] = $category;
}
}
}
$pages = $this->getPageList($widgetItems['items'], $widgetData);
$output .= $pages;
}
}
$output .= '</div>';
if (isset($content->show_all_link) && $content->show_all_link == 'yes') {
$CRLinkType = ($widgetName == 'software' ? 'softwares' : $widgetName);
$allLink = Controllers::$init->CRLink($CRLinkType);
if (($widgetItems['type'] == 'cats') && count($widgetItems['cats']) == 1) {
$allLink = self::parseCanonicalUrl(Controllers::$init->CRLink($CRLinkType . '_category', [$oneCategoryForAllLink['route']]));
}
$output .= '<p class="text-center">' . __('theme/all-' . $widgetName . '-link', ['{page_link}' => $allLink]) . '</p>';
}
$output .= '</div>';
return $output;
}
private function getWidgetItems(string $type, array|string $source, string $kind = '', int $limit = 10): array
{
$sourceItems = ($source != 'none' ? explode(': ', $source) : []);
$sourceType = ($sourceItems ? $sourceItems[0] : '');
$sourceIds = (($source != 'none') && $sourceItems ? explode(',', $sourceItems[1]) : $source);
$result = ['type' => $sourceType];
if ($sourceType == 'cats') {
foreach ($sourceIds as $sourceId) {
if ($sourceId == 'none') {
$result['cats'][$sourceId] = [];
$result['items'][$sourceId] = ($type == 'products' ? $this->getProducts($kind, $sourceId, $limit, true) : $this->getPages($kind, $sourceId, $limit, true));
}
else {
$category = ($type == 'products' ? $this->getCategory($sourceId, $type) : $this->getCategory($sourceId, $kind));
if ($category) {
$result['cats'][$category['id']] = $category;
$result['items'][$category['id']] = ($type == 'products' ? $this->getProducts($kind, $category['id'], $limit, true) : $this->getPages($kind, $category['id'], $limit, true));
}
}
}
}
else {
$result['items'] = ($type == 'products' ? $this->getProducts($kind, $sourceIds, $limit, true) : $this->getPages($kind, $sourceIds, $limit, true));
}
return $result;
}
private function getPageList(array $list, array $data): string
{
$lazyPlaceholder = static::getLazyPlaceholder();
$enableLazyLoading = Config::get('theme/enable_lazy_loading');
$output = '';
if ($list) {
if ($data['carouselData']) {
$containerClass = 'fon-content-carousel ' . $data['name'] . '-carousel';
}
else {
$containerClass = 'row row-cols-' . $data['content']->column->xs . ' row-cols-sm-' . $data['content']->column->sm . ' row-cols-md-' . $data['content']->column->md . ' row-cols-lg-' . $data['content']->column->lg . ' row-cols-xl-' . $data['content']->column->xl;
}
$output .= '<div class="' . $containerClass . ' ' . $data['name'] . '-style-' . $data['content']->widget_style . ' ' . $data['name'] . '-items-container" ' . $data['carouselData'] . '>';
foreach ($list as $item) {
if (isset($data['category']) && is_int($item['category'])) {
$item['category'] = $data['category'];
}
$item['route'] = self::getItemLink($item['type'], $item['route'], false);
if ($item['cover_image']) {
if ($item['type'] == 'software') {
$image_path = 'resources' . DS . 'uploads' . DS . $item['type'] . DS . $item['cover_image'];
}
else {
$image_path = 'resources' . DS . 'uploads' . DS . $item['type'] . DS . 'thumb' . DS . $item['cover_image'];
}
}
else if ($item['type'] == 'software') {
$image_path = 'resources' . DS . 'uploads' . DS . $item['type'] . DS . 'list-image-default.jpg';
}
else {
$image_path = 'resources' . DS . 'uploads' . DS . $item['type'] . DS . 'default.jpg';
}
$imageDimensions = NULL;
if (file_exists($image_path)) {
$item['cover_image'] = $item['image'] = static::assetLinkDetermine($image_path);
$imageDimensions = static::getImageDimensions($image_path, $data['badress']);
}
$item['short_title'] = Utility::short_text(Filter::html_clear($item['title']), 0, 50, true);
$item['short_content'] = Utility::short_text(Filter::html_clear($item['content']), 0, $data['content']->intro_text_limit ?? 100, true);
$item['ctime'] = ($data['isWidget'] ? DateManager::format(Config::get('options/date-format'), $item['ctime']) : $item['ctime']);
if ($item['type'] != 'news') {
$item['category_name'] = (isset($item['category']['title']) && $item['category']['title'] ? $item['category']['title'] : '');
$item['category_route'] = (isset($item['category']['route']) && $item['category']['route'] ? self::getItemLink($item['type'], $item['category']['route'], true) : '');
}
if ($item['type'] == 'software') {
if (isset($item['prices']) && $item['prices']) {
$item['price'] = self::calculatePrices($item['prices'], $data['currency_symbols'], $item['override_usrcurrency'], $item['type']);
}
$item['popular'] = false;
if (isset($item['options']['popular']) && $item['options']['popular']) {
$item['popular'] = true;
}
$item['buy_link'] = Controllers::$init->CRLink('order-steps', ['software', $item['id']]);
if (isset($item['options']['external_link']) && $item['options']['external_link'] != '') {
$item['buy_link'] = $item['options']['external_link'];
}
else if (isset($item['optionsl']['external_link']) && $item['optionsl']['external_link'] != '') {
$item['buy_link'] = $item['optionsl']['external_link'];
}
}
else if (($item['type'] == 'references') || $item['type'] == 'reference') {
$options = (isset($item['options']) && $item['options'] ? Utility::jdecode($item['options'], true) : []);
$item['category_name'] = (isset($item['category']['title']) && $item['category']['title'] ? $item['category']['title'] : '');
$item['category_route'] = (isset($item['category']['route']) && $item['category']['route'] ? self::getItemLink($item['type'], $item['category']['route'], true) : '');
$item['website'] = (isset($options['website']) ? $options['website'] : false);
$item['image'] = $item['cover_image'];
}
$output .= '<div class="col ' . $item['type'] . ' style-' . $data['content']->widget_style . ' ' . (isset($item['popular']) && $item['popular'] ? 'popular' : '') . '">';
if ($data['carouselData']) {
$output .= '<div class="fon-content-carousel-item">';
}
include __DIR__ . DS . 'builder' . DS . 'page-styles' . DS . $item['type'] . DS . 'style_' . $data['content']->widget_style . '.php';
if ($data['carouselData']) {
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '</div>';
}
return $output;
}
public function getProductPackages(array $pageData, bool $isGsd = false, bool $forSelection = false): mixed
{
$output = '';
$selectedCategory = [];
$category = $pageData['items']['category'];
$category2 = $pageData['items']['category2'];
$showCategory = $pageData['items']['showCategory'];
if (isset($pageData['items']) && $pageData['items']) {
if (isset($pageData['widget_content']->show_cat_info) && $pageData['widget_content']->show_cat_info == 'yes') {
$pageTitle = '';
$pageDescription = '';
if (isset($pageData['page'])) {
switch ($pageData['page']) {
case 'hosting':
$pageTitle = ___('constants/category-hosting/title');
$pageDescription = ___('constants/category-hosting/sub_title');
break;
case 'server':
$pageTitle = ___('constants/category-server/title');
$pageDescription = ___('constants/category-server/sub_title');
break;
case 'sms':
$pageTitle = ___('constants/category-sms/title');
$pageDescription = ___('constants/category-sms/sub_title');
break;
case 'software':
$pageTitle = ___('constants/category-software/title');
$pageDescription = ___('constants/category-software/sub_title');
break;
case 'special':
$pageTitle = ___('constants/category-software/title');
$pageDescription = ___('constants/category-software/sub_title');
break;
}
}
if (0 < $pageData['items']['showCategory']['id']) {
$pageTitle = $pageData['items']['showCategory']['title'];
$pageDescription = $pageData['items']['showCategory']['sub_title'];
}
$output .= '<div class="fon-section-title text-center">';
$output .= '<h2 class="fon-section-title-heading">' . $pageTitle . '</h2>';
$output .= '<p class="fon-section-title-subheading">' . $pageDescription . '</p>';
$output .= '</div>';
}
}
if (!$category2) {
$list = $pageData['functions']['get_list']($showCategory['id'], $showCategory['kind']);
$gsd = ['list' => $list, 'cat' => $showCategory['id']];
$output .= $this->getPackagesList($list, $showCategory, $pageData);
}
$categories = $pageData['functions']['get_categories']($category['id'], $category['kind']);
if ($categories) {
$catSize = count($categories);
$category_products = [];
$categories_list = [];
$selection = ($category2 ? $showCategory : false);
$showCategoryList = true;
if ($pageData['isWidget'] && isset($pageData['widget_content']->show_other_cats)) {
if ($pageData['widget_content']->show_other_cats == 'no') {
$showCategoryList = false;
}
}
$output .= '<ul class="product-group-tabs nav nav-pills mb-4 justify-content-center ' . (($catSize == 1) || !$showCategoryList ? 'd-none' : '') . '" role="tablist">';
foreach ($categories as $k => $cat) {
$list = $pageData['functions']['get_list']($cat['id'], $cat['kind']);
$subs = $pageData['functions']['get_categories']($cat['id'], $cat['kind']);
$category_products[$cat['id']] = $list;
$categories_list[$cat['id']] = $subs;
if (!$list && !$subs) {
continue;
}
$selected = false;
if ($list) {
$cat['route'] = $pageData['functions']['category_tab_route']($cat['route']);
}
else {
$cat['route'] = Controllers::$init->CRLink('products', [$cat['route']]);
}
if ($category['id']) {
if (!$selection && $k == 0) {
$selection = $cat;
}
if ($selection && $cat['id'] == $selection['id']) {
$selected = true;
}
}
else if ($category2 && $category2['id'] == $cat['id']) {
$selected = true;
$selection = $cat;
}
else if (!$selection && $category_products[$cat['id']] && $k == 0) {
$selected = true;
$selection = $cat;
}
else if (!$selection && $k == 0) {
$category = $cat;
$selected = true;
$selection = $cat;
}
$categoryTarget = $cat['route'];
if (isset($pageData['row']->row_section_id) && $pageData['row']->row_section_id) {
$categoryTarget .= '#' . $pageData['row']->row_section_id;
}
else if (isset($pageData['row']->text_class_id) && $pageData['row']->text_class_id) {
$categoryTarget .= '#' . $pageData['row']->text_class_id;
}
$output .= '<li class="nav-item" role="presentation"><a href="' . $categoryTarget . '" class="nav-link ' . ($selected ? 'active' : '') . '">';
if (isset($cat['options']['icon']) && $cat['options']['icon']) {
$output .= '<i class="' . $cat['options']['icon'] . '"></i> ';
}
else if (isset($cat['icon']) && $cat['icon']) {
$output .= '<img class="d-inline me-2" src="' . $cat['icon'] . '" width="25" height="25" alt="' . $cat['title'] . '"> ';
}
$output .= $cat['title'];
$output .= '</a></li>';
}
$output .= '</ul>';
}
if (isset($selection) && $selection) {
if (isset($category_products[$selection['id']])) {
$list = $category_products[$selection['id']];
$selectedCategory = ['category' => $selection, 'products' => $list];
$gsd = ['list' => $list, 'cat' => $selection['id']];
$output .= $this->getPackagesList($list, $selection, $pageData);
if ($category['id']) {
$categories = (isset($categories_list[$selection['id']]) ? $categories_list[$selection['id']] : false);
if ($categories) {
if ($pageData['page'] != 'hosting') {
$subCatSize = count($categories);
}
if (isset($subCatSize)) {
$output .= '<div class="fon-accordion-widget style-4">';
$output .= '<div class="accordion" id="subCatAccordion">';
}
foreach ($categories as $cK => $cat) {
$list = $pageData['functions']['get_list']($cat['id'], $cat['kind']);
$catIcon = ($cat['icon'] || isset($cat['options']['icon']) && $cat['options']['icon'] ? true : false);
if ($list) {
$gsd = ['list' => $list, 'cat' => $cat['id']];
if (isset($subCatSize)) {
$output .= '<div class="accordion-item ' . ($catIcon ? 'with-icon' : 'no-icon') . '">';
$output .= '<h5 class="accordion-header">';
$output .= '<button class="accordion-button ' . ($cK == 0 ? '' : 'collapsed') . '" type="button" data-bs-toggle="collapse" data-bs-target="#subcat-' . $cat['kind'] . '-' . $cat['id'] . '" aria-expanded="' . ($cK == 0 ? 'true' : 'false') . '" aria-controls="subcat-' . $cat['kind'] . '-' . $cat['id'] . '">';
if ($catIcon) {
$output .= '<span class="accordion-icon me-1">';
if ($cat['icon']) {
$output .= '<img class="d-inline" src="' . $cat['icon'] . '" width="25" height="25" alt="' . $cat['title'] . '"> ';
}
else if (isset($cat['options']['icon']) && $cat['options']['icon']) {
$output .= '<i class="' . $cat['options']['icon'] . '"></i> ';
}
$output .= '</span>';
}
else {
$output .= '<span class="accordion-icon me-1"><i class="fa-solid fa-server"></i></span>';
}
$output .= $cat['title'];
$output .= '</button>';
$output .= '</h5>';
$output .= '<div id="subcat-' . $cat['kind'] . '-' . $cat['id'] . '" class="accordion-collapse collapse ' . ($cK == 0 ? 'show' : '') . '" data-bs-parent="#subCatAccordion">';
$output .= '<div class="accordion-body">';
}
$output .= $this->getPackagesList($list, $cat, $pageData);
if (isset($subCatSize)) {
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
}
}
}
if (isset($subCatSize)) {
$output .= '</div>';
$output .= '</div>';
}
}
}
}
}
if ($isGsd) {
return $gsd ?? [];
}
else if ($forSelection) {
return $selectedCategory;
}
else {
return $output;
}
}
public function getPackagesList(array $list, array $cat, array $widgetData = []): string
{
Helper::Load('Image');
$widgetData['currency_symbols'] = self::getCurrencySymbols();
if (!isset($widgetData['currency_map']) || !is_array($widgetData['currency_map']) || !$widgetData['currency_map']) {
$widgetData['currency_map'] = [];
foreach (Money::getCurrencies() as $cr) {
$widgetData['currency_map'][$cr['id']] = $cr['code'];
}
}
if (!isset($widgetData['percent_formatter']) || !($widgetData['percent_formatter'] instanceof NumberFormatter)) {
$localeLangCode = (Language::selected() == 'tr' ? 'tr_TR' : 'en_US');
$widgetData['percent_formatter'] = new NumberFormatter($localeLangCode, NumberFormatter::PERCENT);
}
$output = '';
$showDetailLink = (isset($widgetData['widget_content']->show_detail_link) && $widgetData['widget_content']->show_detail_link == 'yes' ? true : false);
$detailLinkType = (isset($widgetData['widget_content']->detail_link_type) ? $widgetData['widget_content']->detail_link_type : 'category');
if (isset($widgetData['widget_content']->detail_link)) {
$detailLinkUrl = (isset($widgetData['widget_content']->detail_link->{$this->lang}) ? $widgetData['widget_content']->detail_link->{$this->lang} : array_values((array) $widgetData['widget_content']->detail_link)[0] ?? '');
}
else {
$detailLinkUrl = '';
}
if (isset($widgetData['widget_content']->detail_link_text)) {
$detailLinkText = (isset($widgetData['widget_content']->detail_link_text->{$this->lang}) ? $widgetData['widget_content']->detail_link_text->{$this->lang} : array_values((array) $widgetData['widget_content']->detail_link_text)[0] ?? '');
}
else {
$detailLinkText = '';
}
$detailLinkTarget = (isset($widgetData['widget_content']->detail_link_target) && $widgetData['widget_content']->detail_link_target ? $widgetData['widget_content']->detail_link_target : '_self');
$widgetStyle = $widgetData['widgetStyle'] ?? (Config::get('theme/package_style') == '0' ? 'default' : Config::get('theme/package_style'));
$showCoupon = $widgetData['showCoupon'] ?? false;
$show_price_type = (isset($widgetData['widget_content']->show_price_type) && $widgetData['widget_content']->show_price_type ? $widgetData['widget_content']->show_price_type : 'default');
if ($show_price_type == 'yes') {
$show_price_type = 'month_year';
}
$price_calc = $widgetData['widget_content']->price_calc ?? 'default';
$show_free_label = !isset($widgetData['widget_content']->show_free_label) || $widgetData['widget_content']->show_free_label == 'yes';
$free_label_text = self::getFieldMultilingualText($widgetData['widget_content']->free_label_text ?? NULL, $this->lang, __('theme/is_free'));
if ($show_free_label && empty($free_label_text)) {
$free_label_text = __('theme/is_free');
}
$card_button_action_on_free = (isset($widgetData['widget_content']->card_button_action_on_free) && $widgetData['widget_content']->card_button_action_on_free ? $widgetData['widget_content']->card_button_action_on_free : 'default');
$enable_custom_card_button_label = isset($widgetData['widget_content']->enable_custom_card_button_label) && $widgetData['widget_content']->enable_custom_card_button_label == 'yes';
$custom_card_button_label = self::getFieldMultilingualText($widgetData['widget_content']->custom_card_button_label ?? NULL, $this->lang, __('website/index/add-basket-button'));
$productType = (isset($widgetData['widget_name']) ? $widgetData['widget_name'] : $widgetData['page'] ?? 'default');
$containerId = ($widgetData['widgetId'] ? $widgetData['widgetId'] . ($cat ? '-' . $cat['id'] : '') : 'product-package-container-' . ($cat ? '-' . $cat['id'] : ''));
$widgetType = ($widgetData['isWidget'] && isset($widgetData['widget_content']->display) ? $widgetData['widget_content']->display : (isset($cat['options']['list_template']) && $cat['options']['list_template'] == 2 ? 'table' : 'box'));
$showLocation = (isset($widgetData['widget_content']->show_location) && $widgetData['widget_content']->show_location == 'yes' ? true : false);
$showFirstLocation = (isset($widgetData['widget_content']->first_location) && $widgetData['widget_content']->first_location == 'yes' ? true : false);
$showFilters = (isset($widgetData['widget_content']->show_filters) && $widgetData['widget_content']->show_filters == 'yes' ? true : false);
$enabledFilters = (isset($widgetData['widget_content']->enabled_filters) && $widgetData['widget_content']->enabled_filters ? $widgetData['widget_content']->enabled_filters : ['processor', 'ram', 'disk-space', 'location']);
if ($showLocation) {
$showFilters = true;
}
$locations = [];
$periods = [];
$serverOptions = [];
if (($cat['kind'] == 'server') || $productType == 'server') {
$this->addAsset('flags');
}
if ($list) {
if ($widgetType == 'table') {
if ($cat['kind'] == 'special') {
$columns = (isset($cat['options_lang']['columns']) ? $cat['options_lang']['columns'] : []);
}
$output .= '<div class="horizontal-pricing-table-container">';
if ((($show_price_type != 'default') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) || $showFilters && $productType == 'server') {
$output .= '<div class="pricing-filter-container text-center mb-' . ($show_price_type == 'all_select' ? '5' : '3') . ' ' . $show_price_type . ' d-flex ' . ($showFilters && $productType == 'server' ? 'flex-column' : '') . ' align-items-center justify-content-center gap-3">';
if (($show_price_type == 'month_year') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) {
$output .= '<div class="pricing-period-swithcer mb-0" data-id="' . $containerId . '"><input id="monthly-package-price' . $containerId . '" class="monthly-package-price" type="radio" name="switch' . $containerId . '" checked="checked"><input id="yearly-package-price' . $containerId . '" class="yearly-package-price" type="radio" name="switch' . $containerId . '"><label class="monthly-package-price-label" for="monthly-package-price' . $containerId . '">' . ___('date/period-month') . '</label><label class="yearly-package-price-label" for="yearly-package-price' . $containerId . '">' . ___('date/period-year') . '</label><span class="package-prices-highlighter"></span></div>';
}
else if (($show_price_type == 'all_filter') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) {
foreach ($list as $sk => $sp) {
foreach ($sp['prices'] as $spkey => $spprice) {
$periods[$spkey] = $spprice['time'] . ' ' . ___('date/period-' . $spprice['period']);
}
}
if ($periods && 1 < count($periods)) {
$output .= '<div class="pricing-period-filter" data-id="#' . $containerId . '">';
$i = 0;
foreach ($periods as $spkey => $spperiod) {
$output .= '<input id="package-filter-price-' . $containerId . '-' . $spkey . '" class="package-filter-price-' . $spkey . '" type="radio" name="switch' . $containerId . '" ' . ($i == 0 ? 'checked="checked"' : '') . '>';
$output .= '<label class="package-filter-price-label-' . $spkey . '" for="package-filter-price-' . $containerId . '-' . $spkey . '">' . $spperiod . '</label>';
++$i;
}
$output .= '</div>';
}
}
if ($showFilters && $productType == 'server') {
$this->addAsset('select2');
$output .= '<div class="server-filter-container row g-2 align-items-center justify-content-center">';
foreach ($list as $sk => $sp) {
if (isset($sp['options'])) {
$serverOptions[] = $sp['options'];
}
}
if ($serverOptions && 1 < count($serverOptions)) {
$serverProcessors = [];
$serverRams = [];
$serverDisks = [];
$serverBandwidths = [];
$serverRaids = [];
foreach ($serverOptions as $pkg) {
if (isset($pkg['processor'])) {
$serverProcessors[] = $pkg['processor'];
}
if (isset($pkg['ram'])) {
$serverRams[] = $pkg['ram'];
}
if (isset($pkg['disk-space'])) {
$serverDisks[] = $pkg['disk-space'];
}
if (isset($pkg['bandwidth'])) {
$serverBandwidths[] = $pkg['bandwidth'];
}
if (isset($pkg['raid'])) {
$serverRaids[] = $pkg['raid'];
}
}
$serverProcessors = array_unique($serverProcessors);
$serverRams = array_unique($serverRams);
$serverDisks = array_unique($serverDisks);
$serverBandwidths = array_unique($serverBandwidths);
$serverRaids = array_unique($serverRaids);
sort($serverProcessors);
sort($serverRams);
sort($serverDisks);
sort($serverBandwidths);
sort($serverRaids);
$filtersCounts = 0;
if ($serverProcessors && 1 < count($serverProcessors) && in_array('processor', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-processor" class="form-select select-filter processor-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-cpu-label="' . __('website/products/server-list-processor') . '">';
$output .= '<option value="">' . __('website/products/server-list-processor') . '</option>';
foreach ($serverProcessors as $serverProcessor) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverProcessor)) . '">' . htmlspecialchars($serverProcessor) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverRams && 1 < count($serverRams) && in_array('ram', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-ram" class="form-select select-filter ram-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-ram-label="' . __('website/products/server-list-ram') . '">';
$output .= '<option value="">' . __('website/products/server-list-ram') . '</option>';
foreach ($serverRams as $serverRam) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverRam)) . '">' . htmlspecialchars($serverRam) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverDisks && 1 < count($serverDisks) && in_array('disk-space', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-disk" class="form-select select-filter disk-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-disk-label="' . __('website/products/server-list-disk') . '">';
$output .= '<option value="">' . __('website/products/server-list-disk') . '</option>';
foreach ($serverDisks as $serverDisk) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverDisk)) . '">' . htmlspecialchars($serverDisk) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverBandwidths && 1 < count($serverBandwidths) && in_array('bandwidth', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-bandwidth" class="form-select select-filter bandwidth-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-bandwidth-label="' . __('website/products/server-list-bandwidth') . '">';
$output .= '<option value="">' . __('website/products/server-list-bandwidth') . '</option>';
foreach ($serverBandwidths as $serverBandwidth) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverBandwidth)) . '">' . htmlspecialchars($serverBandwidth) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverRaids && 1 < count($serverRaids) && in_array('raid', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-raid" class="form-select select-filter raid-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-raid-label="' . __('website/products/server-list-raid') . '">';
$output .= '<option value="">' . __('website/products/server-list-raid') . '</option>';
foreach ($serverRaids as $serverRaid) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverRaid)) . '">' . htmlspecialchars($serverRaid) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
foreach ($list as $sk => $sp) {
if (isset($sp['options_lang']['location']) && !in_array($sp['options_lang']['location'], $locations)) {
$locations[] = $sp['options_lang']['location'];
}
}
if ($locations && 1 < count($locations) && in_array('location', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-location" class="form-select location-filter select-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-location-label="' . __('theme/server_location') . '">';
if (!$showFirstLocation) {
$output .= '<option value="">' . __('theme/server_location') . '</option>';
}
foreach ($locations as $location) {
$country = $code = NULL;
if (strpos($location, '-') !== false) {
$parts = explode('-', $location);
$country = $parts[0];
$code = end($parts);
}
else {
$country = $location;
$code = NULL;
}
if (!empty($code)) {
$code = mb_convert_encoding((string) $code, 'UTF-8', 'UTF-8');
}
$output .= '<option value="' . Filter::permalink(htmlspecialchars($location)) . '" data-flag="' . strtolower(htmlspecialchars($code)) . '">' . $country . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($filtersCounts && 2 <= $filtersCounts) {
$output .= '<div class="col btn-clear-filters" style="display: none;"><button type="button" class="btn btn-danger"><i class="fa-solid fa-times" title="' . __('theme/clear_filters') . '"></i></button></div>';
}
}
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '<div id="' . $containerId . '" class="fon-pricing-tables">';
$productCards = [];
foreach ($list as $k => $product) {
$product['order_image'] = Image::picture('product', $product['id'], 'order');
$opt = $product['options'];
$optl = $product['options_lang'];
$p_n = 0;
$prices = (!isset($product['prices']) ? [] : $product['prices']);
$productPrice = self::calculatePrices($prices, $widgetData['currency_symbols'], $product['override_usrcurrency'], $productType, $show_price_type, $price_calc);
$columnCount = (isset($columns) && $columns ? 3 + count($columns) : 8);
if (!isset($product['buy_link'])) {
if (isset($optl['external_link']) && $optl['external_link'] != '') {
$buy_link = $optl['external_link'];
}
else if (isset($product['optionsl']['external_link']) && $product['optionsl']['external_link'] != '') {
$buy_link = $product['optionsl']['external_link'];
}
else if (isset($product['options']['external_link']) && $product['options']['external_link'] != '') {
$buy_link = $product['options']['external_link'];
}
else {
$buy_link = Controllers::$init->CRLink('order-steps', [($cat ? $cat['kind'] : $product['type']), $product['id']]);
}
}
else if (isset($optl['external_link']) && $optl['external_link'] != '') {
$buy_link = $optl['external_link'];
}
else if (isset($product['optionsl']['external_link']) && $product['optionsl']['external_link'] != '') {
$buy_link = $product['optionsl']['external_link'];
}
else if (isset($product['options']['external_link']) && $product['options']['external_link'] != '') {
$buy_link = $product['options']['external_link'];
}
else {
$buy_link = $product['buy_link'];
}
$buy_button_name = __('website/index/add-basket-button');
if (isset($optl['buy_button_name']) && $optl['buy_button_name'] != '') {
$buy_button_name = $optl['buy_button_name'];
}
else if (isset($product['optionsl']['buy_button_name']) && $product['optionsl']['buy_button_name'] != '') {
$buy_button_name = $product['optionsl']['buy_button_name'];
}
else if (isset($product['options']['buy_button_name']) && $product['options']['buy_button_name'] != '') {
$buy_button_name = $product['options']['buy_button_name'];
}
else if ($enable_custom_card_button_label && !empty($custom_card_button_label)) {
$buy_button_name = $custom_card_button_label;
}
$columnWidth = 100 / $columnCount;
if (!empty($cat)) {
$catTitle = $cat['title'];
$pattern = '/^(http:\\/\\/|https:\\/\\/)/';
if (preg_match($pattern, $cat['route'])) {
$catRoute = $cat['route'];
}
else {
$catRoute = Controllers::$init->CRLink('products', [$cat['route']]);
}
}
else if (is_array($product['category']) && $product['category']) {
$catTitle = $product['category']['title'];
$pattern = '/^(http:\\/\\/|https:\\/\\/)/';
if (preg_match($pattern, $product['category']['route'])) {
$catRoute = $product['category']['route'];
}
else {
$catRoute = Controllers::$init->CRLink('products', [$product['category']['route']]);
}
}
else {
$catRoute = '';
$catTitle = '';
}
if (isset($widgetData['items']) && $widgetData['items'] && 0 < (int) $widgetData['items']['showCategory']['id']) {
$catRoute = '';
}
if (isset($product['features']) && $product['features']) {
$productFeatures = (self::isJSON($product['features']) ? Utility::jdecode($product['features'], true) : $product['features']);
}
ob_start();
include __DIR__ . DS . 'builder' . DS . 'product-styles' . DS . 'table.php';
$productCards[] = ob_get_clean();
}
if ($productCards) {
$output .= implode('', $productCards);
}
unset($productCards);
$output .= '</div>';
$output .= '</div>';
}
else {
$verticalAlign = (isset($widgetData['widget_content']->vertical_align) && $widgetData['widget_content']->vertical_align ? 'align-items-' . $widgetData['widget_content']->vertical_align : '');
$containerClass = 'row row-cols-1 row-cols-sm-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-3 justify-content-center pricing-style-' . $widgetStyle . ' ' . $verticalAlign;
if ($widgetData['isWidget']) {
if (isset($widgetData['carouselData']) && $widgetData['carouselData']) {
$containerClass = 'fon-content-carousel fon-products-carousel pricing-style-' . $widgetStyle . ' ' . $widgetData['widget_name'] . '-carousel ' . $verticalAlign;
}
else {
$containerClass = 'row row-cols-' . $widgetData['widget_content']->column->xs . ' row-cols-sm-' . $widgetData['widget_content']->column->sm . ' row-cols-md-' . $widgetData['widget_content']->column->md . ' row-cols-lg-' . $widgetData['widget_content']->column->lg . ' row-cols-xl-' . $widgetData['widget_content']->column->xl . ' justify-content-center pricing-style-' . $widgetStyle . ' ' . $verticalAlign;
}
}
$containerId = $widgetData['widgetId'] . ($cat ? '-' . $cat['id'] : '');
if ((($show_price_type != 'default') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) || $showFilters && $productType == 'server') {
$output .= '<div class="pricing-filter-container text-center mb-' . ($show_price_type == 'all_select' ? '5' : '3') . ' ' . $show_price_type . ' d-flex ' . ($showFilters && $productType == 'server' ? 'flex-column' : '') . ' align-items-center justify-content-center gap-3">';
if (($show_price_type == 'month_year') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) {
$output .= '<div class="pricing-period-swithcer mb-0" data-id="' . $containerId . '"><input id="monthly-package-price' . $containerId . '" class="monthly-package-price" type="radio" name="switch' . $containerId . '" checked="checked"><input id="yearly-package-price' . $containerId . '" class="yearly-package-price" type="radio" name="switch' . $containerId . '"><label class="monthly-package-price-label" for="monthly-package-price' . $containerId . '">' . ___('date/period-month') . '</label><label class="yearly-package-price-label" for="yearly-package-price' . $containerId . '">' . ___('date/period-year') . '</label><span class="package-prices-highlighter"></span></div>';
}
else if (($show_price_type == 'all_filter') && in_array($productType, ['hosting' => true, 'server' => true, 'special' => true])) {
foreach ($list as $sk => $sp) {
foreach ($sp['prices'] as $spkey => $spprice) {
$periods[$spkey] = $spprice['time'] . ' ' . ___('date/period-' . $spprice['period']);
}
}
if ($periods && 1 < count($periods)) {
$output .= '<div class="pricing-period-filter" data-id="#' . $containerId . '">';
$i = 0;
foreach ($periods as $spkey => $spperiod) {
$output .= '<input id="package-filter-price-' . $containerId . '-' . $spkey . '" class="package-filter-price-' . $spkey . '" type="radio" name="switch' . $containerId . '" ' . ($i == 0 ? 'checked="checked"' : '') . '>';
$output .= '<label class="package-filter-price-label-' . $spkey . '" for="package-filter-price-' . $containerId . '-' . $spkey . '">' . $spperiod . '</label>';
++$i;
}
$output .= '</div>';
}
}
if ($showFilters && $productType == 'server') {
$this->addAsset('select2');
$output .= '<div class="server-filter-container row g-2 align-items-center justify-content-center">';
foreach ($list as $sk => $sp) {
if (isset($sp['options'])) {
$serverOptions[] = $sp['options'];
}
}
if ($serverOptions && 1 < count($serverOptions)) {
$serverProcessors = [];
$serverRams = [];
$serverDisks = [];
$serverBandwidths = [];
$serverRaids = [];
foreach ($serverOptions as $pkg) {
if (isset($pkg['processor'])) {
$serverProcessors[] = $pkg['processor'];
}
if (isset($pkg['ram'])) {
$serverRams[] = $pkg['ram'];
}
if (isset($pkg['disk-space'])) {
$serverDisks[] = $pkg['disk-space'];
}
if (isset($pkg['bandwidth'])) {
$serverBandwidths[] = $pkg['bandwidth'];
}
if (isset($pkg['raid'])) {
$serverRaids[] = $pkg['raid'];
}
}
$serverProcessors = array_unique($serverProcessors);
$serverRams = array_unique($serverRams);
$serverDisks = array_unique($serverDisks);
$serverBandwidths = array_unique($serverBandwidths);
$serverRaids = array_unique($serverRaids);
sort($serverProcessors);
sort($serverRams);
sort($serverDisks);
sort($serverBandwidths);
sort($serverRaids);
$filtersCounts = 0;
if ($serverProcessors && 1 < count($serverProcessors) && in_array('processor', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-processor" class="form-select select-filter processor-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-cpu-label="' . __('website/products/server-list-processor') . '">';
$output .= '<option value="">' . __('website/products/server-list-processor') . '</option>';
foreach ($serverProcessors as $serverProcessor) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverProcessor)) . '">' . htmlspecialchars($serverProcessor) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverRams && 1 < count($serverRams) && in_array('ram', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-ram" class="form-select select-filter ram-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-ram-label="' . __('website/products/server-list-ram') . '">';
$output .= '<option value="">' . __('website/products/server-list-ram') . '</option>';
foreach ($serverRams as $serverRam) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverRam)) . '">' . htmlspecialchars($serverRam) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverDisks && 1 < count($serverDisks) && in_array('disk-space', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-disk" class="form-select select-filter disk-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-disk-label="' . __('website/products/server-list-disk') . '">';
$output .= '<option value="">' . __('website/products/server-list-disk') . '</option>';
foreach ($serverDisks as $serverDisk) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverDisk)) . '">' . htmlspecialchars($serverDisk) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverBandwidths && 1 < count($serverBandwidths) && in_array('bandwidth', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-bandwidth" class="form-select select-filter bandwidth-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-bandwidth-label="' . __('website/products/server-list-bandwidth') . '">';
$output .= '<option value="">' . __('website/products/server-list-bandwidth') . '</option>';
foreach ($serverBandwidths as $serverBandwidth) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverBandwidth)) . '">' . htmlspecialchars($serverBandwidth) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($serverRaids && 1 < count($serverRaids) && in_array('raid', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-raid" class="form-select select-filter raid-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-raid-label="' . __('website/products/server-list-raid') . '">';
$output .= '<option value="">' . __('website/products/server-list-raid') . '</option>';
foreach ($serverRaids as $serverRaid) {
$output .= '<option value="' . Filter::permalink(htmlspecialchars($serverRaid)) . '">' . htmlspecialchars($serverRaid) . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
foreach ($list as $sk => $sp) {
if (isset($sp['options_lang']['location']) && !in_array($sp['options_lang']['location'], $locations)) {
$locations[] = $sp['options_lang']['location'];
}
}
if ($locations && 1 < count($locations) && in_array('location', $enabledFilters)) {
++$filtersCounts;
$output .= '<div class="col">';
$output .= '<select id="' . $containerId . '-server-location" class="form-select location-filter select-filter" data-id="' . $containerId . '" data-type="' . $widgetType . '" data-carousel="' . (isset($widgetData['carouselData']) && $widgetData['carouselData'] ? 1 : 0) . '" data-location-label="' . __('theme/server_location') . '">';
if (!$showFirstLocation) {
$output .= '<option value="">' . __('theme/server_location') . '</option>';
}
foreach ($locations as $location) {
$country = $code = NULL;
if (strpos($location, '-') !== false) {
$parts = explode('-', $location);
$country = $parts[0];
$code = end($parts);
}
else {
$country = $location;
$code = NULL;
}
if (!empty($code)) {
$code = mb_convert_encoding((string) $code, 'UTF-8', 'UTF-8');
}
$output .= '<option value="' . Filter::permalink(htmlspecialchars($location)) . '" data-flag="' . strtolower(htmlspecialchars($code)) . '">' . $country . '</option>';
}
$output .= '</select>';
$output .= '</div>';
}
if ($filtersCounts && 2 <= $filtersCounts) {
$output .= '<div class="col btn-clear-filters" style="display: none;"><button type="button" class="btn btn-danger"><i class="fa-solid fa-times" title="' . __('theme/clear_filters') . '"></i></button></div>';
}
}
$output .= '</div>';
}
$output .= '</div>';
}
$output .= '<div class="' . $containerClass . ' fon-pricing-tables" ' . ($widgetData['carouselData'] ?? '') . ' id="' . $containerId . '">';
$productCards = [];
foreach ($list as $product) {
$product['order_image'] = Image::picture('product', $product['id'], 'order');
$popular = false;
$prices = (!isset($product['prices']) ? [] : $product['prices']);
$productPrice = self::calculatePrices($prices, $widgetData['currency_symbols'], $product['override_usrcurrency'], $productType, $show_price_type, $price_calc);
$categoryCoupon = [];
$productCoupon = [];
if ($cat) {
if ($cat['kind'] == 'special') {
$categortKind = $this->getCategory($cat['id'], 'products', 'special');
$categoryKindId = $categortKind['kind_id'] ?? ($categortKind['kind_id'] ?? 0);
if ($categoryKindId) {
$categoryCoupon = $this->couponCheck('category', $cat['kind'], [$categoryKindId . '/' . $cat['id']]);
}
else {
$categoryCoupon = $this->couponCheck('category', $cat['kind'], [$cat['id']]);
}
$productCoupon = $this->couponCheck('product', $product['type'], [$categoryKindId, $product['id']]);
}
else {
$categoryCoupon = $this->couponCheck('category', $cat['kind'], [$cat['id']]);
$productCoupon = $this->couponCheck('product', $product['type'], [$cat['id'], $product['id']]);
}
}
else if (isset($product['category'])) {
$categoryId = (is_array($product['category']) ? $product['category']['id'] : $product['category']);
if ($cat['kind'] == 'special') {
$categortKind = $this->getCategory($categoryId, 'products', 'special');
$categoryKindId = $categortKind['kind_id'] ?? ($categortKind['kind_id'] ?? 0);
if ($categoryKindId) {
$categoryCoupon = $this->couponCheck('category', $cat['kind'], [$categoryKindId . '/' . $cat['id']]);
}
else {
$categoryCoupon = $this->couponCheck('category', $cat['kind'], [$cat['id']]);
}
$productCoupon = $this->couponCheck('product', $product['type'], [$categoryKindId, $product['id']]);
}
else {
$categoryCoupon = $this->couponCheck('category', $product['type'], [$categoryId]);
$productCoupon = $this->couponCheck('product', $product['type'], [$categoryId, $product['id']]);
}
}
else {
$categoryCoupon = $this->couponCheck('category', $product['type'], [0, $product['id']]);
$productCoupon = $this->couponCheck('product', $product['type'], [0, $product['id']]);
}
if (isset($product['options']['popular']) && $product['options']['popular']) {
$popular = true;
}
$features_output = '';
$slogan = '';
$packageIcon = '';
if ($product['features']) {
$productFeatures = (self::isJSON($product['features']) ? Utility::jdecode($product['features'], true) : $product['features']);
if (is_array($productFeatures) && isset($productFeatures['slogan'])) {
$slogan = $productFeatures['slogan'];
}
if (is_array($productFeatures) && isset($productFeatures['icon'])) {
$packageIcon = $productFeatures['icon'];
}
if ($product['type'] == 'server') {
$serverFeatures = [];
$server['features'] = ['processor', 'ram', 'disk-space', 'bandwidth', 'raid'];
foreach ($server['features'] as $key) {
if (isset($product['options'][$key])) {
$serverFeatures[] = ['name' => match ($key) {
'processor' => __('website/products/server-list-processor'),
'ram' => __('website/products/server-list-ram'),
'disk-space' => __('website/products/server-list-disk'),
'bandwidth' => __('website/products/server-list-bandwidth'),
'raid' => __('website/products/server-list-raid')
}, 'desc' => '', 'icon' => match ($key) {
'processor' => 'fa-solid fa-microchip',
'ram' => 'fa-solid fa-memory',
'disk-space' => 'fa-solid fa-hard-drive',
'bandwidth' => 'fa-solid fa-gauge-high',
'raid' => 'fa-solid fa-server'
}, 'type' => 'text', 'text' => $product['options'][$key], 'exist' => true];
}
}
if (isset($product['options_lang']['location'])) {
$country = '-';
$code = NULL;
if ($product['options_lang']['location'] != '') {
if (strpos($product['options_lang']['location'], '-') !== false) {
$parts = explode('-', $product['options_lang']['location']);
$country = $parts[0];
$code = end($parts);
}
else {
$country = $product['options_lang']['location'];
$code = NULL;
}
}
$serverFeatures[] = ['name' => __('website/products/server-list-location'), 'desc' => '', 'icon' => 'fa-solid fa-location-dot', 'type' => 'text', 'text' => ($code ? '<i class="flag flag-xs rounded-1 flag-country-' . strtolower($code) . ' me-1"></i>' . $country : $country), 'exist' => true];
}
if ($serverFeatures && is_array($productFeatures) && isset($productFeatures['features'])) {
$productFeatures['features'] = array_merge($serverFeatures, $productFeatures['features']);
}
}
}
else if ($product['type'] == 'server') {
$product['features'] = ['processor', 'ram', 'disk-space', 'bandwidth', 'raid'];
$productFeatures = [
'count' => 6,
'features' => []
];
if (isset($product['options']) && is_array($product['options'])) {
foreach ($product['features'] as $key) {
if (isset($product['options'][$key])) {
$productFeatures['features'][] = ['name' => match ($key) {
processor => __('website/products/server-list-processor'),
ram => __('website/products/server-list-ram'),
disk-space => __('website/products/server-list-disk'),
bandwidth => __('website/products/server-list-bandwidth'),
raid => __('website/products/server-list-raid')
}, 'desc' => '', 'icon' => match ($key) {
processor => 'fa-solid fa-microchip',
ram => 'fa-solid fa-memory',
disk-space => 'fa-solid fa-hard-drive',
bandwidth => 'fa-solid fa-gauge-high',
raid => 'fa-solid fa-server'
}, 'type' => 'text', 'text' => $product['options'][$key], 'exist' => true];
}
}
}
if (isset($product['options_lang']['location'])) {
$country = '-';
$code = NULL;
if ($product['options_lang']['location'] != '') {
if (strpos($product['options_lang']['location'], '-') !== false) {
$parts = explode('-', $product['options_lang']['location']);
$country = $parts[0];
$code = end($parts);
}
else {
$country = $product['options_lang']['location'];
$code = NULL;
}
}
$productFeatures['features'][] = ['name' => __('website/products/server-list-location'), 'desc' => '', 'icon' => 'fa-solid fa-location-dot', 'type' => 'text', 'text' => ($code ? '<i class="flag flag-xs rounded-1 flag-country-' . strtolower($code) . ' me-1"></i>' . $country : $country), 'exist' => true];
}
}
$optl = $product['options_lang'];
if (!isset($product['buy_link'])) {
if (isset($product['options']['external_link']) && $product['options']['external_link'] != '') {
$buy_link = $product['options']['external_link'];
}
else if (isset($product['optionsl']['external_link']) && $product['optionsl']['external_link'] != '') {
$buy_link = $product['optionsl']['external_link'];
}
else if (isset($optl['external_link']) && $optl['external_link'] != '') {
$buy_link = $optl['external_link'];
}
else {
$buy_link = Controllers::$init->CRLink('order-steps', [($cat ? $cat['kind'] : $product['type']), $product['id']]);
}
}
else if (isset($optl['external_link']) && $optl['external_link'] != '') {
$buy_link = $optl['external_link'];
}
else if (isset($product['optionsl']['external_link']) && $product['optionsl']['external_link'] != '') {
$buy_link = $product['optionsl']['external_link'];
}
else if (isset($product['options']['external_link']) && $product['options']['external_link'] != '') {
$buy_link = $product['options']['external_link'];
}
else {
$buy_link = $product['buy_link'];
}
$buy_button_name = __('website/index/add-basket-button');
if (isset($optl['buy_button_name']) && $optl['buy_button_name'] != '') {
$buy_button_name = $optl['buy_button_name'];
}
else if (isset($product['optionsl']['buy_button_name']) && $product['optionsl']['buy_button_name'] != '') {
$buy_button_name = $product['optionsl']['buy_button_name'];
}
else if (isset($product['options']['buy_button_name']) && $product['options']['buy_button_name'] != '') {
$buy_button_name = $product['options']['buy_button_name'];
}
else if ($enable_custom_card_button_label && !empty($custom_card_button_label)) {
$buy_button_name = $custom_card_button_label;
}
if (!empty($cat)) {
$catTitle = $cat['title'];
$pattern = '/^(http:\\/\\/|https:\\/\\/)/';
if (preg_match($pattern, $cat['route'])) {
$catRoute = $cat['route'];
}
else if (isset($widgetData['items']) && $widgetData['items'] && 0 < (int) $widgetData['items']['showCategory']['id'] && $widgetData['items']['showCategory']['id'] == $cat['id']) {
$catRoute = '';
}
else {
$catRoute = Controllers::$init->CRLink('products', [$cat['route']]);
}
}
else if (is_array($product['category']) && $product['category']) {
$catTitle = $product['category']['title'];
$pattern = '/^(http:\\/\\/|https:\\/\\/)/';
if (preg_match($pattern, $product['category']['route'])) {
$catRoute = $product['category']['route'];
}
else {
$catRoute = Controllers::$init->CRLink('products', [$product['category']['route']]);
}
}
else if (isset($widgetData['items']) && $widgetData['items'] && 0 < (int) $widgetData['items']['showCategory']['id']) {
$catRoute = '';
}
else {
$catRoute = '';
$catTitle = '';
}
ob_start();
include __DIR__ . DS . 'builder' . DS . 'product-styles' . DS . 'grid_' . $widgetStyle . '.php';
$productCards[] = ob_get_clean();
}
if ($productCards) {
$output .= implode('', $productCards);
}
unset($productCards);
$output .= '</div>';
}
}
return $output;
}
public function getPageContent(string $pageType, array $sourcePage): array
{
$cacheActive = false;
$themeCache = Config::get('theme/cache_pages');
$globalCache = Config::get('general/cache');
if ($themeCache && $globalCache) {
$cacheActive = true;
}
if ($cacheActive) {
$cache = Controllers::$cache;
$cache->setCache('fonbuilderpages');
$cache->eraseExpired();
}
if ($cacheActive) {
if (!$cache->isCached('page_' . $pageType . '_' . $sourcePage['id'])) {
$page = static::pageContentQuery($pageType, $sourcePage['id'] ?? 0);
$cache->store('page_' . $pageType . '_' . $sourcePage['id'], $page, '86400');
}
else {
$page = $cache->retrieve('page_' . $pageType . '_' . $sourcePage['id']);
}
}
else {
$page = static::pageContentQuery($pageType, $sourcePage['id'] ?? 0);
}
if (!$page && in_array($pageType, ['hosting' => true, 'server' => true, 'sms' => true, 'special' => true])) {
if ($cacheActive) {
if (!$cache->isCached('page_' . $pageType . '_' . $sourcePage['parent'])) {
$page = static::pageContentQuery($pageType, $sourcePage['parent'] ?? 0);
$cache->store('page_' . $pageType . '_' . $sourcePage['parent'], $page, '86400');
}
else {
$page = $cache->retrieve('page_' . $pageType . '_' . $sourcePage['parent']);
}
}
else {
$page = static::pageContentQuery($pageType, $sourcePage['parent'] ?? 0);
}
if (!$page) {
if ($cacheActive) {
if (!$cache->isCached('page_' . $pageType . '_0')) {
$page = static::pageContentQuery($pageType, 0);
$cache->store('page_' . $pageType . '_0', $page, '86400');
}
else {
$page = $cache->retrieve('page_' . $pageType . '_0');
}
}
else {
$page = static::pageContentQuery($pageType, 0);
}
}
}
$this->addAsset('builder');
if (isset($page['page_style']) && $page['page_style']) {
$pageType = ($pageType != 'page' ? $pageType : 'page-detail-normal');
$this->addStyle($pageType, $page['page_style']);
}
$page['page_content'] = (isset($page['page_content']) && $page['page_content'] ? Utility::jdecode(html_entity_decode($page['page_content'], ENT_QUOTES, 'UTF-8')) : []);
$page['page_options'] = (isset($page['page_options']) && $page['page_options'] ? Utility::jdecode(html_entity_decode($page['page_options'], ENT_QUOTES, 'UTF-8'), true) : []);
return $page;
}
private static function pageContentQuery(string $pageType, ?int $pageId = 0): array
{
if (is_null($pageId) || !$pageId) {
$pageId = 0;
}
$page_query = Models::$init->db->select('*');
$page_query->from('fonpagebuilder');
if ($pageType == 'custom') {
$page_query->where('id', '=', (string) $pageId, '&&');
}
else {
$page_query->where('type_id', '=', (string) $pageId, '&&');
}
$page_query->where('status', '=', '1', '&&');
$page_query->where('type', '=', (string) $pageType);
$page = ($page_query->build() ? $page_query->getAssoc() : []);
return $page;
}
private function getProducts(string $kind = '', array|string $id = [], int $limit = 10, bool $widget = false): array
{
$select = ['p.id', 'p.type', 'p.type_id', 'p.category', 'p.rank', 'p.override_usrcurrency', 'p.options', 'pl.options AS options_lang', 'pl.options AS optionsl', 'pl.title', 'pl.features', 'c.options AS c_options', 'cl.options AS cl_options', 'i.name AS cover_image', 'CASE' . "\n" . ' WHEN stock = "" THEN 1' . "\n" . ' WHEN stock IS NULL THEN 1' . "\n" . ' ELSE stock' . "\n" . ' END AS haveStock'];
$query = Models::$init->db->select(implode(',', $select))->from('products AS p');
$query->join('LEFT', 'products_lang AS pl', 'pl.owner_id=p.id AND pl.lang=\'' . $this->lang . '\'');
$query->join('LEFT', 'categories_lang AS cl', 'cl.owner_id=p.category AND cl.lang=\'' . $this->lang . '\'');
$query->join('LEFT', 'pictures AS i', 'i.owner=\'product\' AND i.owner_id=p.id AND i.reason=\'order\'');
if ($kind != 'sms') {
$query->join('LEFT', 'categories AS c', 'p.category=c.id');
$query->join('LEFT', 'categories_lang AS cl', 'cl.owner_id=p.category AND cl.lang=\'' . $this->lang . '\'');
if ($id != 'none') {
$query->where('c.id', 'IS NOT NULL', '', '&&');
}
}
$query->where('pl.id', 'IS NOT NULL', '', '&&');
if ($widget) {
if (is_array($id)) {
$query->where('p.id', 'IN (' . implode(', ', $id) . ')', '', '&&');
}
else if ($id != 'none') {
$query->where('(');
$query->where('p.category', '=', $id, '||');
$query->where('FIND_IN_SET(' . $id . ',p.categories)', '', '');
$query->where(')', '', '', '&&');
}
else {
$query->where('p.category', '=', 0, '&&');
}
}
else {
$query->where('(');
$query->where('FIND_IN_SET(p.category,\'' . $id . '\')', '', '', '||');
$query->where('FIND_IN_SET(p.categories,\'' . $id . '\')', '', '', '');
$query->where(')', '', '', '&&');
}
if ($kind) {
$query->where('p.type', '=', $kind, '&&');
}
$query->where('p.status', '=', 'active', '&&');
$query->where('p.visibility', '=', 'visible');
$query->order_by('p.rank ASC');
if ($limit) {
$query->limit($limit);
}
$results = ($query->build() ? $query->fetch_assoc() : []);
if ($results) {
foreach ($results as $key => $result) {
$results[$key]['prices'] = self::getPrices('products', $result['id'], $kind);
$results[$key]['options'] = ($results[$key]['options'] ? json_decode($results[$key]['options'], true) : []);
$results[$key]['optionsl'] = ($results[$key]['optionsl'] ? json_decode($results[$key]['optionsl'], true) : []);
$results[$key]['options_lang'] = ($results[$key]['options_lang'] ? json_decode($results[$key]['options_lang'], true) : []);
}
}
return $results;
}
private function getPages(string $type = '', array|string $id = [], int $limit = 10): array
{
$select = ['p.id', 'p.type', 'p.category', 'p.ctime', 'pl.route', 'pl.title', 'pl.content', 'p.options', 'p.override_usrcurrency', 'pl.options AS optionsl', 'i.name AS cover_image'];
$query = Models::$init->db->select(implode(',', $select))->from('pages AS p');
$query->join('LEFT', 'pages_lang AS pl', 'pl.owner_id=p.id AND pl.lang=\'' . $this->lang . '\'');
$query->join('LEFT', 'pictures AS i', 'i.owner=\'page_' . $type . '\' AND i.owner_id=p.id AND i.reason=\'cover\'');
$query->where('pl.id', 'IS NOT NULL', '', '&&');
if (is_array($id)) {
$query->where('p.id', 'IN (' . implode(', ', $id) . ')', '', '&&');
}
else if ($id != 'none') {
$query->where('(');
$query->where('p.category', '=', $id, '||');
$query->where('FIND_IN_SET(' . $id . ',p.categories)', '', '');
$query->where(')', '', '', '&&');
}
$query->where('p.type', '=', $type, '&&');
$query->where('p.status', '=', 'active', '&&');
$query->where('p.visibility', '=', 'visible');
if ($type == 'software') {
if (!is_array($id) && $id != 'none') {
$query->order_by('p.rank ASC');
}
else {
$query->order_by('p.id DESC');
}
}
else if ($type == 'references') {
$query->order_by('p.rank ASC,p.id DESC');
}
else {
$query->order_by('p.id DESC');
}
$query->limit($limit);
$results = ($query->build() ? $query->fetch_assoc() : []);
if ($results) {
foreach ($results as $key => $result) {
if ($type == 'software') {
$results[$key]['prices'] = self::getPrices('softwares', $result['id'], 'software');
}
$results[$key]['options'] = ($results[$key]['options'] ? json_decode($results[$key]['options'], true) : []);
$results[$key]['optionsl'] = ($results[$key]['optionsl'] ? json_decode($results[$key]['optionsl'], true) : []);
}
}
return $results;
}
private function getCategory(int $id, string $type = 'products', string $kind = ''): array
{
$select = ['c.id', 'c.parent', 'c.kind', 'c.kind_id', 'c.options', 'cl.title', 'cl.sub_title', 'cl.route', 'cl.options AS optionsl', 'cl.options AS options_lang', 'cl.faq AS faqs', 'i.name AS background_image', '(SELECT name FROM ' . $this->db_prefix . 'pictures WHERE owner=\'category\' AND owner_id=c.id AND reason=\'icon\') AS icon'];
$query = Models::$init->db->select(implode(',', $select))->from('categories AS c');
$query->join('LEFT', 'categories_lang AS cl', 'cl.owner_id=c.id AND cl.lang=\'' . $this->lang . '\'');
$query->join('LEFT', 'pictures AS i', 'i.owner=\'category\' AND i.owner_id=c.id AND i.reason=\'background-image\'');
$query->where('cl.id', 'IS NOT NULL', '', '&&');
$query->where('c.type', '=', $type, '&&');
if ($kind) {
$query->where('c.kind', '=', $kind, '&&');
}
$query->where('c.status', '=', 'active', '&&');
$query->where('c.visibility', '=', 'visible', '&&');
$query->where('c.id', '=', $id);
$result = ($query->build() ? $query->getAssoc() : []);
if ($result) {
$result['options'] = ($result['options'] ? json_decode($result['options'], true) : []);
$result['optionsl'] = ($result['optionsl'] ? json_decode($result['optionsl'], true) : []);
$result['options_lang'] = ($result['options_lang'] ? json_decode($result['options_lang'], true) : []);
}
return $result;
}
private function getCategories(int $parent = 0, string $type = 'products', string $kind = ''): array
{
$select = ['c.id', 'c.parent', 'c.kind', 'c.options', 'cl.title', 'cl.sub_title', 'cl.route', 'cl.options AS optionsl', 'cl.options AS options_lang', 'i.name AS background_image', '(SELECT name FROM ' . $this->db_prefix . 'pictures WHERE owner=\'category\' AND owner_id=c.id AND reason=\'cover\') AS icon'];
$query = Models::$init->db->select(implode(',', $select))->from('categories AS c');
$query->join('LEFT', 'categories_lang AS cl', 'cl.owner_id=c.id AND cl.lang=\'' . $this->lang . '\'');
$query->join('LEFT', 'pictures AS i', 'i.owner=\'category\' AND i.owner_id=c.id AND i.reason=\'background-image\'');
$query->where('cl.id', 'IS NOT NULL', '', '&&');
$query->where('c.type', '=', $type, '&&');
if ($kind) {
$query->where('c.kind', '=', $kind, '&&');
}
$query->where('c.status', '=', 'active', '&&');
$query->where('c.visibility', '=', 'visible', '&&');
if (($kind === 'server') && 0 < $parent) {
$query->where('(SELECT id FROM ' . $this->db_prefix . 'products WHERE (category=c.id OR FIND_IN_SET(c.id,categories) OR FIND_IN_SET(category,(SELECT GROUP_CONCAT(id) FROM categories WHERE parent=c.id))) AND status=\'active\' AND visibility=\'visible\' LIMIT 1)', '', '', '&&');
}
$query->where('c.parent', '=', $parent);
$results = ($query->build() ? $query->fetch_assoc() : []);
if ($results) {
foreach ($results as $key => $result) {
$results[$key]['options'] = ($result['options'] ? json_decode($result['options'], true) : []);
$results[$key]['optionsl'] = ($result['optionsl'] ? json_decode($result['optionsl'], true) : []);
$results[$key]['options_lang'] = ($result['options_lang'] ? json_decode($result['options_lang'], true) : []);
}
}
return $results;
}
private static function getPrices(string $owner, int $owner_id, string $kind): array
{
$type = ($kind == 'sms' ? 'sale' : 'periodicals');
$query = Models::$init->db->select('*')->from('prices');
$query->where('type', '=', $type, '&&');
$query->where('owner', '=', $owner, '&&');
$query->where('owner_id', '=', $owner_id);
$query->order_by('rank ASC');
return ($query->build() ? $query->fetch_assoc() : []);
}
public function couponCheck(string $type = 'category', string $kind = 'hosting', array $ids = []): array
{
$sth = Models::$init->db->select('*')->from('coupons');
if ($type == 'category') {
$categoryId = $ids[0];
$sth->where('(');
$sth->where('pservices', 'LIKE', '%category/' . $kind . '/' . $categoryId . '%', '||');
if ($kind == 'special') {
if (strpos($categoryId, '/') !== false) {
$parts = explode('/', $categoryId);
$groupId = $parts[0];
$sth->where('pservices', 'LIKE', '%allOf/' . $kind . '/' . $groupId . '%');
}
else {
$sth->where('pservices', 'LIKE', '%allOf/' . $kind . '/' . $categoryId . '%');
}
}
else {
$sth->where('pservices', 'LIKE', '%allOf/' . $kind . '%');
}
$sth->where(')', '', '', '&&');
}
else {
$product_id = implode('/', $ids);
$sth->where('pservices', 'LIKE', '%product/' . $kind . '/' . $product_id . '%', '&&');
}
$sth->where('status', '=', 'active', '&&');
$sth->where('duedate', '>=', DateManager::Now());
$sth->limit('1');
$result = ($sth->build() ? $sth->getAssoc() : []);
$coupon = [];
$periodTypes = ['hour' => $this->language['coupon_hour'], 'day' => $this->language['coupon_day'], 'week' => $this->language['coupon_week'], 'month' => $this->language['coupon_month'], 'year' => $this->language['coupon_year']];
if ($result) {
if ($result['type'] == 'percentage') {
$coupon['discount'] = '%' . $result['rate'];
}
else {
$coupon['discount'] = Money::formatter_symbol($result['amount'], $result['currency']);
}
$periodtext = '';
if ($result['period_type'] && $result['period_type'] != 'none') {
if (1 < $result['period_duration']) {
$periodtext .= $result['period_duration'];
}
$periodtext .= $periodTypes[$result['period_type']];
$coupon['period'] = $periodtext;
}
$coupon['code'] = $result['code'];
$coupon['merge'] = $result['use_merge'];
}
return $coupon;
}
private function getTestimonials(int $limit = 4): array
{
$lang = Language::selected();
$query = Models::$init->db->select('t1.*,t2.message,t3.name AS image')->from('customer_feedbacks AS t1');
$query->join('LEFT', 'customer_feedbacks_lang AS t2', 't2.owner_id=t1.id AND t2.lang=\'' . $lang . '\'');
$query->join('LEFT', 'pictures AS t3', 't1.id=t3.owner_id AND t3.owner=\'customer_feedback\' AND t3.reason=\'image\'');
$query->where('t2.id', 'IS NOT NULL', '', '&&');
$query->where('status', '=', 'approved');
$query->order_by('t1.rank ASC,id DESC');
$query->limit($limit);
return ($query->build() ? $query->fetch_assoc() : []);
}
private static function getTldPrices(int $tldId = 0, string $priceType = 'register', string $order = 'p.rank ASC', int $limit = 0): array
{
$query = Models::$init->db->select()->from('prices AS p');
$query->where('p.owner', '=', 'tld', '&&');
$query->where('p.type', '=', $priceType, '&&');
if ($tldId) {
$query->where('p.owner_id', '=', $tldId);
}
$query->order_by($order);
if ($limit) {
$query->limit($limit);
}
$price = ($query->build() ? $query->getAssoc() : []);
return $price;
}
public static function getCurrencySymbols(string $code = ''): array
{
$currency_symbols = [];
foreach (Money::getCurrencies() as $currency) {
if ($code) {
if ($code == 'format') {
$currency_symbols[$currency['code']] = $currency['format'];
}
else {
$currency_symbols[] = $currency['code'];
}
}
else {
$symbol = ($currency['prefix'] != '' ? trim($currency['prefix']) : trim($currency['suffix']));
if (!$symbol) {
$symbol = $currency['code'];
}
$currency_symbols[] = $symbol;
}
}
return $currency_symbols;
}
public static function currencySymbol(string $amount, array $currency_symbols): string
{
$symbol_position = '';
$symbol = '';
$split_amount = explode(' ', $amount);
if (in_array(current($split_amount), $currency_symbols)) {
$symbol_position = 'left';
$symbol = current($split_amount);
array_shift($split_amount);
$amount = implode(' ', $split_amount);
}
else if (in_array(end($split_amount), $currency_symbols)) {
$symbol_position = 'right';
$symbol = end($split_amount);
array_pop($split_amount);
$amount = implode(' ', $split_amount);
}
if ($symbol_position == 'left') {
$priceFormatted = '<sup class="currency-symbol ' . $symbol_position . '">' . $symbol . '</sup>' . $amount;
}
else {
$priceFormatted = $amount . '<sup class="currency-symbol ' . $symbol_position . '">' . $symbol . '</sup>';
}
return $priceFormatted;
}
public static function calculatePrices(array $prices, array $currency_symbols, int|bool $override_usrcurrency = 0, string $type = 'default', string|bool $show_price_type = '', string $price_calc = 'default'): array
{
if ((($show_price_type == 'yes') || $show_price_type == 'month_year') && in_array($type, ['hosting' => true, 'server' => true, 'special' => true])) {
$productPrices = self::getPriceInfo($prices, $price_calc);
if ($productPrices && 0 < $productPrices['price']) {
$cid = $productPrices['cid'];
$amount = $productPrices['price'];
$price = Money::formatter_symbol($amount, $cid, !$override_usrcurrency);
$priceRaw = self::parsePrice($price);
$price = self::currencySymbol($price, $currency_symbols);
$amountYearly = $productPrices['yearly'];
$priceYearly = Money::formatter_symbol($amountYearly, $cid, !$override_usrcurrency);
$priceRawYearly = self::parsePrice($priceYearly);
$priceYearly = self::currencySymbol($priceYearly, $currency_symbols);
$special = false;
$specialYearly = false;
if ($productPrices['discount'] && 0 < (float) $productPrices['discount']) {
$specialAmount = (float) $amount / (1 - ((float) $productPrices['discount'] / 100));
$special = Money::formatter_symbol($specialAmount, $cid, !$override_usrcurrency);
$specialRaw = self::parsePrice($special);
$special = self::currencySymbol($special, $currency_symbols);
$specialAmountYearly = (float) $amountYearly / (1 - ((float) $productPrices['discount'] / 100));
$specialYearly = Money::formatter_symbol($specialAmountYearly, $cid, !$override_usrcurrency);
$specialRawYearly = self::parsePrice($specialYearly);
$specialYearly = self::currencySymbol($specialYearly, $currency_symbols);
}
}
if ($productPrices) {
$period = View::period(1, $productPrices['period']);
}
$productPrice = ['price' => $price ?? '', 'priceRaw' => $priceRaw ?? '', 'special' => $special ?? '', 'specialRaw' => $specialRaw ?? '', 'priceY' => $priceYearly ?? '', 'priceRawY' => $priceRawYearly ?? '', 'specialY' => $specialYearly ?? '', 'specialRawY' => $specialRawYearly ?? '', 'period' => $period ?? '', 'discount' => (float) $productPrices['discount'], 'prices' => $prices, 'prices_periodically' => $productPrices, 'show_monthly' => $show_price_type, 'monthly_calc' => $price_calc, 'show_price_type' => $show_price_type, 'time' => $productPrices['time']];
return $productPrice;
}
else if ((($show_price_type == 'all_filter') || $show_price_type == 'all_select') && in_array($type, ['hosting' => true, 'server' => true, 'special' => true])) {
$productPrices = ['price_list' => $prices, 'price_type' => $show_price_type];
if ($prices) {
foreach ($prices as $price) {
if (0 < $price['amount']) {
$cid = $price['cid'];
$amount = $price['amount'];
$productPrice = Money::formatter_symbol($amount, $cid, !$override_usrcurrency);
$productPriceRaw = self::parsePrice($productPrice);
$productPrice = self::currencySymbol($productPrice, $currency_symbols);
$productSpecial = false;
if ($price['discount'] && 0 < (float) $price['discount']) {
$productSpecialAmount = (float) $amount / (1 - ((float) $price['discount'] / 100));
$productSpecial = Money::formatter_symbol($productSpecialAmount, $cid, !$override_usrcurrency);
$productSpecialRaw = self::parsePrice($productSpecial);
$productSpecial = self::currencySymbol($productSpecial, $currency_symbols);
}
}
$period = View::period($price['time'], $price['period']);
$productPrices['filter_prices'][] = ['price' => $productPrice ?? '', 'priceRaw' => $productPriceRaw ?? '', 'special' => $productSpecial ?? '', 'specialRaw' => $productSpecialRaw ?? '', 'period' => $period ?? '', 'period_key' => $price['time'] . '_' . $price['period'], 'discount' => (float) $price['discount'], 'show_price_type' => $show_price_type, 'time' => $price['time']];
}
}
return $productPrices;
}
if (isset($prices[0]) && 0 < $prices[0]['amount']) {
$cid = $prices[0]['cid'];
$amount = $prices[0]['amount'];
$price = Money::formatter_symbol($amount, $cid, !$override_usrcurrency);
$priceRaw = self::parsePrice($price);
$price = self::currencySymbol($price, $currency_symbols);
$special = false;
if ($prices[0]['discount'] && 0 < (float) $prices[0]['discount']) {
$specialAmount = (float) $amount / (1 - ((float) $prices[0]['discount'] / 100));
$special = Money::formatter_symbol($specialAmount, $cid, !$override_usrcurrency);
$specialRaw = self::parsePrice($special);
$special = self::currencySymbol($special, $currency_symbols);
}
}
if (isset($prices[0])) {
$period = View::period($prices[0]['time'], $prices[0]['period']);
}
$productPrice = ['price' => $price ?? '', 'priceRaw' => $priceRaw ?? '', 'special' => $special ?? '', 'specialRaw' => $specialRaw ?? '', 'period' => $period ?? '', 'discount' => (float) $prices[0]['discount'], 'show_monthly' => 0, 'monthly_calc' => 'default', 'show_price_type' => $show_price_type, 'time' => $prices[0]['time']];
return $productPrice;
}
private static function getPriceInfo(array $prices, string $price_calc = 'default'): array
{
$nonePrices = [];
$monthlyPrices = [];
$yearlyPrices = [];
$otherPrices = [];
foreach ($prices as $price) {
switch ($price['period']) {
case 'none':
$nonePrices[] = $price;
break;
case 'month':
$monthlyPrices[] = $price;
break;
case 'year':
$yearlyPrices[] = $price;
break;
default:
$otherPrices[] = $price;
break;
}
}
$priceInfo = ['price' => '', 'monthly' => '', 'yearly' => '', 'period' => (isset($prices[0]['period']) ? $prices[0]['period'] : ''), 'cid' => (isset($prices[0]['cid']) ? $prices[0]['cid'] : ''), 'discount' => (isset($prices[0]['discount']) ? $prices[0]['discount'] : ''), 'time' => (isset($prices[0]['time']) ? $prices[0]['time'] : '')];
if (!empty($nonePrices)) {
$priceInfo['price'] = $nonePrices[0]['amount'];
$priceInfo['monthly'] = $nonePrices[0]['amount'];
$priceInfo['yearly'] = $nonePrices[0]['amount'];
$priceInfo['period'] = $nonePrices[0]['period'];
$priceInfo['cid'] = $nonePrices[0]['cid'];
$priceInfo['discount'] = $nonePrices[0]['discount'];
$priceInfo['time'] = $nonePrices[0]['time'];
return $priceInfo;
}
if (empty($monthlyPrices) && empty($yearlyPrices)) {
$firstPrice = $prices[0];
$priceInfo['price'] = $firstPrice['amount'];
$priceInfo['monthly'] = $firstPrice['amount'];
$priceInfo['yearly'] = $firstPrice['amount'];
$priceInfo['period'] = $nonePrices[0]['period'];
$priceInfo['cid'] = $firstPrice['cid'];
$priceInfo['discount'] = $firstPrice['discount'];
$priceInfo['time'] = $firstPrice['time'];
return $priceInfo;
}
if (!empty($monthlyPrices)) {
$monthlyPrice = array_filter($monthlyPrices, function($p) {
return $p['time'] == 1;
});
if (!empty($monthlyPrice)) {
$monthlyPrice = reset($monthlyPrice);
$priceInfo['monthly'] = $monthlyPrice['amount'];
$priceInfo['period'] = 'month';
$priceInfo['cid'] = $monthlyPrice['cid'];
$priceInfo['discount'] = $monthlyPrice['discount'];
$priceInfo['time'] = $monthlyPrice['time'];
}
else {
usort($monthlyPrices, function($a, $b) {
return $a['time'] <=> $b['time'];
});
$monthlyPrice = $monthlyPrices[0];
$priceInfo['monthly'] = number_format($monthlyPrice['amount'] / $monthlyPrice['time'], 5, '.', '');
$priceInfo['period'] = 'month';
$priceInfo['cid'] = $monthlyPrice['cid'];
$priceInfo['discount'] = $monthlyPrice['discount'];
$priceInfo['time'] = $monthlyPrice['time'];
}
}
if (!empty($yearlyPrices)) {
if ($price_calc === 'heighest_year') {
usort($yearlyPrices, function($a, $b) {
return $b['time'] <=> $a['time'];
});
}
else {
usort($yearlyPrices, function($a, $b) {
return $a['time'] <=> $b['time'];
});
}
$yearlyPrice = $yearlyPrices[0];
$yearlyPrice = $yearlyPrices[0];
$priceInfo['yearly'] = number_format($yearlyPrice['amount'] / $yearlyPrice['time'], 5, '.', '');
$priceInfo['cid'] = $yearlyPrice['cid'];
$priceInfo['discount'] = $yearlyPrice['discount'];
$priceInfo['time'] = $yearlyPrice['time'];
}
if (empty($priceInfo['monthly']) && !empty($priceInfo['yearly'])) {
if ($price_calc === 'heighest_year') {
usort($yearlyPrices, function($a, $b) {
return $b['time'] <=> $a['time'];
});
}
else {
usort($yearlyPrices, function($a, $b) {
return $a['time'] <=> $b['time'];
});
}
$yearlyPrice = $yearlyPrices[0];
$priceInfo['monthly'] = number_format($yearlyPrice['amount'] / ($yearlyPrice['time'] * 12), 5, '.', '');
$priceInfo['period'] = 'month';
$priceInfo['time'] = $yearlyPrice['time'];
}
if (empty($priceInfo['yearly']) && !empty($priceInfo['monthly'])) {
$priceInfo['yearly'] = number_format($priceInfo['monthly'] * 12, 5, '.', '');
$priceInfo['period'] = 'month';
$priceInfo['time'] = 1;
}
$priceInfo['price'] = $priceInfo['monthly'] ?: $priceInfo['yearly'];
return $priceInfo;
}
public static function parsePrice(string $price): string
{
$priceKey = $parsedPrice = $price;
$priceCode = '';
$prefix = '';
$suffix = '';
foreach (Money::getCurrencies() as $currency) {
$price = str_ireplace([$currency['prefix'], $currency['suffix'], $currency['code']], '', $price);
if (($currency['prefix'] && strpos($priceKey, $currency['prefix']) !== false) || $currency['suffix'] && strpos($priceKey, $currency['suffix']) !== false || $currency['code'] && strpos($priceKey, $currency['code']) !== false) {
$priceCode = $currency['code'];
$prefix = $currency['prefix'];
$suffix = $currency['suffix'];
}
$search = [$currency['prefix'], $currency['suffix'], $currency['code']];
$price = str_replace($search, '', $price);
$price = trim($price);
$parsedPrice = Money::parseDecimal($price);
}
$returnPrice = '';
if ($prefix) {
$returnPrice .= '<sup class="currency-symbol">' . trim($prefix) . '</sup>';
}
if (is_array($parsedPrice)) {
$returnPrice .= $parsedPrice['amount'];
if (0 < (int) $parsedPrice['decimal']) {
$returnPrice .= '<sup class="currency-decimal">.' . $parsedPrice['decimal'] . '</sup>';
}
}
else {
$returnPrice .= $parsedPrice;
}
if ($suffix) {
$returnPrice .= '<sup class="currency-symbol">' . trim($suffix) . '</sup>';
}
if (!$prefix && !$suffix) {
$returnPrice .= '<sup class="currency-symbol"> ' . $priceCode . '</sup>';
}
return $returnPrice;
}
public static function isJSON(mixed $value): bool
{
if (!is_string($value) || trim($value) === '') {
return false;
}
json_decode($value);
return json_last_error() === JSON_ERROR_NONE;
}
public static function unicodeFix(string $string): string
{
return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function(array $matches): string {
return mb_chr(hexdec($matches[1]), 'UTF-8');
}, $string);
}
private function getItemLink(string $type, string $route, bool $cat = false): string
{
$link = '';
switch ($type) {
case 'articles':
$link = ($cat ? Controllers::$init->CRLink('articles_category', [$route]) : Controllers::$init->CRLink('articles_detail', [$route]));
break;
case 'references':
$link = ($cat ? Controllers::$init->CRLink('references_category', [$route]) : Controllers::$init->CRLink('references_detail', [$route]));
break;
case 'software':
$link = ($cat ? Controllers::$init->CRLink('softwares_cat', [$route]) : Controllers::$init->CRLink('software_detail', [$route]));
break;
case 'news':
$link = ($cat ? '' : Controllers::$init->CRLink('news_detail', [$route]));
break;
}
return $link;
}
private function checkLink(string $input_link, bool $checkInternal = false): string|bool
{
$isInternal = false;
if (preg_match('/^(http:\\/\\/|https:\\/\\/)/', $input_link)) {
$fixed_link = $input_link;
}
else if (preg_match('/^(www\\.)?[\\w\\-]+\\.[a-z]{2,6}(\\/[\\w\\-\\/]*)?$/i', $input_link)) {
$fixed_link = 'https://' . $input_link;
}
else {
$isInternal = true;
$fixed_link = APP_URI . '/' . ltrim($input_link, '/');
}
return ($checkInternal ? $isInternal : $fixed_link);
}
public function getAssets(): array
{
return $this->assets;
}
public function getStyles(string $page): array|string
{
return $this->styles[$page] ?? '';
}
public function getScripts(string $page, string $position = 'footer'): string
{
$scripts = '';
if (isset($this->scripts[$position]) && isset($this->scripts[$position][$page])) {
$scripts .= $this->scripts[$position][$page];
}
return $scripts;
}
public function getHeaderCodes(string $page): string
{
if (isset($this->headerCodes[$page])) {
return $this->headerCodes[$page];
}
return '';
}
public function registerWidgetAsset(mixed $asset): void
{
$this->addAsset($asset);
}
public function registerWidgetStyle(string $page, string $style): void
{
if (($page == '') || $style == '') {
return;
}
$this->addStyle($page, $style);
}
public function registerWidgetScript(string $position, string $page, string $script): void
{
if (($position == '') || $page == '' || $script == '') {
return;
}
$this->addScript($position, $page, $script);
}
private function addAsset(mixed $asset): void
{
if (is_array($asset)) {
foreach ($asset as $item) {
if (!in_array($item, $this->assets)) {
$this->assets[] = $item;
}
}
}
else if (!in_array($asset, $this->assets)) {
$this->assets[] = $asset;
}
}
private function addScript(string $position, string $page, string $script): void
{
if (isset($this->scripts[$position][$page])) {
$this->scripts[$position][$page] .= $script;
}
else {
$this->scripts[$position][$page] = $script;
}
}
private function addStyle(string $page, string $style): void
{
if (isset($this->styles[$page])) {
$this->styles[$page] .= $style;
}
else {
$this->styles[$page] = $style;
}
}
private function addHeaderCode(string $page, string $code): void
{
if (isset($this->headerCodes[$page])) {
$this->headerCodes[$page] .= $code;
}
else {
$this->headerCodes[$page] = $code;
}
}
private function parseButtons(array $items, string|int $moduleId, array $pageData, object|string|null $align = NULL): string
{
$widgetId = 'fon-widget-' . $moduleId;
$buttonCount = count($items);
$style = '';
if (!is_object($align)) {
$rawAlign = (is_string($align) ? trim($align) : '');
$textAlign = match ($rawAlign) {
left => 'start',
center => 'center',
right => 'end',
default => 'center'
};
$align = new stdClass();
$align->xs = $align->sm = $align->md = $align->lg = $align->xl = $textAlign;
}
$hasBlockButton = false;
foreach ($items as $item) {
if (isset($item->block_button) && $item->block_button === 'yes') {
$hasBlockButton = true;
}
else {
}
}
$alignClass = ($align ? 'text-' . $align->xs . ' text-sm-' . $align->sm . ' text-md-' . $align->md . ' text-lg-' . $align->lg . ' text-xl-' . $align->xl : 'text-center');
$groupClass = (1 < $buttonCount ? 'fon-widget-button-group' : 'fon-button-wrapper');
$gridClass = ($hasBlockButton ? ' d-grid' : '');
$output = '';
$output .= '<div class="' . $alignClass . ' ' . $groupClass . $gridClass . '">';
foreach ($items as $key => $item) {
$button_style = ($item->button_style ?? '') ?: 'default';
$button_custom_style = ($item->button_custom_style ?? '') ?: 'default';
$button_type = ($item->button_type ?? '') ?: 'default';
$button_shape = ($item->button_shape ?? '') ?: 'round';
$button_size = (isset($item->button_size) && $item->button_size !== 'default' ? $item->button_size : '');
$button_rel = $item->button_rel ?? [];
$scroll_button = isset($item->scroll_button) && $item->scroll_button === 'yes';
$button_target = ($item->button_target ?? '') ?: '_self';
$class = '';
$class .= (($button_style === 'outline') && $button_type !== 'custom' ? '-' . $button_style : '');
$class .= ($button_type ? '-' . $button_type : '');
$class .= (($button_style === 'gradient') && $button_type !== 'custom' ? ' btn-style-' . $button_style : '');
$class .= ($button_size ? ' btn-' . $button_size : '');
$class .= ($button_shape !== 'round' ? ' btn-' . $button_shape : '');
$rawLink = $item->button_link ?? '';
$link = (isset($rawLink->{$this->lang}) && $rawLink->{$this->lang} ? $rawLink->{$this->lang} : array_values((array) $rawLink)[0] ?? '');
$isInternal = false;
if ($link) {
$isInternal = self::checkLink($link, true);
}
$attribs = 'id="btn-' . ($moduleId . $key) . '"';
if (!empty($button_rel) && !$scroll_button) {
$attribs .= ' rel="' . implode(' ', (array) $button_rel) . '"';
}
$attribs .= ' target="' . $button_target . '"';
if ($scroll_button && $isInternal) {
$class .= ' fon-scroll-button';
}
$rawText = $item->button_text ?? '';
$text = (isset($rawText->{$this->lang}) && $rawText->{$this->lang} ? $rawText->{$this->lang} : array_values((array) $rawText)[0] ?? '');
$show_icon = isset($item->show_button_icon) && $item->show_button_icon === 'yes';
$icon = $item->button_icon ?? '';
$icon_position = $item->button_icon_position ?? 'left';
if ($show_icon && $icon) {
$iconTag = '<i class="' . $icon . '" aria-hidden="true"></i>';
$text = ($icon_position === 'left' ? $iconTag . ' ' . $text : $text . ' ' . $iconTag);
}
$hrefTag = (!empty($link) ? 'href="' . $link . '"' : '');
$output .= '<a ' . $hrefTag . ' ' . $attribs . ' class="btn btn' . $class . '">' . $text . '</a>';
$fontProperties = (isset($item->button_font) ? self::parseFontProperties($item->button_font) : '');
if (($button_type === 'custom') || $button_type === 'link' || $button_size === 'custom' || $fontProperties) {
$style .= '#btn-' . ($moduleId . $key) . '{';
$style .= $fontProperties;
if (($button_type === 'custom') || $button_type === 'link') {
$style .= (isset($item->button_color_normal) && $item->button_color_normal ? '--bs-btn-color:' . $item->button_color_normal . ';' : '');
$style .= (isset($item->button_color_hover) && $item->button_color_hover ? '--bs-btn-hover-color:' . $item->button_color_hover . ';' : '');
}
if ($button_type === 'custom') {
if ($button_custom_style === 'default') {
if (isset($item->button_background_normal) && $item->button_background_normal) {
$style .= '--bs-btn-bg:' . $item->button_background_normal . ';';
}
if (isset($item->button_background_hover) && $item->button_background_hover) {
$style .= '--bs-btn-hover-bg:' . $item->button_background_hover . ';';
}
if (isset($item->button_border_normal) && $item->button_border_normal) {
$style .= '--bs-btn-border-color:' . $item->button_border_normal . ';';
}
else if (isset($item->button_background_normal)) {
$style .= '--bs-btn-border-color:' . $item->button_background_normal . ';';
}
if (isset($item->button_border_hover) && $item->button_border_hover) {
$style .= '--bs-btn-hover-border-color:' . $item->button_border_hover . ';';
}
else if (isset($item->button_background_hover)) {
$style .= '--bs-btn-hover-border-color:' . $item->button_background_hover . ';';
}
}
else if ($button_custom_style === 'gradient') {
$style .= '--bs-btn-border-width:0;';
$style .= (isset($item->button_gradient_normal) && $item->button_gradient_normal ? self::parseGradient($item->button_gradient_normal, 'normal') : '');
$style .= (isset($item->button_gradient_hover) && $item->button_gradient_hover ? self::parseGradient($item->button_gradient_hover, 'hover') : '');
$style .= 'background-image: var(--bs-normal-gradient);';
}
}
$style .= '}';
if (($button_type === 'custom') && $button_custom_style === 'gradient') {
$style .= '#btn-' . ($moduleId . $key) . ':hover{';
if (isset($item->button_gradient_hover) && $item->button_gradient_hover) {
$style .= 'background-image: var(--bs-hover-gradient);';
}
$style .= '}';
}
if (($button_size === 'custom') && isset($item->button_padding)) {
$responsiveItems = [];
$responsiveItems['#btn-' . $moduleId . $key][] = ['type' => 'padding', 'value' => $item->button_padding];
$style .= self::parseResponsiveItems($responsiveItems);
}
}
}
$output .= '</div>';
if ($style) {
$pageName = $pageData['page'] ?? 'index';
$this->addStyle($pageName, $style);
}
return $output;
}
private function parseButton(object $item, string|int $moduleId, array $pageData, array $btnProperties = []): string
{
$style = '';
$buttonId = $btnProperties['id'] ?? ('fon-btn-' . $moduleId . '-' . bin2hex(random_bytes(3)));
$attribs = ' id="' . $buttonId . '"';
$button_style = ($item->button_style ?? '') ?: 'default';
$button_custom_style = ($item->button_custom_style ?? '') ?: 'default';
$button_type = ($item->button_type ?? '') ?: 'default';
$button_shape = ($item->button_shape ?? '') ?: 'rounded';
$button_size = (isset($item->button_size) && $item->button_size !== 'default' ? $item->button_size : '');
$link = $item->button_link ?? '';
if (is_object($link)) {
$link = (isset($link->{$this->lang}) && $link->{$this->lang} ? $link->{$this->lang} : array_values((array) $link)[0] ?? '');
}
$rawText = $item->button_text ?? '';
$text = (isset($rawText->{$this->lang}) && $rawText->{$this->lang} ? $rawText->{$this->lang} : array_values((array) $rawText)[0] ?? '');
$show_icon = isset($item->show_button_icon) && $item->show_button_icon === 'yes';
$icon = $item->button_icon ?? '';
$icon_position = $item->button_icon_position ?? 'left';
$scrollButton = isset($item->scroll_button) && $item->scroll_button === 'yes';
$button_rel = (array) ($item->button_rel ?? []);
$button_target = ($item->button_target ?? '') ?: '_self';
$class = '';
$class .= (($button_style === 'outline') && $button_type !== 'custom' ? '-' . $button_style : '');
$class .= ($button_type ? '-' . $button_type : '');
$class .= (($button_style === 'gradient') && $button_type !== 'custom' ? ' btn-style-' . $button_style : '');
$class .= ($button_size && $button_size !== 'custom' ? ' btn-' . $button_size : '');
$class .= ($button_shape !== 'round' ? ' btn-' . $button_shape : '');
$class .= (isset($item->block_button) && $item->block_button === 'yes' ? ' btn-block' : '');
if (!empty($btnProperties)) {
if (!empty($btnProperties['class'])) {
$class .= ' ' . $btnProperties['class'];
}
if (isset($btnProperties['disabled']) && $btnProperties['disabled'] === 'true') {
$class .= ' disabled';
}
if (!empty($btnProperties['attributes'])) {
$attribs .= ' ' . $btnProperties['attributes'];
}
}
$isInternal = false;
if ($link && is_string($link)) {
$isInternal = self::checkLink($link, true);
}
if ($scrollButton && $isInternal) {
$class .= ' fon-scroll-button';
}
if (!empty($button_rel)) {
$attribs .= ' rel="' . implode(' ', $button_rel) . '"';
}
if ($button_target) {
$attribs .= ' target="' . $button_target . '"';
}
if ($show_icon && $icon) {
$iconTag = '<i class="' . $icon . '" aria-hidden="true"></i>';
$text = ($icon_position === 'left' ? $iconTag . ' ' . $text : $text . ' ' . $iconTag);
}
if (!empty($btnProperties['data']) && is_array($btnProperties['data'])) {
foreach ($btnProperties['data'] as $bdk => $btnData) {
$formattedData = (is_array($btnData) ? htmlspecialchars(json_encode($btnData, JSON_UNESCAPED_UNICODE), ENT_QUOTES, 'UTF-8') : htmlspecialchars((string) $btnData, ENT_QUOTES, 'UTF-8'));
$attribs .= ' data-' . $bdk . '=\'' . $formattedData . '\'';
}
}
$output = '';
if (!empty($btnProperties['is_btn'])) {
$output .= '<button class="btn btn' . $class . '" ' . $attribs;
if (!empty($btnProperties['type'])) {
$output .= ' type="' . $btnProperties['type'] . '"';
}
if (isset($btnProperties['disabled']) && $btnProperties['disabled']) {
$output .= ' aria-disabled="' . $btnProperties['disabled'] . '"';
}
$output .= '>' . $text . '</button>';
}
else {
$hrefTag = (!empty($link) ? 'href="' . $link . '"' : '');
$output .= '<a ' . $hrefTag . ' ' . $attribs . ' class="btn btn' . $class . '">' . $text . '</a>';
}
$fontProperties = (isset($item->button_font) && $item->button_font ? self::parseFontProperties($item->button_font) : '');
if (($button_type === 'custom') || $button_type === 'link' || $button_size === 'custom' || $fontProperties) {
$style .= '#' . $buttonId . '{';
$style .= $fontProperties;
if (($button_type === 'custom') || $button_type === 'link') {
$style .= (isset($item->button_color_normal) && $item->button_color_normal ? '--bs-btn-color:' . $item->button_color_normal . ';' : '');
$style .= (isset($item->button_color_hover) && $item->button_color_hover ? '--bs-btn-hover-color:' . $item->button_color_hover . ';' : '');
}
if ($button_type === 'custom') {
if ($button_custom_style === 'default') {
if (isset($item->button_background_normal) && $item->button_background_normal) {
$style .= '--bs-btn-bg:' . $item->button_background_normal . ';';
}
if (isset($item->button_background_hover) && $item->button_background_hover) {
$style .= '--bs-btn-hover-bg:' . $item->button_background_hover . ';';
}
if (isset($item->button_border_normal) && $item->button_border_normal) {
$style .= '--bs-btn-border-color:' . $item->button_border_normal . ';';
}
else if (isset($item->button_background_normal)) {
$style .= '--bs-btn-border-color:' . $item->button_background_normal . ';';
}
if (isset($item->button_border_hover) && $item->button_border_hover) {
$style .= '--bs-btn-hover-border-color:' . $item->button_border_hover . ';';
}
else if (isset($item->button_background_hover)) {
$style .= '--bs-btn-hover-border-color:' . $item->button_background_hover . ';';
}
}
else if ($button_custom_style === 'gradient') {
$style .= '--bs-btn-border-width:0;';
$style .= (isset($item->button_gradient_normal) && $item->button_gradient_normal ? self::parseGradient($item->button_gradient_normal, 'normal') : '');
$style .= (isset($item->button_gradient_hover) && $item->button_gradient_hover ? self::parseGradient($item->button_gradient_hover, 'hover') : '');
$style .= 'background-image: var(--bs-normal-gradient);';
}
}
$style .= '}';
if (($button_type === 'custom') && $button_custom_style === 'gradient') {
$style .= '#' . $buttonId . ':hover{';
if (isset($item->button_gradient_hover) && $item->button_gradient_hover) {
$style .= 'background-image: var(--bs-hover-gradient);';
}
$style .= '}';
}
if (($button_size === 'custom') && isset($item->button_padding)) {
$responsiveItems = [];
$responsiveItems['#' . $buttonId][] = ['type' => 'padding', 'value' => $item->button_padding];
$style .= self::parseResponsiveItems($responsiveItems);
}
}
if ($style) {
$pageName = $pageData['page'] ?? 'index';
$this->addStyle($pageName, $style);
}
return $output;
}
public static function parseFontProperties(object $properties, bool $align = true): string
{
$style = [];
if ($properties) {
foreach ($properties as $key => $property) {
if (is_object($property)) {
if ($key == 'font-style') {
if (isset($property->underline) && $property->underline) {
$style[] = 'text-decoration:underline!important';
}
if (isset($property->italic) && $property->italic) {
$style[] = 'font-style:italic!important';
}
if (isset($property->uppercase) && $property->uppercase) {
$style[] = 'text-transform:uppercase!important';
}
}
else if ($key == 'text-align') {
if ($align) {
if (isset($property->left) && $property->left) {
$style[] = $key . ':left!important';
}
else if (isset($property->center) && $property->center) {
$style[] = $key . ':center!important';
}
else if (isset($property->right) && $property->right) {
$style[] = $key . ':right!important';
}
}
}
else if (isset($property->value) && $property->value) {
$style[] = $key . ':' . $property->value . $property->unit . '!important';
}
}
else if ($property) {
$style[] = $key . ':' . $property . '!important';
}
}
}
if ($style) {
return implode(';', $style) . ';';
}
return '';
}
public static function parseResponsiveItems(array $responsiveItems = [], string $widgetId = ''): string
{
$style = '';
$breakpoints = [];
$mediaQueries = ['xxl' => '1400px', 'xl' => '1200px', 'lg' => '1199.98px', 'md' => '991.98px', 'sm' => '767.98px', 'xs' => '575.98px'];
if ($responsiveItems) {
foreach ($responsiveItems as $selector => $items) {
foreach ($items as $item) {
$itemBreakPoints = $item['value'] ?? (object) [];
if ($itemBreakPoints) {
foreach ($itemBreakPoints as $itemBreakPoint => $breakPointvalue) {
if (($breakPointvalue !== '') && $breakPointvalue !== null) {
$breakpoints[$itemBreakPoint][$selector][] = ['type' => $item['type'], 'unit' => $item['unit'] ?? '', 'value' => $breakPointvalue];
}
}
}
}
}
}
if ($breakpoints) {
$largestKey = NULL;
if (isset($breakpoints['xxl'])) {
$largestKey = 'xxl';
}
else if (isset($breakpoints['xl'])) {
$largestKey = 'xl';
}
if ($largestKey && isset($breakpoints[$largestKey])) {
foreach ($breakpoints[$largestKey] as $selector => $breakpointItem) {
if ($widgetId) {
$style .= '#' . $widgetId . ' ';
}
$style .= $selector . '{';
foreach ($breakpointItem as $item) {
$style .= $item['type'] . ': ' . $item['value'] . $item['unit'] . ';';
}
$style .= '}';
}
}
$orderedBreakpoints = array_keys($mediaQueries);
foreach ($orderedBreakpoints as $breakpoint) {
if ($breakpoint == $largestKey) {
continue;
}
if (isset($breakpoints[$breakpoint])) {
$style .= '@media(max-width:' . $mediaQueries[$breakpoint] . '){';
foreach ($breakpoints[$breakpoint] as $selector => $breakpointItem) {
if ($widgetId) {
$style .= '#' . $widgetId . ' ';
}
$style .= $selector . '{';
foreach ($breakpointItem as $item) {
$style .= $item['type'] . ': ' . $item['value'] . $item['unit'] . ';';
}
$style .= '}';
}
$style .= '}';
}
}
}
return $style;
}
private static function parseGradient(object $gradient, string $bs_gradient = ''): string
{
$style = '';
if (!empty($gradient->sc) && !empty($gradient->ec)) {
$gradientType = $gradient->gt ?? 'linear';
$startColorPos = $gradient->scp ?? 0;
$endColorPos = $gradient->ecp ?? 100;
$style .= ($bs_gradient !== '' ? '--bs-' . $bs_gradient . '-gradient: ' : 'background-image: ');
$gradientDetails = match ($gradientType) {
linear => ($gradient->lga ?? 180) . 'deg',
radial => 'at ' . str_replace('_', ' ', $gradient->rga ?? 'center'),
default => '180deg'
};
$style .= $gradientType . '-gradient(' . $gradientDetails . ', ' . $gradient->sc . ' ' . $startColorPos . '%, ' . $gradient->ec . ' ' . $endColorPos . '%);';
}
return $style;
}
public static function validateAndNormalizeColor(string $colorInput): array
{
if (preg_match('/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6,8})$/', $colorInput)) {
if ((strlen($colorInput) === 4) || strlen($colorInput) === 5) {
$hexColor = '#' . str_repeat($colorInput[1], 2) . str_repeat($colorInput[2], 2) . str_repeat($colorInput[3], 2);
if (strlen($colorInput) === 5) {
$hexColor .= str_repeat($colorInput[4], 2);
}
}
else {
$hexColor = strtolower($colorInput);
}
if (strlen($hexColor) === 9) {
$alpha = substr($hexColor, -2);
$hexColor = substr($hexColor, 0, 7);
}
else {
$alpha = 'FF';
}
return ['color' => self::hexToRgb($hexColor), 'alpha' => round(hexdec($alpha) / 255, 2)];
}
if (preg_match('/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*([\\d.]+))?\\)/i', $colorInput, $matches)) {
$red = (int) $matches[1];
$green = (int) $matches[2];
$blue = (int) $matches[3];
$alpha = (isset($matches[4]) ? (float) $matches[4] : 1);
return ['color' => $red . ',' . $green . ',' . $blue, 'alpha' => strval($alpha)];
}
if (preg_match('/hsla?\\((\\d+),\\s*(\\d+)%?,\\s*(\\d+)%?(?:,\\s*([\\d.]+))?\\)/i', $colorInput, $matches)) {
$hue = (int) $matches[1];
$saturation = (int) $matches[2];
$lightness = (int) $matches[3];
$alpha = (isset($matches[4]) ? (float) $matches[4] : 1);
$rgb = self::hslToRgb([$hue, $saturation, $lightness]);
return ['color' => $rgb, 'alpha' => $alpha];
}
return ['color' => $colorInput, 'alpha' => 1];
}
public static function hexToRgb(string $hexColor): string
{
$hexColor = ltrim($hexColor, '#');
$r = hexdec(substr($hexColor, 0, 2));
$g = hexdec(substr($hexColor, 2, 2));
$b = hexdec(substr($hexColor, 4, 2));
return $r . ',' . $g . ',' . $b;
}
public static function rgbToHex(array $rgbArray): string
{
list($r, $g, $b) = $rgbArray;
return sprintf('#%02X%02X%02X', $r, $g, $b);
}
public static function rgbToHsl(array $rgbArray): string
{
list($r, $g, $b) = $rgbArray;
$r /= 255;
$g /= 255;
$b /= 255;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$h = $s = $l = ($max + $min) / 2;
if ($max === $min) {
$h = $s = 0;
}
else {
$d = $max - $min;
$s = (0.5 < $l ? $d / (2 - $max - $min) : $d / ($max + $min));
switch ($max) {
case $r:
$h = (($g - $b) / $d) + ($g < $b ? 6 : 0);
break;
case $g:
$h = (($b - $r) / $d) + 2;
break;
default:
$h = (($r - $g) / $d) + 4;
break;
}
$h /= 6;
}
$h = round($h * 360, 2);
$s = round($s * 100, 2);
$l = round($l * 100, 2);
return $h . ' ' . $s . '%';
}
public static function hslToRgb(array $hslArray): string
{
list($h, $s, $l) = $hslArray;
$h /= 360;
$s /= 100;
$l /= 100;
if ($s == 0) {
$r = $g = $b = $l;
}
else {
$func = function($p, $q, $t) {
if ($t < 0) {
$t += 1;
}
if (1 < $t) {
$t -= 1;
}
if ($t < 0.16666666666666666) {
return $p + ($t * (($q - $p) * 6));
}
if ($t < 0.5) {
return $q;
}
if ($t < 0.6666666666666666) {
return $p + (($q - $p) * (0.6666666666666666 - $t) * 6);
}
return $p;
};
$q = ($l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($l * $s));
$p = ($l * 2) - $q;
$r = $func($p, $q, $h + 0.3333333333333333);
$g = $func($p, $q, $h);
$b = $func($p, $q, $h - 0.3333333333333333);
}
$r = (int) round($r * 255);
$g = (int) round($g * 255);
$b = (int) round($b * 255);
return $r . ',' . $g . ',' . $b;
}
public static function hexToHsl(string $hexColor): string
{
$rgbArray = self::hexToRgb($hexColor);
$rgbArray = explode(',', $rgbArray);
return self::rgbToHsl($rgbArray);
}
public static function hslToHex(array $hslArray): string
{
$rgbArray = self::hslToRgb($hslArray);
$rgbArray = explode(',', $rgbArray);
return self::rgbToHex($rgbArray);
}
public static function assetLinkDetermine(string $src, bool $isImage = true): string
{
if (strpos($src, 'http://') !== false || strpos($src, 'https://') !== false) {
if (defined('APP_URI') && strpos($src, APP_URI) === false) {
return $src;
}
}
$path = parse_url($src, PHP_URL_PATH);
if ($path) {
$src = $path;
}
$cleanSrc = ltrim($src, '/');
if (empty($cleanSrc)) {
return '';
}
$asset_src = '';
if ($isImage) {
$info = pathinfo($cleanSrc);
$directory = $info['dirname'];
if ($directory === '.') {
$directory = '';
}
if ($directory) {
$directory = trim($directory, '/') . '/';
}
else {
$directory = '/';
}
$asset_src = Utility::image_link_determiner($info['basename'], $directory);
}
else {
$asset_src = '/' . $cleanSrc;
}
return $asset_src;
}
public function get_css_url(): string
{
return Controllers::$init->CRLink('templates/website/' . $this->name . '/css/fononline.min.css', false, 'none') . '?version=' . License::get_version();
}
public static function getHeaderMenu(array $list = [], bool $children = false, array $opt = [], int $childCount = 0): string
{
$menuFontSize = Config::get('theme/fonts/menu/size');
$menuFontWeight = Config::get('theme/fonts/menu/weight');
$mobile = isset($opt['mobile']) && $opt['mobile'];
$output = '';
if ($children) {
$output .= '<ul class="' . (0 < $childCount ? 'child-' . $childCount : '') . ' ' . ($mobile ? 'inner' : '') . '">';
}
$i = $childCount;
foreach ($list as $menu) {
$mega = false;
$tag = false;
if (isset($menu['extra']['mega']['header_' . $opt['header_type']])) {
$mega = $menu['extra']['mega']['header_' . $opt['header_type']];
}
if (isset($menu['extra']['tag'])) {
$tag = $menu['extra']['tag'];
}
$menuClass = '';
$menuWidth = '';
if (!$children) {
if ($mega) {
$menuClass = 'megamenuli';
if ($menu['icon']) {
if (!str_contains($menu['icon'], 'fa-')) {
if ($menu['icon'] == 'full') {
$menuClass .= ' full-width';
}
else {
$menuClass .= ' position-relative';
$menuWidth = $menu['icon'] . 'px';
}
}
}
}
else if ($menu['children']) {
$menuClass = 'flatmenuli';
}
}
if ($menu['children'] || $mega) {
$menu['link'] = 'javascript:void 0;';
}
$output .= '<li class="nav-item ' . $menuClass . ' ' . ($menu['children'] || $mega ? 'has-child' : '') . '">';
$output .= '<a href="' . $menu['link'] . '" ' . ($menu['target'] ? ' target="_blank"' : '') . ' class="nav-link ' . ($mobile && $menu['children'] || $mega ? 'toggle' : '') . '" style="font-size:' . $menuFontSize . 'px;font-weight:' . $menuFontWeight . ';">';
if ($tag) {
$output .= '<span class="menu_tag" ' . ($tag['color'] != '' ? 'style="--menu-tag-background:' . $tag['color'] . ';"' : '') . '>' . self::getPriceHolders($tag['name']) . '</span>';
}
$output .= (isset($opt['span']) ? '<span class="menu-title">' : '');
$output .= ($menu['icon'] && !$menuWidth ? '<i class="' . $menu['icon'] . '" aria-hidden="true"></i> ' : '');
$output .= $menu['title'];
$output .= (isset($opt['span']) ? '</span>' : '');
$output .= ($menu['children'] || $mega ? ' <i class="fa-solid fa-angle-down"></i>' : '');
$output .= '</a>';
if (!$children && $mega) {
$output .= '<div class="megamenu-container ' . ($mobile ? 'inner' : '') . ' ' . ($menuWidth ? 'has-width' : '') . '" ' . ($menuWidth ? 'style="width:' . $menuWidth . '; left:50%; transform:translateX(-' . ($menu['icon'] / 2) . 'px)"' : '') . '>';
$output .= '<div class="container">';
$output .= '<ul class="megamenu p-0">';
$mega = self::getPriceHolders($mega);
$output .= Utility::text_replace($mega, ['{SITE_URL}' => APP_URI . '/', '{TEMPLATE_URL}' => $opt['template_address']]);
$output .= '</ul>';
$output .= '</div>';
$output .= '</div>';
}
if ($menu['children'] && !$mega) {
++$i;
$output .= static::getHeaderMenu($menu['children'], true, $opt, $i);
}
$output .= '</li>' . PHP_EOL;
}
$output .= ($children ? '</ul>' . PHP_EOL : '');
return $output;
}
public static function getFooterMenu(array $list = [], bool $children = false, array $opt = []): string
{
$footerMenu = '';
foreach ($list as $menu) {
if (!$children) {
$footerMenu .= '<div class="col footer-menu-links">';
$footerMenu .= '<div class="dropdown">';
}
else {
$footerMenu .= '<li>';
}
$footerMenu .= '<a';
$footerMenu .= (!$children ? ' class="dropdown-toggle" role="button" data-bs-toggle="dropdown" ' : ' class="dropdown-item" ');
if ($menu['link'] != '') {
$footerMenu .= ' href="' . $menu['link'] . '"';
$footerMenu .= ($menu['target'] ? ' target="_blank"' : '');
}
$footerMenu .= '>';
$footerMenu .= (!$children ? '<h3 class="footer-menu-header">' : '');
$footerMenu .= (!empty($menu['icon']) ? '<i class="' . $menu['icon'] . '" aria-hidden="true"></i>' : '');
$footerMenu .= $menu['title'];
$footerMenu .= (!$children ? '</h3>' : '');
$footerMenu .= '</a>';
if ($children) {
$footerMenu .= '</li>';
}
if ($menu['children']) {
$footerMenu .= '<ul class="dropdown-menu footer-menu-list mb-4 mb-lg-0">';
$footerMenu .= static::getFooterMenu($menu['children'], true, $opt);
$footerMenu .= '</ul>';
}
if (!$children) {
$footerMenu .= '</div>';
$footerMenu .= '</div>';
}
}
return $footerMenu;
}
public static function getClientAreaMenu(array $list = [], bool $children = false, array $opt = []): string
{
$pname = $opt['pname'] ?? '';
$gtype = $opt['gtype'] ?? '';
$acheader_info = $opt['acheader_info'] ?? '';
$menu_links = $opt['menu_links'] ?? '';
$visibility_ticket = $opt['visibility_ticket'] ?? '';
$visibility_invoice = $opt['visibility_invoice'] ?? '';
$domain_total = $opt['domain_total'] ?? 0;
$software_total = $opt['software_total'] ?? 0;
$sms_total = $opt['sms_total'] ?? 0;
$hosting_total = $opt['hosting_total'] ?? 0;
$server_total = $opt['server_total'] ?? 0;
$special_total = $opt['special_total'] ?? 0;
$special_list = $opt['special_list'] ?? [];
$category = $opt['category'] ?? [];
$ul_active = (isset($opt['active']) ? $opt['active'] : false);
$pagebuilder = $opt['pagebuilder'] ?? false;
$output = '';
if ($children) {
$output .= '<ul';
$output .= ' class="inner list-group list-group-flush ' . ($ul_active ? ' show' : '') . '"';
if ($ul_active) {
$output .= ' style="display:block;"';
}
$output .= '>';
}
foreach ($list as $menu) {
if ($menu['id'] == 'FonPageBuilder') {
continue;
}
if (($menu['page'] == 'ca-tickets') && !$visibility_ticket) {
continue;
}
if (($menu['page'] == 'ca-invoices') && !$visibility_invoice) {
continue;
}
if ($menu['onlyCa'] && !$acheader_info) {
continue;
}
if (($menu['page'] == 'create-account') && $acheader_info) {
continue;
}
if (($menu['page'] == 'login-account') && $acheader_info) {
continue;
}
if (($menu['page'] == 'product-group/domain') && !Config::get('options/pg-activation/domain')) {
continue;
}
if (($menu['page'] == 'product-group/hosting') && !Config::get('options/pg-activation/hosting')) {
continue;
}
if (($menu['page'] == 'product-group/server') && !Config::get('options/pg-activation/server')) {
continue;
}
if (($menu['page'] == 'product-group/software') && !Config::get('options/pg-activation/software')) {
continue;
}
if (($menu['page'] == 'product-group/sms') && !Config::get('options/pg-activation/sms')) {
continue;
}
if ((($menu['page'] == 'product-group/international-sms') || $menu['page'] == 'ca-intl-sms') && !Config::get('options/pg-activation/international-sms')) {
continue;
}
if (($menu['page'] == 'ca-affiliate') && !Config::get('options/affiliate/status')) {
continue;
}
if (($menu['page'] == 'ca-reseller') && !Config::get('options/dealership/status')) {
continue;
}
if (($menu['page'] == 'ca-reseller') && !Config::get('options/dealership/view-without-membership') && isset($acheader_info['dealership']['status']) && $acheader_info['dealership']['status'] == 'inactive') {
continue;
}
if (($menu['page'] == 'ca-domains') && !Config::get('options/pg-activation/domain') && $domain_total < 1) {
continue;
}
if (($menu['page'] == 'ca-orders') && !$menu['children']) {
if (0 < $hosting_total) {
$menu['children'][] = [
'id' => 'hosting',
'parent' => $menu['id'],
'icon' => '',
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'ca-order-group',
'onlyCa' => 1,
'link' => $menu_links['menu-2-2'],
'title' => __('website/account/sidebar-menu-2-sub-hosting'),
'children' => []
];
}
if (0 < $server_total) {
$menu['children'][] = [
'id' => 'server',
'parent' => $menu['id'],
'icon' => '',
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'ca-order-group',
'onlyCa' => 1,
'link' => $menu_links['menu-2-3'],
'title' => __('website/account/sidebar-menu-2-sub-server'),
'children' => []
];
}
if (0 < $software_total) {
$menu['children'][] = [
'id' => 'software',
'parent' => $menu['id'],
'icon' => '',
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'ca-order-group',
'onlyCa' => 1,
'link' => $menu_links['menu-2-0'],
'title' => __('website/account/sidebar-menu-2-sub-software'),
'children' => []
];
}
if (0 < $sms_total) {
$menu['children'][] = [
'id' => 'sms',
'parent' => $menu['id'],
'icon' => '',
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'ca-order-group',
'onlyCa' => 1,
'link' => $menu_links['menu-2-1'],
'title' => __('website/account/sidebar-menu-2-sub-sms'),
'children' => []
];
}
if ((0 < $special_total) && $special_list) {
foreach ($special_list as $group) {
if ($group['parent'] != 0) {
continue;
}
$menu['children'][] = [
'id' => 'special-' . $group['id'],
'parent' => $menu['id'],
'icon' => '',
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'ca-order-group',
'onlyCa' => 1,
'link' => $menu_links['menu-2-4'] . '?category=' . $group['id'],
'title' => $group['name'],
'children' => []
];
}
}
}
else if (($menu['page'] == 'ca-addons') && !$menu['children']) {
$addons = Modules::Load('Addons', 'All', true, true);
if ($addons) {
$addon_menus = [];
foreach ($addons as $k => $v) {
if (!isset($v['config']['show_on_clientArea']) || !$v['config']['show_on_clientArea']) {
continue;
}
$addon_menus[] = [
'id' => $k,
'parent' => 0,
'icon' => $menu['icon'],
'rank' => 0,
'target' => 0,
'status' => 'active',
'page' => 'addon',
'onlyCa' => 1,
'link' => Utility::link_determiner('addon/' . $k . '/client'),
'title' => $v['lang']['meta']['name'],
'children' => []
];
}
if ($addon_menus) {
$output .= self::getClientAreaMenu($addon_menus, false, $opt);
}
}
continue;
}
$active = false;
if ((($pname == 'account_dashboard') && $menu['page'] == 'ca-dashboard') || ($pname == 'account_tickets') && $menu['page'] == 'ca-tickets' || ($pname == 'account_products') && $gtype == 'domain' && $menu['page'] == 'ca-domains' || ($pname == 'account_products') && $gtype != 'domain' && $menu['page'] == 'ca-orders' || ($pname == 'account_sms') && $menu['page'] == 'ca-intl-sms' || ($pname == 'account_invoices') && $menu['page'] == 'ca-invoices' || ($pname == 'account_info') && $menu['page'] == 'ca-ac-information' || ($pname == 'account_messages') && $menu['page'] == 'ca-messages' || ($menu['page'] == 'ca-order-group') && $category && ('special-' . $category['id']) == $menu['id'] || ($menu['page'] == 'ca-order-group') && $gtype == $menu['id'] || ($menu['page'] == 'addon') && $pname == $menu['id'] || ($menu['page'] == 'ca-affiliate') && $pname == 'affiliate' || ($menu['page'] == 'ca-reseller') && $pname == 'reseller') {
$active = true;
}
if ($menu['children']) {
$menu['link'] = 'javascript:void 0;';
}
$output .= '<li class="list-group-item ' . ($children ? 'py-0 px-3' : 'p-0');
if (stristr($menu['icon'], 'shopping-cart')) {
$output .= ' neworderbtn';
}
$output .= '">';
$output .= '<a href="' . $menu['link'] . '"';
if ($menu['target']) {
$output .= ' target="_blank"';
}
$output .= ' class="toggle d-flex align-items-center justify-content-between py-2"';
if ($active) {
$output .= ' data-id="active"';
}
$output .= '>';
$output .= '<span>';
$output .= ($menu['icon'] ? '<i class="' . $menu['icon'] . ' rounded bg-theme-light p-2 fa-fw" aria-hidden="true" style="width: 30px;height:30px"></i> ' : '');
$output .= (!$menu['icon'] && $children ? '<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i> ' : '');
$output .= $menu['title'];
$output .= '</span>';
if ($menu['children']) {
$output .= '<i class="fa-solid fa-angle-down"></i>';
}
$output .= '</a>';
if ($menu['children']) {
$_opt = $opt;
$_opt['active'] = $active;
$output .= self::getClientAreaMenu($menu['children'], true, $_opt);
}
$output .= '</li>' . PHP_EOL;
}
$output .= ($children ? '</ul>' . PHP_EOL : '');
return $output;
}
public static function getThemeCustomStyles(): string
{
$configFonts = Config::get('theme/fonts');
$themeFonts = [];
$themeColors = self::getThemeColors();
$fontSelectors = ['body', 'menu', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'custom'];
$output = '';
$baseFontSize = $configFonts['body']['size'] ?? 16;
if ($configFonts) {
if ($configFonts['source'] == 'google') {
$fontHost = $configFonts['host'] ?? 'cloud';
foreach ($configFonts as $fontKey => $themeFont) {
if (in_array($fontKey, $fontSelectors)) {
if (($fontKey == 'custom') && !$themeFont['selectors']) {
continue;
}
$themeFonts[] = $themeFont['family'] . ':' . $themeFont['variants'];
}
}
if ($themeFonts) {
$themeFonts = array_unique($themeFonts);
$cssFilePath = self::downloadGoogleFont($themeFonts, $fontHost);
if ($cssFilePath) {
if ($fontHost == 'cloud') {
$output .= '<link rel="preconnect" href="https://fonts.googleapis.com">';
$output .= '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';
$output .= '<link rel="dns-prefetch" href="https://fonts.gstatic.com">';
}
$output .= '<link href="' . $cssFilePath . '" rel="stylesheet" media="print" onload="this.media=\'all\'">' . PHP_EOL;
$output .= '<noscript><link href="' . $cssFilePath . '" rel="stylesheet"></noscript>' . PHP_EOL;
}
}
}
else if ($configFonts['local']) {
$cssFiles = explode(',', $configFonts['local']);
foreach ($cssFiles as $cssFile) {
$output .= '<link href="' . trim($cssFile) . '" rel="stylesheet" media="print" onload="this.media=\'all\'">' . PHP_EOL;
$output .= '<noscript><link href="' . trim($cssFile) . '" rel="stylesheet"></noscript>' . PHP_EOL;
}
}
}
$output .= '<style>';
$output .= 'html {';
$output .= 'font-size:' . $configFonts['body']['size'] . 'px;';
$output .= '}';
$output .= ':root {';
$output .= '--theme-primary: #' . $themeColors['theme-primary']['color'] . ';';
$output .= '--theme-primary-rgb : ' . $themeColors['theme-primary']['rgb'] . ';';
$output .= '--theme-primary-hsl : ' . $themeColors['theme-primary']['hsl'] . ';';
$output .= '--theme-secondary: #' . $themeColors['theme-secondary']['color'] . ';';
$output .= '--theme-secondary-rgb : ' . $themeColors['theme-secondary']['rgb'] . ';';
$output .= '--theme-secondary-hsl : ' . $themeColors['theme-secondary']['hsl'] . ';';
$output .= '--text-color: #' . $themeColors['text-color']['color'] . ';';
$output .= '--text-color-rgb: ' . $themeColors['text-color']['rgb'] . ';';
$output .= '--text-color-hsl: ' . $themeColors['text-color']['hsl'] . ';';
$output .= '--link-color: #' . $themeColors['link-color']['color'] . ';';
$output .= '--link-color-rgb: ' . $themeColors['link-color']['rgb'] . ';';
$output .= '--link-color-hsl: ' . $themeColors['link-color']['hsl'] . ';';
$output .= '--link-color-hover: #' . $themeColors['link-color-hover']['color'] . ';';
$output .= '--link-color-hover-rgb: ' . $themeColors['link-color-hover']['rgb'] . ';';
$output .= '--link-color-hover-hsl: ' . $themeColors['link-color-hover']['hsl'] . ';';
$output .= '--link-color-active: #' . $themeColors['link-color-active']['color'] . ';';
$output .= '--link-color-active-rgb: ' . $themeColors['link-color-active']['rgb'] . ';';
$output .= '--link-color-active-hsl: ' . $themeColors['link-color-active']['hsl'] . ';';
if ($configFonts['source'] == 'google') {
$output .= '--body-font-family:"' . $configFonts['body']['family'] . '", ' . $configFonts['body']['category'] . ';';
$output .= '--body-font-weight:' . $configFonts['body']['weight'] . ';';
$output .= '--menu-font-family:"' . $configFonts['menu']['family'] . '", ' . $configFonts['menu']['category'] . ';';
$output .= '--menu-font-weight:' . $configFonts['menu']['weight'] . ';';
$output .= '--h1-font-family:"' . $configFonts['h1']['family'] . '", ' . $configFonts['h1']['category'] . ';';
$output .= '--h1-font-weight:' . $configFonts['h1']['weight'] . ';';
$output .= '--h2-font-family:"' . $configFonts['h2']['family'] . '", ' . $configFonts['h2']['category'] . ';';
$output .= '--h2-font-weight:' . $configFonts['h2']['weight'] . ';';
$output .= '--h3-font-family:"' . $configFonts['h3']['family'] . '", ' . $configFonts['h3']['category'] . ';';
$output .= '--h3-font-weight:' . $configFonts['h3']['weight'] . ';';
$output .= '--h4-font-family:"' . $configFonts['h4']['family'] . '", ' . $configFonts['h4']['category'] . ';';
$output .= '--h4-font-weight:' . $configFonts['h4']['weight'] . ';';
$output .= '--h5-font-family:"' . $configFonts['h5']['family'] . '", ' . $configFonts['h5']['category'] . ';';
$output .= '--h5-font-weight:' . $configFonts['h5']['weight'] . ';';
$output .= '--h6-font-family:"' . $configFonts['h6']['family'] . '", ' . $configFonts['h6']['category'] . ';';
$output .= '--h6-font-weight:' . $configFonts['h6']['weight'] . ';';
}
$output .= '--body-font-size:' . round($configFonts['body']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--menu-font-size:' . round($configFonts['menu']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h1-font-size:' . round($configFonts['h1']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h2-font-size:' . round($configFonts['h2']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h3-font-size:' . round($configFonts['h3']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h4-font-size:' . round($configFonts['h4']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h5-font-size:' . round($configFonts['h5']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '--h6-font-size:' . round($configFonts['h6']['size'] / $baseFontSize, 2) . 'rem;';
$output .= '}';
if (($configFonts['source'] == 'google') && isset($configFonts['custom']['selector']) && $configFonts['custom']['selector']) {
$output .= $configFonts['custom']['selector'] . '{';
if ($configFonts['custom']['family']) {
$output .= 'font-family:"' . $configFonts['custom']['family'] . '", ' . $configFonts['custom']['category'] . ';';
$output .= 'font-size:' . round($configFonts['custom']['size'] / $baseFontSize, 2) . 'rem;';
$output .= 'font-weight:' . $configFonts['custom']['weight'] . ';';
}
$output .= '}';
}
$output .= '</style>';
return $output;
}
private static function downloadGoogleFont(array $fonts, string $host = 'cloud'): string
{
$outputDir = View::$init->get_template_dir() . 'fonts/google-fonts';
$outputLink = View::$init->get_template_url() . Config::get('theme/name') . '/fonts/google-fonts';
if ($host != 'cloud') {
if (!is_dir($outputDir)) {
mkdir($outputDir, 511, true);
}
}
$fontName = [];
$fontUrl = [];
foreach ($fonts as $font) {
list($name, $variants) = explode(':', $font);
$fontName[] = strtolower(str_replace(' ', '_', $name));
$variants = str_replace(',', ';', $variants);
$fontUrl[] = 'family=' . urlencode($name) . ':wght@' . $variants;
}
$sanitizedFontFamily = implode('_', $fontName);
$fontUrl = implode('&', $fontUrl);
$cssFilePath = $outputDir . '/' . $sanitizedFontFamily . '.css';
$cssFileLink = $outputLink . '/' . $sanitizedFontFamily . '.css';
if ($host != 'cloud') {
if (file_exists($cssFilePath)) {
return $cssFileLink;
}
}
$fontUrl = 'https://fonts.googleapis.com/css2?' . $fontUrl . '&display=swap';
if ($host == 'cloud') {
return $fontUrl;
}
$cssContent = file_get_contents($fontUrl);
if (!$cssContent) {
Modules::save_log('Addons', 'FonPageBuilder', 'themeDownloadGoogleFont', $fontUrl, $cssContent, '');
return '';
}
preg_match_all('/url\\((https:\\/\\/fonts\\.gstatic\\.com\\/s\\/[^)]+)\\)/', $cssContent, $matches);
foreach ($matches[1] as $fontFileUrl) {
$filePath = $outputDir . '/' . basename($fontFileUrl);
if (!file_exists($filePath)) {
file_put_contents($filePath, file_get_contents($fontFileUrl));
}
$cssContent = str_replace($fontFileUrl, basename($fontFileUrl), $cssContent);
}
file_put_contents($cssFilePath, $cssContent);
return $cssFileLink;
}
private static function getThemeColors(): array
{
$themePrimary = Config::get('theme/color1');
$themeSecondary = Config::get('theme/color2');
$themeTextColor = Config::get('theme/text-color');
$themeLinkColor = Config::get('theme/link_color');
$themeLinkColorHover = Config::get('theme/link_color_hover');
$themeLinkColorActive = Config::get('theme/link_color_active');
$themeColors = [
'theme-primary' => ['color' => $themePrimary, 'rgb' => self::hexToRgb($themePrimary), 'hsl' => self::hexToHsl($themePrimary)],
'theme-secondary' => ['color' => $themeSecondary, 'rgb' => self::hexToRgb($themeSecondary), 'hsl' => self::hexToHsl($themeSecondary)],
'text-color' => ['color' => $themeTextColor, 'rgb' => self::hexToRgb($themeTextColor), 'hsl' => self::hexToHsl($themeTextColor)],
'link-color' => ['color' => $themeLinkColor, 'rgb' => self::hexToRgb($themeLinkColor), 'hsl' => self::hexToHsl($themeLinkColor)],
'link-color-hover' => ['color' => $themeLinkColorHover, 'rgb' => self::hexToRgb($themeLinkColorHover), 'hsl' => self::hexToHsl($themeLinkColorHover)],
'link-color-active' => ['color' => $themeLinkColorActive, 'rgb' => self::hexToRgb($themeLinkColorActive), 'hsl' => self::hexToHsl($themeLinkColorActive)]
];
return $themeColors;
}
public static function getRandomColors(): string
{
$colors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A6', '#33FFF6', '#5733FF', '#FF8C33', '#33FF8C', '#FF3333', '#33A1FF', '#FF9933', '#33FF99', '#FF33FF', '#FF6633', '#CC33FF', '#FF33CC', '#FFB533', '#640D5F', '#D91656', '#EE66A6', '#FF6600', '#4379F2', '#117554', '#624E88', '#C96868', '#16423C', '#161D6F', '#C7253E', '#7A1CAC', '#4E31AA', '#921A40', '#FF8225', '#36C2CE', '#F4CE14', '#1679AB', '#C80036', '#AF47D2', '#C738BD', '#D8AE7E', 'var(--theme-primary)', 'var(--theme-secondary)', 'var(--text-color)', 'var(--link-color)', 'var(--link-color-hover)', 'var(--link-color-active)'];
return $colors[array_rand($colors)];
}
public function addHeroStyle(array $pageData, array $hero, string $section_id): void
{
if ($hero && $section_id != '') {
$heroStyle = '';
$heroStyle .= $section_id . '{';
if (isset($hero['background']) && $hero['background']) {
if ($hero['background']['type'] == 'image') {
$heroStyle .= ($hero['background']['image'] ? 'background-image:url(' . self::assetLinkDetermine($hero['background']['image']) . ')!important;' : '');
$heroStyle .= ($hero['background']['position'] ? 'background-position:' . $hero['background']['position'] . '!important;' : '');
$heroStyle .= ($hero['background']['size'] ? 'background-size:' . $hero['background']['size'] . '!important;' : '');
$heroStyle .= ($hero['background']['repeat'] ? 'background-repeat:' . $hero['background']['repeat'] . '!important;' : '');
$heroStyle .= ($hero['background']['attachment'] ? 'background-attachment:' . $hero['background']['attachment'] . '!important;' : '');
$heroStyle .= ($hero['background']['color'] ? 'background-color:' . $hero['background']['color'] . '!important;' : '');
}
else if ($hero['background']['type'] == 'gradient') {
$heroStyle .= ($hero['background']['gradient']['final'] ? 'background-image:' . $hero['background']['gradient']['final'] . '!important;' : '');
}
else if ($hero['background']['type'] == 'color') {
$heroStyle .= ($hero['background']['color'] ? 'background-color:' . $hero['background']['color'] . '!important;' : '');
}
}
$heroStyle .= ($hero['padding'] ? 'padding:' . $hero['padding'] . ';' : '');
$heroStyle .= '}';
$heroStyle .= $section_id . ' .fon-hero-content{';
$heroStyle .= ($hero['text_color'] ? 'color:' . $hero['text_color'] . ';' : '');
$heroStyle .= '}';
if (isset($hero['heading_color']) && $hero['heading_color'] != '') {
$heroStyle .= $section_id . ' .fon-hero-content h1 ,' . $section_id . ' .fon-hero-content h2,' . $section_id . ' .fon-hero-content h3,' . $section_id . ' h4,' . $section_id . ' .fon-hero-content h5,' . $section_id . ' .fon-hero-content h6{color:' . $hero['heading_color'] . '!important;}';
}
if (isset($hero['link_color']) && $hero['link_color'] != '') {
$heroStyle .= $section_id . '.fon-hero-content a:not(.btn){color:' . $hero['link_color'] . '!important;}';
}
if (isset($hero['link_hover_color']) && $hero['link_hover_color'] != '') {
$heroStyle .= $section_id . ' .fon-hero-content a:not(.btn):hover{color:' . $hero['link_hover_color'] . '!important;}';
}
if (isset($hero['overlay']) && $hero['overlay']) {
if (($hero['overlay']['type'] == 'solid') && $hero['overlay']['color']) {
$heroStyle .= $section_id . ' .fon-background-overlay{background-color:' . $hero['overlay']['color'] . ';}';
}
else if (($hero['overlay']['type'] == 'gradient') && $hero['overlay']['gradient']['final']) {
$heroStyle .= $section_id . ' .fon-background-overlay{background-image:' . $hero['overlay']['gradient']['final'] . ';}';
}
}
}
if ($heroStyle) {
$this->addStyle($pageData['page'], $heroStyle);
}
}
public static function generateColumnDisplayClassess(object $col): string
{
$columnStyle = '';
$hiddenClass = [];
if (isset($col->xl_col_display) && $col->xl_col_display) {
$hiddenClass[] = $col->xl_col_display;
}
if (isset($col->lg_col_display) && $col->lg_col_display) {
$hiddenClass[] = $col->lg_col_display;
}
if (isset($col->md_col_display) && $col->md_col_display) {
$hiddenClass[] = $col->md_col_display;
}
if (isset($col->sm_col_display) && $col->sm_col_display) {
$hiddenClass[] = $col->sm_col_display;
}
if (isset($col->xs_col_display) && $col->xs_col_display) {
$hiddenClass[] = $col->xs_col_display;
}
$orderClass = [];
if (isset($col->xl_col_order) && $col->xl_col_order != '') {
$orderClass[] = 'order-xl-' . $col->xl_col_order;
}
if (isset($col->lg_col_order) && $col->lg_col_order != '') {
$orderClass[] = 'order-lg-' . $col->lg_col_order;
}
if (isset($col->md_col_order) && $col->md_col_order != '') {
$orderClass[] = 'order-md-' . $col->md_col_order;
}
if (isset($col->sm_col_order) && $col->sm_col_order != '') {
$orderClass[] = 'order-sm-' . $col->sm_col_order;
}
if (isset($col->xs_col_order) && $col->xs_col_order != '') {
$orderClass[] = 'order-' . $col->xs_col_order;
}
$columnStyle = implode(' ', array_merge($hiddenClass, $orderClass));
return $columnStyle;
}
public function getPreloader(string $logo, string $favicon, string $url): string
{
$sitePreloader = Config::get('theme/site_preloader');
$sitePreloaderBg = Config::get('theme/site_preloader_bg');
if ($sitePreloader == 'site-logo') {
$preloader_image = $logo;
}
else if ($sitePreloader == 'site-favicon') {
$preloader_image = $favicon;
}
else {
$preloader_image = $url . 'images/svg-loaders/' . $sitePreloader . '.svg';
}
$preloader = '<div id="site-preloader" class="loader ' . $sitePreloader . '" style="--fon-preloader-bg:#' . $sitePreloaderBg . '"><div class="align-items-center d-flex flex-column justify-content-center"><img src="' . $preloader_image . '" alt="Preloader" class="' . ($sitePreloader === 'site-logo' ? 'animated pulse infinite' : '') . '"/><p class="mt-3">' . $this->language['preloader_text'] . '</p></div></div>';
return $preloader;
}
public static function isRecaptcha(object $captcha): bool
{
if (isset($captcha->module->config) && $captcha->module->config && isset($captcha->module->config['site-key']) && $captcha->module->config['site-key']) {
return true;
}
return false;
}
private static function getTldList(string $names = ''): array
{
$query = Models::$init->db->select()->from('tldlist AS t');
if ($names) {
$query->where('t.name', 'IN (\'' . $names . '\')', '', '&&');
}
$query->where('t.status', '=', 'active');
$query->order_by('t.rank ASC');
$tlds = ($query->build() ? $query->fetch_assoc() : []);
if ($tlds) {
foreach ($tlds as $key => $tld) {
$tlds[$key]['reg_price'] = self::getTldPrices($tld['id'], 'register');
$tlds[$key]['ren_price'] = self::getTldPrices($tld['id'], 'renewal');
$tlds[$key]['tra_price'] = self::getTldPrices($tld['id'], 'transfer');
}
}
return $tlds;
}
public static function isMobile(): bool
{
$useragent = $_SERVER['HTTP_USER_AGENT'];
$isMobile = preg_match('/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i', $useragent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i', substr($useragent, 0, 4));
return $isMobile;
}
public static function getPriceHolders(string $text): string
{
$pattern = '/\\{\\{(domain|hosting|server|software|sms|special):([\\w.]+)(?::(register|transfer|renewal))?\\}\\}/';
$codePrice = preg_replace_callback($pattern, function($matches) {
$urunGrubu = $matches[1];
$urunId = $matches[2];
$priceType = $matches[3] ?? NULL;
if ($urunGrubu === 'domain') {
$domain_override_uscurrency = Config::get('options/domain-override-user-currency');
$query = Models::$init->db->select('p.*, t.name, t.promo_status, t.promo_register_price, t.promo_transfer_price, t.promo_duedate')->from('prices AS p');
$query->join('LEFT', 'tldlist AS t', 't.id=p.owner_id');
$query->where('p.type', '=', $priceType, '&&');
$query->where('p.owner', '=', 'tld', '&&');
$query->where('t.name', '=', $urunId);
$query->order_by('p.rank ASC');
$price = ($query->build() ? $query->getAssoc() : false);
if ($price) {
if ($priceType != 'renewal') {
if ($price['promo_status'] && (substr($price['promo_duedate'], 0, 4) == '1881') || DateManager::strtotime() < DateManager::strtotime($price['promo_duedate'] . ' 23:59:59') && 0 < $price['promo_' . $priceType . '_price']) {
$price['amount'] = $price['promo_' . $priceType . '_price'];
}
}
$rawPrice = self::calculatePrices([$price], self::getCurrencySymbols(), $domain_override_uscurrency, $urunGrubu);
$price = $rawPrice['price'];
}
}
else if ($urunGrubu === 'software') {
$query = Models::$init->db->select('p.*, s.override_usrcurrency')->from('prices AS p');
$query->join('LEFT', 'pages AS s', 's.id=p.owner_id');
$query->where('p.owner', '=', 'softwares', '&&');
$query->where('p.owner_id', '=', $urunId);
$query->order_by('p.rank ASC');
$query->limit('1');
$price = ($query->build() ? $query->getAssoc() : false);
if ($price) {
$rawPrice = self::calculatePrices([$price], self::getCurrencySymbols(), $price['override_usrcurrency'], $urunGrubu);
$price = $rawPrice['price'];
}
}
else {
$query = Models::$init->db->select('p.*, pr.override_usrcurrency')->from('prices AS p');
$query->join('LEFT', 'products AS pr', 'pr.id=p.owner_id');
$query->where('pr.type', '=', $urunGrubu, '&&');
$query->where('p.owner', '=', 'products', '&&');
$query->where('p.owner_id', '=', $urunId);
$query->order_by('p.rank ASC');
$query->limit('1');
$price = ($query->build() ? $query->getAssoc() : false);
if ($price) {
$rawPrice = self::calculatePrices([$price], self::getCurrencySymbols(), $price['override_usrcurrency'], $urunGrubu);
$price = $rawPrice['price'];
}
}
if ($price === false) {
return $matches[0];
}
return strip_tags($price);
}, $text);
return $codePrice;
}
private function checkAndUpdateVersion(): void
{
$themeConfig = $this->config;
$versionFile = TEMPLATE_DIR . 'website' . DS . $themeConfig['meta']['name'] . DS . 'VERSION';
$updateFile = TEMPLATE_DIR . 'website' . DS . $themeConfig['meta']['name'] . DS . 'UPDATE';
if (!file_exists($versionFile)) {
return;
}
$versionFileContent = trim(file_get_contents($versionFile));
if (!$versionFileContent) {
return;
}
$currentVersion = $themeConfig['meta']['version'] ?? NULL;
if (version_compare($versionFileContent, $currentVersion, '>')) {
$themeConfig['meta']['version'] = $versionFileContent;
if (file_exists($updateFile)) {
FileManager::file_delete($updateFile);
}
$this->ensureKeyExists($themeConfig, [
['key' => 'wisecpverion', 'value' => '3.1.9.7', 'parent' => 'meta', 'overwrite' => true],
['key' => 'enable_lazy_loading', 'value' => true, 'parent' => 'settings', 'overwrite' => false],
['key' => 'google_analytics_id', 'value' => '', 'parent' => 'settings', 'overwrite' => false],
['key' => 'google_ads_id', 'value' => '', 'parent' => 'settings', 'overwrite' => false],
['key' => 'google_conversion_id', 'value' => '', 'parent' => 'settings', 'overwrite' => false],
['key' => 'facebook_pixel_id', 'value' => '', 'parent' => 'settings', 'overwrite' => false],
['key' => 'google_tm_id', 'value' => '', 'parent' => 'settings', 'overwrite' => false],
['key' => 'fb_pixel_via_gtm', 'value' => false, 'parent' => 'settings', 'overwrite' => false]
]);
$this->migratePreviewImagesToCDN($themeConfig);
$configDir = TEMPLATE_DIR . 'website' . DS . $themeConfig['meta']['name'] . DS;
$export = Utility::array_export($themeConfig, ['pwith' => true]);
FileManager::file_write($configDir . 'theme-config.php', $export);
$this->_clearFonBuilderCache();
}
}
private function ensureKeyExists(array &$config, array $options = []): void
{
if (!empty($options)) {
foreach ($options as $option) {
$key = $option['key'] ?? '';
$value = $option['value'] ?? NULL;
$parent = $option['parent'] ?? '';
$forceUpdate = isset($option['overwrite']) && $option['overwrite'] === true;
if ($key === '') {
continue;
}
if ($parent !== '') {
if (!isset($config[$parent]) || !is_array($config[$parent])) {
$config[$parent] = [];
}
if (!array_key_exists($key, $config[$parent]) || $forceUpdate) {
$config[$parent][$key] = $value;
}
}
else if (!array_key_exists($key, $config) || $forceUpdate) {
$config[$key] = $value;
}
}
}
}
private function migratePreviewImagesToCDN(array &$config): bool
{
$search = 'https://fonwise.com/documentation/images/';
$replace = 'https://cdn.jsdelivr.net/gh/Fononline/documentation-assets/';
$targetKeys = ['package_styles', 'accordion_styles', 'animated_number_styles', 'articles_styles', 'banner_styles', 'campaign_styles', 'contentbox_styles', 'domain_tlds_styles', 'featurebox_styles', 'news_styles', 'references_styles', 'software_styles', 'tabs_styles', 'team_styles', 'testimonial_styles', 'timeline_styles'];
$hasChanges = false;
foreach ($targetKeys as $section) {
if (isset($config[$section]) && is_array($config[$section])) {
foreach ($config[$section] as $key => $value) {
if (is_string($value) && strpos($value, $search) !== false) {
$config[$section][$key] = str_replace($search, $replace, $value);
$hasChanges = true;
}
}
}
}
return $hasChanges;
}
public static function getLazyPlaceholder(): string
{
$lazyPlaceholder = static::assetLinkDetermine('templates/website/Datawise/builder/image/lazy-placeholder.svg');
return $lazyPlaceholder;
}
public static function getDueDateWarning(string $dueDate, array $language, string $status): string
{
if (!$dueDate || $dueDate == '1970') {
return '';
}
$dueDateObj = new DateTime($dueDate);
$today = new DateTime();
$interval = $today->diff($dueDateObj);
$daysLeft = (int) $interval->format('%r%a');
if (($daysLeft <= 60) && $status == 'active') {
return ' <i class="fa-solid fa-bell fa-shake text-danger" title="' . $language['duedate_warning'] . '"></i>';
}
return '';
}
public static function getBCPLocale(string $lang): string
{
$localeMap = ['af' => 'af-ZA', 'am' => 'am-ET', 'ar' => 'ar-SA', 'ay' => 'ay-BO', 'az' => 'az-AZ', 'be' => 'be-BY', 'bg' => 'bg-BG', 'bi' => 'bi-VU', 'bn' => 'bn-IN', 'bs' => 'bs-BA', 'ca' => 'ca-ES', 'ch' => 'ch-PW', 'cs' => 'cs-CZ', 'da' => 'da-DK', 'de' => 'de-DE', 'dv' => 'dv-MV', 'dz' => 'dz-BT', 'el' => 'el-GR', 'en' => 'en-US', 'es' => 'es-ES', 'et' => 'et-EE', 'fa' => 'fa-IR', 'fi' => 'fi-FI', 'fj' => 'fj-FJ', 'fo' => 'fo-FO', 'fr' => 'fr-FR', 'ga' => 'ga-IE', 'gn' => 'gn-PY', 'gv' => 'gv-GB', 'he' => 'he-IL', 'hi' => 'hi-IN', 'ho' => 'ho-PG', 'hr' => 'hr-HR', 'ht' => 'ht-HT', 'hu' => 'hu-HU', 'hy' => 'hy-AM', 'hz' => 'hz-NA', 'id' => 'id-ID', 'is' => 'is-IS', 'it' => 'it-IT', 'ja' => 'ja-JP', 'ka' => 'ka-GE', 'kg' => 'kg-CD', 'kk' => 'kk-KZ', 'kl' => 'kl-GL', 'km' => 'km-KH', 'ko' => 'ko-KR', 'ky' => 'ky-KG', 'la' => 'la-VAT', 'ln' => 'ln-CD', 'lo' => 'lo-LA', 'lt' => 'lt-LT', 'lu' => 'lu-CD', 'lv' => 'lv-LV', 'mg' => 'mg-MG', 'mh' => 'mh-MH', 'mi' => 'mi-NZ', 'mk' => 'mk-MK', 'mn' => 'mn-MN', 'ms' => 'ms-MY', 'mt' => 'mt-MT', 'my' => 'my-MM', 'na' => 'na-NR', 'nb' => 'nb-NO', 'nd' => 'nd-ZW', 'ne' => 'ne-NP', 'ng' => 'ng-NA', 'nl' => 'nl-NL', 'nn' => 'nn-NO', 'no' => 'no-NO', 'nr' => 'nr-ZA', 'ny' => 'ny-MW', 'pl' => 'pl-PL', 'ps' => 'ps-AF', 'pt' => 'pt-PT', 'qu' => 'qu-PE', 'rm' => 'rm-CH', 'rn' => 'rn-BI', 'ro' => 'ro-RO', 'ru' => 'ru-RU', 'rw' => 'rw-RW', 'sg' => 'sg-CF', 'si' => 'si-LK', 'sk' => 'sk-SK', 'sl' => 'sl-SI', 'sm' => 'sm-AS', 'sn' => 'sn-ZW', 'so' => 'so-SO', 'sq' => 'sq-AL', 'sr' => 'sr-RS', 'ss' => 'ss-ZA', 'st' => 'st-ZA', 'sv' => 'sv-SE', 'sw' => 'sw-KE', 'ta' => 'ta-IN', 'tg' => 'tg-TJ', 'th' => 'th-TH', 'ti' => 'ti-ER', 'tk' => 'tk-TM', 'tn' => 'tn-ZA', 'to' => 'to-TO', 'tr' => 'tr-TR', 'ts' => 'ts-ZA', 'uk' => 'uk-UA', 'ur' => 'ur-PK', 'uz' => 'uz-UZ', 've' => 've-ZA', 'vi' => 'vi-VN', 'xh' => 'xh-ZA', 'zh' => 'zh-CN', 'zu' => 'zu-ZA'];
$lang = strtolower($lang);
return $localeMap[$lang] ?? 'en-US';
}
public static function getStarRating(int $score, string $color = 'var(--theme-primary)', int $starSize = 20): string
{
$maxStars = 5;
$fullStar = '<span class="d-inline-flex align-items-center justify-content-center rounded text-white" style="width: ' . ($starSize + 8) . 'px;height: ' . ($starSize + 8) . 'px;background-color:' . $color . '"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>';
$halfStar = '<span class="d-inline-flex align-items-center justify-content-center rounded text-white" style="width: ' . ($starSize + 8) . 'px;height: ' . ($starSize + 8) . 'px;background-color:' . $color . '"><i class="fa-solid fa-star-half" style="font-size:' . $starSize . 'px" ></i></span>';
$emptyStar = '<span class="d-inline-flex align-items-center justify-content-center rounded bg-theme-light-200 text-white" style="width: ' . ($starSize + 8) . 'px;height: ' . ($starSize + 8) . 'px;"><i class="fa-solid fa-star" style="font-size:' . $starSize . 'px"></i></span>';
$starsHtml = '';
$fullStars = floor($score);
$decimalPart = $score - $fullStars;
if (0.75 <= $decimalPart) {
++$fullStars;
$halfStars = 0;
}
else if (0.25 <= $decimalPart) {
$halfStars = 1;
}
else {
$halfStars = 0;
}
$emptyStars = $maxStars - $fullStars - $halfStars;
$starsHtml .= str_repeat($fullStar, $fullStars);
$starsHtml .= str_repeat($halfStar, $halfStars);
$starsHtml .= str_repeat($emptyStar, $emptyStars);
return $starsHtml;
}
public static function parseCanonicalUrl(string $url, string $current_lang = '', bool $alternate = false): string
{
if (!$current_lang) {
$current_lang = Language::selected();
}
$default_lang = Config::get('general/local');
$page_param = '';
if (strpos($url, '?') !== false) {
$url_parts = explode('?', $url, 2);
$url = $url_parts[0];
$parsed_query = [];
parse_str($url_parts[1], $parsed_query);
if (isset($parsed_query['page']) && is_numeric($parsed_query['page'])) {
$page_param = '?page=' . (int) $parsed_query['page'];
}
}
$slug_suffix = '';
if (preg_match('#/sayfa/([0-9]+)$#i', $url, $page_matches)) {
$slug_suffix = '/sayfa/' . $page_matches[1];
$url = preg_replace('#/sayfa/[0-9]+$#i', '', $url);
}
$parsed = parse_url($url);
$protocol = (isset($parsed['scheme']) ? $parsed['scheme'] : (Utility::isSSL() ? 'https' : 'http'));
$host = (isset($parsed['host']) ? $parsed['host'] : $_SERVER['HTTP_HOST']);
if (View::$init->template_file == 'index.php') {
$homeRoute = ___('website-routes/website-routes/home', false, $current_lang);
$firstHomeRoute = trim($homeRoute[0], ' ' . "\t\n\r" . "\0" . '/');
if ($firstHomeRoute !== '') {
$url = str_replace($homeRoute[0], '', $url);
}
else {
$url = str_replace($homeRoute[1], '', $url);
}
}
if ($current_lang == $default_lang) {
$url = preg_replace('#^' . preg_quote($protocol . '://' . $host, '#') . '/' . $default_lang . '(?=/|$)#', $protocol . '://' . $host, $url);
}
$categoryRoute = ___('website-routes/website-routes/products', false, $current_lang);
$category_slug = preg_replace('/\\/\\(\\?\\).*/', '', $categoryRoute[0]);
$pattern = '#/' . $category_slug . '/(.*)#';
if (preg_match($pattern, $url, $matches)) {
$category_path = $matches[1];
$slugs = explode('/', trim($category_path, '/'));
$lang_prefix = ($current_lang != $default_lang ? $current_lang . '/' : '');
$last_slug = end($slugs);
if ($last_slug == 'sms') {
$canonical_path = $category_slug . '/sms';
$url = $protocol . '://' . $host . '/' . $lang_prefix . $canonical_path;
}
else {
$canonical_path = $category_slug . '/' . trim($last_slug, '/');
$url = $protocol . '://' . $host . '/' . $lang_prefix . $canonical_path;
}
}
$url = rtrim($url, '/');
$url = $url . $slug_suffix . $page_param;
return $url;
}
private static function parseShortcodesToHtml(string $content): string
{
$content = preg_replace_callback('/\\[iframe\\s+(.*?)\\]/i', function($matches) {
$attrs = [];
preg_match_all('/(\\w+)\\s*=\\s*"([^"]*)"/', $matches[1], $attrMatches, PREG_SET_ORDER);
foreach ($attrMatches as $attr) {
$attrs[] = $attr[1] . '="' . htmlspecialchars($attr[2], ENT_QUOTES) . '"';
}
return '<iframe ' . implode(' ', $attrs) . '></iframe>';
}, $content);
$content = preg_replace_callback('/\\[script\\](.*?)\\[\\/script\\]/is', function($matches) {
return '<script>' . $matches[1] . '</script>';
}, $content);
return $content;
}
public function googleStructuredData(array $pageData = []): string
{
$settings = (isset($this->config['settings']) ? $this->config['settings'] : []);
$gsdData = ['show' => (isset($settings['seo_gsd_show']) ? $settings['seo_gsd_show'] : false), 'site_name' => (isset($settings['seo_site_name']) ? $settings['seo_site_name'] : []), 'organisation_name' => (isset($settings['seo_organisation_name']) ? $settings['seo_organisation_name'] : []), 'organisation_address' => (isset($settings['seo_organisation_address']) ? $settings['seo_organisation_address'] : ''), 'organisation_city' => (isset($settings['seo_organisation_city']) ? $settings['seo_organisation_city'] : ''), 'organisation_region' => (isset($settings['seo_organisation_region']) ? $settings['seo_organisation_region'] : ''), 'organisation_postal_code' => (isset($settings['seo_organisation_postal_code']) ? $settings['seo_organisation_postal_code'] : ''), 'organisation_country' => (isset($settings['seo_organisation_country']) ? $settings['seo_organisation_country'] : ''), 'organisation_price_min' => (isset($settings['seo_organisation_price_min']) ? $settings['seo_organisation_price_min'] : 0), 'organisation_price_max' => (isset($settings['seo_organisation_price_max']) ? $settings['seo_organisation_price_max'] : 0), 'organisation_price_currency' => (isset($settings['seo_organisation_price_currency']) ? $settings['seo_organisation_price_currency'] : 147), 'organisation_rating_value' => (isset($settings['seo_organisation_rating_value']) ? $settings['seo_organisation_rating_value'] : ''), 'organisation_rating_count' => (isset($settings['seo_organisation_rating_count']) ? $settings['seo_organisation_rating_count'] : '')];
$template = $pageData['hoptions']['page'] ?? 'index';
$lang = Language::selected();
$currencies = Money::getCurrencies();
$phones = Config::get('contact/phone-numbers');
$address = Config::get('contact/address');
$emails = Config::get('contact/email-addresses');
$socials = Config::get('contact/social-links');
$maps = Config::get('contact/maps');
$logo = static::assetLinkDetermine(Config::get('theme/header-logo'));
$breadcrumb = $pageData['breadcrumb'] ?? [];
if ($socials) {
$socials = array_column($socials, 'url');
}
$output = [];
if (!empty($gsdData) && isset($gsdData['show']) && $gsdData['show']) {
if ($breadcrumb) {
end($breadcrumb);
$lastKey = key($breadcrumb);
$breadcrumb[$lastKey]['link'] = $pageData['hoptions']['gsd_route'] ?? '';
$breadcrumbItems = [];
foreach ($breadcrumb as $item) {
if (isset($item['title']) && isset($item['link'])) {
$breadcrumbItems[] = ['@type' => 'ListItem', 'position' => count($breadcrumbItems) + 1, 'name' => $item['title'], 'item' => ($item['link'] != '' ? $item['link'] : (!preg_match('/^https?:\\/\\//', $_SERVER['REQUEST_URI']) ? Controllers::$init->CRLink(ltrim($_SERVER['REQUEST_URI'], '/'), false, 'none') : $_SERVER['REQUEST_URI']))];
}
}
$output['breadcrums'] = ['@context' => 'http://schema.org', '@type' => 'BreadcrumbList', 'itemListElement' => $breadcrumbItems];
}
$output['website'] = [
'@context' => 'http://schema.org',
'@type' => 'WebSite',
'@id' => $pageData['badress'] ?? Utility::AppAdress(),
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang),
'description' => __('website/index/meta/description', false, $lang),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'image' => ['@type' => 'ImageObject', 'url' => $logo],
'sameAs' => $socials
];
$output['webpage'] = [
'@context' => 'http://schema.org',
'@type' => 'WebPage',
'name' => (isset($pageData['header_title']) && $pageData['header_title'] ? $pageData['header_title'] : (isset($pageData['meta']['title']) && $pageData['meta']['title'] ? $pageData['meta']['title'] : __('website/index/meta/title', false, $lang))),
'description' => (isset($pageData['header_description']) && $pageData['header_description'] ? $pageData['header_description'] : (isset($pageData['meta']['description']) && $pageData['meta']['description'] ? $pageData['meta']['description'] : __('website/index/meta/description', false, $lang))),
'url' => $_SERVER['REQUEST_URI'],
'inLanguage' => $lang,
'isPartOf' => ['@id' => $pageData['badress'] ?? Utility::AppAdress()]
];
if ($template == 'index') {
$output['index'] = [
'@context' => 'http://schema.org',
'@type' => 'Organization',
'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang)),
'description' => __('website/index/meta/description', false, $lang),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => $logo ?? false,
'image' => $logo ?? false,
'email' => $emails[0] ?? false,
'sameAs' => $socials,
'telephone' => str_replace(' ', '', $phones[0] ?? ''),
'address' => ['@type' => 'PostalAddress', 'streetAddress' => $gsdData['organisation_address'] ?? ($address ?? false), 'addressLocality' => $gsdData['organisation_city'] ?? false, 'addressRegion' => $gsdData['organisation_region'] ?? false, 'postalCode' => $gsdData['organisation_postal_code'] ?? false, 'addressCountry' => $gsdData['organisation_country'] ?? false]
];
}
else if ($template == 'articles') {
if (isset($pageData['hoptions']['gsd_list']) && is_array($pageData['hoptions']['gsd_list']) && 0 < count($pageData['hoptions']['gsd_list'])) {
$blogPosts = [];
foreach ($pageData['hoptions']['gsd_list'] as $index => $item) {
$mtime = $this->gsd_get_page_mtime($item['id']);
$blogPosts[] = [
'@type' => 'BlogPosting',
'headline' => $item['title'],
'url' => $item['route'],
'image' => $item['image'] ?? false,
'datePublished' => (isset($item['ctime']) && $item['ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $item['ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c')),
'dateModified' => $mtime ?: (new DateTime())->format('c'),
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()]
];
}
$output['blog'] = ['@context' => 'https://schema.org', '@type' => 'Blog', 'name' => (isset($pageData['meta']['title']) && $pageData['meta']['title'] != '' ? $pageData['meta']['title'] : $pageData['header_title']), 'url' => Controllers::$init->CRLink('articles', false, $lang), 'blogPost' => $blogPosts];
}
}
else if (($template == 'softwares') || $template == 'news' || $template == 'knowledgebase' || $template == 'references') {
if (isset($pageData['hoptions']['gsd_list']) && is_array($pageData['hoptions']['gsd_list']) && 0 < count($pageData['hoptions']['gsd_list'])) {
$itemListElements = [];
foreach ($pageData['hoptions']['gsd_list'] as $index => $item) {
$itemListElements[$index] = ['@type' => 'ListItem', 'url' => $item['route'], 'name' => $item['title'], 'position' => $index + 1];
}
$output[$template] = ['@context' => 'https://schema.org', '@type' => 'ItemList', 'name' => (isset($pageData['meta']['title']) && $pageData['meta']['title'] != '' ? $pageData['meta']['title'] : $pageData['header_title']), 'itemListElement' => $itemListElements];
}
}
else if (($template == 'hosting-products') || $template == 'server-products' || $template == 'sms-products' || $template == 'special-products') {
if (isset($pageData['hoptions']['gsd_list']['list']) && $pageData['hoptions']['gsd_list']['list'] && 0 < count($pageData['hoptions']['gsd_list']['list'])) {
$old_serialize_precision = ini_get('serialize_precision');
ini_set('serialize_precision', -1);
$offers = [];
foreach ($pageData['hoptions']['gsd_list']['list'] as $item) {
$currency = (isset($item['prices'][0]['cid']) ? $currencies[array_search($item['prices'][0]['cid'], array_column($currencies, 'id'))]['code'] : 'TRY');
$sale_price = $item['prices'][0]['amount'];
$raw_price = 0;
if (0 < $item['prices'][0]['discount']) {
$raw_price = $item['prices'][0]['amount'] / (1 - ($item['prices'][0]['discount'] / 100));
}
$offers[$item['id']] = [
'@type' => 'Offer',
'name' => $item['title'],
'sku' => (isset($pageData['hoptions']['gsd_list']['cat']) && $pageData['hoptions']['gsd_list']['cat'] ? $pageData['hoptions']['gsd_list']['cat'] . '-' . $item['id'] : $item['id']),
'availability' => (isset($item['haveStock']) && $item['haveStock'] ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock'),
'itemCondition' => 'https://schema.org/NewCondition',
'seller' => ['@type' => 'Organization', 'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang))],
'url' => self::parseCanonicalUrl($item['buy_link'], $lang)
];
if ((0 < $raw_price) && $raw_price != $sale_price) {
$offers[$item['id']]['priceSpecification'] = [
['@type' => 'UnitPriceSpecification', 'price' => (float) sprintf('%.2f', $sale_price), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false],
['@type' => 'UnitPriceSpecification', 'priceType' => 'https://schema.org/StrikethroughPrice', 'price' => (float) sprintf('%.2f', $raw_price), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false]
];
}
else {
$offers[$item['id']]['priceSpecification'] = ['@type' => 'UnitPriceSpecification', 'price' => (float) sprintf('%.2f', $sale_price), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false];
}
}
$output[$template] = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['header_description']) && $pageData['header_description'] != '' ? $pageData['header_description'] : false)),
'brand' => ['@type' => 'Brand', 'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang))],
'image' => ['@type' => 'ImageObject', 'url' => (isset($pageData['header_background']) && $pageData['header_background'] ? $pageData['header_background'] : false)],
'offers' => array_values($offers)
];
ini_set('serialize_precision', $old_serialize_precision);
}
if (isset($pageData['hoptions']['gsd_faq']) && $pageData['hoptions']['gsd_faq'] && 0 < count($pageData['hoptions']['gsd_faq'])) {
$faqs = [];
foreach ($pageData['hoptions']['gsd_faq'] as $faq) {
$faqs[] = [
'@type' => 'Question',
'name' => $faq['title'],
'acceptedAnswer' => ['@type' => 'Answer', 'text' => $faq['description']]
];
}
$output[$template . '_faqs'] = ['@context' => 'https://schema.org', '@type' => 'FAQPage', 'mainEntity' => $faqs];
}
}
else if ($template == 'page-detail-software') {
$old_serialize_precision = ini_get('serialize_precision');
ini_set('serialize_precision', -1);
$ctime = (isset($pageData['hoptions']['gsd_ctime']) && $pageData['hoptions']['gsd_ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $pageData['hoptions']['gsd_ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c'));
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0);
$output['software-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'SoftwareApplication',
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']],
'name' => $pageData['header_title'],
'applicationCategory' => 'BusinessApplication',
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => (isset($pageData['hoptions']['gsd_mockup']) && $pageData['hoptions']['gsd_mockup'] ? $pageData['hoptions']['gsd_mockup'] : (isset($pageData['hoptions']['gsd_cover']) && $pageData['hoptions']['gsd_cover'] ? $pageData['hoptions']['gsd_cover'] : $pageData['header_background'] ?? false)),
'datePublished' => $ctime,
'dateModified' => $mtime ?: $ctime,
'aggregateRating' => ['@type' => 'AggregateRating', 'ratingValue' => (float) sprintf('%.1f', 4.7), 'ratingCount' => $pageData['hoptions']['gsd_ratingCount'] ?? 0],
'offers' => ['@type' => 'Offer', 'price' => (float) sprintf('%.2f', $pageData['hoptions']['gsd_price']['amount']), 'priceCurrency' => $currencies[array_search($pageData['hoptions']['gsd_price']['cid'], array_column($currencies, 'id'))]['code']],
'operatingSystem' => 'Web'
];
ini_set('serialize_precision', $old_serialize_precision);
}
else if ($template == 'page-detail-articles') {
$ctime = (isset($pageData['hoptions']['gsd_ctime']) && $pageData['hoptions']['gsd_ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $pageData['hoptions']['gsd_ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c'));
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0);
$output['article-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'BlogPosting',
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']],
'isPartOf' => ['@type' => 'Blog', 'name' => __('website/articles/meta/title') . ' - ' . __('website/index/meta/title'), 'url' => Controllers::$init->CRLink('articles')],
'headline' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => (isset($pageData['hoptions']['gsd_cover']) && $pageData['hoptions']['gsd_cover'] ? $pageData['hoptions']['gsd_cover'] : $pageData['header_background'] ?? false),
'datePublished' => $ctime,
'dateModified' => $mtime ?: $ctime,
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()],
'publisher' => [
'@type' => 'Organization',
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => ['@type' => 'ImageObject', 'url' => $logo ?? false]
]
];
}
else if ($template == 'page-detail-news') {
$ctime = (isset($pageData['hoptions']['gsd_ctime']) && $pageData['hoptions']['gsd_ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $pageData['hoptions']['gsd_ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c'));
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0);
$output['news-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'NewsArticle',
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']],
'headline' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => (isset($pageData['hoptions']['gsd_cover']) && $pageData['hoptions']['gsd_cover'] ? static::assetLinkDetermine('resources/uploads/news/' . $pageData['hoptions']['gsd_cover']) : $pageData['header_background'] ?? false),
'datePublished' => $ctime,
'dateModified' => $mtime ?: $ctime,
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()],
'publisher' => [
'@type' => 'Organization',
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => ['@type' => 'ImageObject', 'url' => $logo ?? false]
]
];
}
else if ($template == 'page-detail-references') {
$ctime = (isset($pageData['hoptions']['gsd_ctime']) && $pageData['hoptions']['gsd_ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $pageData['hoptions']['gsd_ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c'));
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0);
$output['reference-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']],
'isPartOf' => ['@type' => 'CollectionPage', 'name' => __('website/references/meta/title') . ' - ' . __('website/index/meta/title'), 'url' => Controllers::$init->CRLink('references')],
'headline' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => (isset($pageData['hoptions']['gsd_mockup']) && $pageData['hoptions']['gsd_mockup'] ? $pageData['hoptions']['gsd_mockup'] : (isset($pageData['hoptions']['gsd_cover']) && $pageData['hoptions']['gsd_cover'] ? static::assetLinkDetermine('resources/uploads/references/' . $pageData['hoptions']['gsd_cover']) : $pageData['header_background'] ?? false)),
'datePublished' => $ctime,
'dateModified' => $mtime ?: $ctime,
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()],
'publisher' => [
'@type' => 'Organization',
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => ['@type' => 'ImageObject', 'url' => $logo ?? false]
]
];
}
else if ($template == 'page-detail-normal') {
$ctime = (isset($pageData['hoptions']['gsd_ctime']) && $pageData['hoptions']['gsd_ctime'] ? ($dt = DateTime::createFromFormat(Config::get('options/date-format'), $pageData['hoptions']['gsd_ctime']) ? $dt->format('c') : (new DateTime())->format('c')) : (new DateTime())->format('c'));
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0);
$output['normal-page-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link'],
'url' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link'],
'name' => $pageData['header_title'],
'headline' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => $pageData['header_background'] ?? false,
'inLanguage' => $lang,
'datePublished' => $ctime,
'dateModified' => $mtime ?: $ctime,
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()],
'publisher' => [
'@type' => 'Organization',
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => ['@type' => 'ImageObject', 'url' => $logo ?? false]
],
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']]
];
}
else if ($template == 'knowledgebase-detail') {
$ctime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0, 'ctime', 'knowledgebase');
$mtime = $this->gsd_get_page_mtime($pageData['hoptions']['gsd_id'] ?? 0, 'mtime', 'knowledgebase');
$output['knowledgebase-detail'] = [
'@context' => 'https://schema.org',
'@type' => 'TechArticle',
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $pageData['hoptions']['gsd_route'] ?? $breadcrumb[count($breadcrumb) - 1]['link']],
'isPartOf' => ['@type' => 'CollectionPage', 'name' => __('website/knowledgebase/meta/title') . ' - ' . __('website/index/meta/title'), 'url' => Controllers::$init->CRLink('knowledgebase')],
'headline' => (isset($pageData['hoptions']['gsd_title']) && $pageData['hoptions']['gsd_title'] != '' ? $pageData['hoptions']['gsd_title'] : (isset($pageData['meta']['title']) && $pageData['meta']['title'] != '' ? $pageData['meta']['title'] : '')),
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['gsd_description']) && $pageData['hoptions']['gsd_description'] != '' ? $this->_gsd_description_create($pageData['hoptions']['gsd_description']) : '')),
'image' => (isset($pageData['header_background']) && $pageData['header_background'] ? $pageData['header_background'] : false),
'datePublished' => $ctime ?: (new DateTime())->format('c'),
'dateModified' => $mtime ?: (new DateTime())->format('c'),
'author' => ['@type' => 'Organization', 'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'), 'url' => $pageData['badress'] ?? Utility::AppAdress()],
'publisher' => [
'@type' => 'Organization',
'name' => $gsdData['site_name'][$lang] ?? __('website/index/meta/title'),
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'logo' => ['@type' => 'ImageObject', 'url' => $logo ?? false]
]
];
}
else if ($template == 'contact') {
$old_serialize_precision = ini_get('serialize_precision');
ini_set('serialize_precision', -1);
$output['contact'] = [
'@context' => 'https://schema.org',
'@type' => ['LocalBusiness'],
'@id' => ($pageData['badress'] ? $pageData['badress'] . '#LocalBusiness' : Utility::AppAdress() . '#LocalBusiness'),
'image' => $logo ?? false,
'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title')),
'telephone' => str_replace(' ', '', $phones[0] ?? ''),
'email' => $emails[0] ?? false,
'priceRange' => str_replace(' ', '', Money::formatter_symbol($gsdData['organisation_price_min'], $gsdData['organisation_price_currency'])) . ' - ' . str_replace(' ', '', Money::formatter_symbol($gsdData['organisation_price_max'], $gsdData['organisation_price_currency'])),
'address' => ['@type' => 'PostalAddress', 'streetAddress' => $gsdData['organisation_address'] ?? ($address ?? false), 'addressLocality' => $gsdData['organisation_city'] ?? false, 'addressRegion' => $gsdData['organisation_region'] ?? false, 'postalCode' => $gsdData['organisation_postal_code'] ?? false, 'addressCountry' => $gsdData['organisation_country'] ?? false],
'aggregateRating' => ['@type' => 'AggregateRating', 'ratingValue' => ($gsdData['organisation_rating_value'] ? (float) sprintf('%.1f', $gsdData['organisation_rating_value']) : 5), 'reviewCount' => $gsdData['organisation_rating_count'] ?? 100, 'worstRating' => 1, 'bestRating' => 5],
'geo' => ['@type' => 'GeoCoordinates', 'latitude' => $maps['latitude'] ?? false, 'longitude' => $maps['longitude'] ?? false],
'url' => $pageData['badress'] ?? Utility::AppAdress(),
'sameAs' => $socials
];
ini_set('serialize_precision', $old_serialize_precision);
}
else if ($template == 'domain') {
if (isset($pageData['hoptions']['gsd_list']) && $pageData['hoptions']['gsd_list'] && 0 < count($pageData['hoptions']['gsd_list'])) {
$old_serialize_precision = ini_get('serialize_precision');
ini_set('serialize_precision', -1);
$offers = [];
foreach ($pageData['hoptions']['gsd_list'] as $item) {
$currency = (isset($item['currency']) ? $currencies[array_search($item['currency'], array_column($currencies, 'id'))]['code'] : 'TRY');
$offers[$item['id']] = [
'@type' => 'Offer',
'name' => '.' . $item['name'] . ' Domain',
'sku' => 'domain-' . $item['name'],
'availability' => 'https://schema.org/InStock',
'itemCondition' => 'https://schema.org/NewCondition',
'seller' => ['@type' => 'Organization', 'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang))],
'url' => self::parseCanonicalUrl(Controllers::$init->CRLink('domain', false, $lang), $lang)
];
if ($item['promo_status'] && 0 < $item['promo_register_price']) {
$offers[$item['id']]['priceValidUntil'] = $item['promo_duedate'];
$offers[$item['id']]['priceSpecification'] = [
['@type' => 'UnitPriceSpecification', 'price' => (float) sprintf('%.2f', $item['promo_register_price']), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false],
['@type' => 'UnitPriceSpecification', 'priceType' => 'https://schema.org/StrikethroughPrice', 'price' => (float) sprintf('%.2f', $item['reg_price']['amount']), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false]
];
}
else {
$offers[$item['id']]['priceSpecification'] = ['@type' => 'UnitPriceSpecification', 'price' => (float) sprintf('%.2f', $item['reg_price']['amount']), 'priceCurrency' => $currency, 'valueAddedTaxIncluded' => false];
}
}
$output[$template] = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $pageData['header_title'],
'description' => (isset($pageData['meta']['description']) && $pageData['meta']['description'] != '' ? $pageData['meta']['description'] : (isset($pageData['hoptions']['header_description']) && $pageData['header_description'] != '' ? $pageData['header_description'] : false)),
'brand' => ['@type' => 'Brand', 'name' => $gsdData['organisation_name'][$lang] ?? ($gsdData['site_name'][$lang] ?? __('website/index/meta/title', false, $lang))],
'image' => ['@type' => 'ImageObject', 'url' => (isset($pageData['header_background']) && $pageData['header_background'] ? $pageData['header_background'] : false)],
'offers' => array_values($offers)
];
ini_set('serialize_precision', $old_serialize_precision);
}
if (isset($pageData['hoptions']['gsd_faq']) && $pageData['hoptions']['gsd_faq'] && 0 < count($pageData['hoptions']['gsd_faq'])) {
$faqs = [];
foreach ($pageData['hoptions']['gsd_faq'] as $faq) {
$faqs[] = [
'@type' => 'Question',
'name' => $faq['title'],
'acceptedAnswer' => ['@type' => 'Answer', 'text' => $faq['description']]
];
}
$output['hosting-faqs'] = ['@context' => 'https://schema.org', '@type' => 'FAQPage', 'mainEntity' => $faqs];
}
}
}
$final_output = '<!-- Google Yapılandırılmış Veri - Start -->' . "\n";
if ($output && is_array($output) && 0 < count($output)) {
foreach ($output as $item) {
$final_output .= '<script type="application/ld+json">';
$final_output .= json_encode($item, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
$final_output .= '</script>';
}
}
$final_output .= '<!-- Google Yapılandırılmış Veri - End -->' . "\n";
return $final_output;
}
public function parseOpenGraph(array $data = []): string
{
if (($data['type'] ?? '') == 'business.business') {
$settings = (isset($this->config['settings']) ? $this->config['settings'] : []);
$data['title'] = (isset($settings['seo_organisation_name'][$this->lang]) ? $settings['seo_organisation_name'][$this->lang] : __('website/meta/title', false, $this->lang));
$data['image'] = static::assetLinkDetermine(Config::get('theme/header-logo'));
$data['description'] = __('website/meta/description', false, $this->lang);
$data['url'] = Controllers::$init->CRLink('contact');
$address = (isset($settings['seo_organisation_address']) ? $settings['seo_organisation_address'] : Config::get('contact/address') ?? '');
$city = (isset($settings['seo_organisation_city']) ? $settings['seo_organisation_city'] : '');
$region = (isset($settings['seo_organisation_region']) ? $settings['seo_organisation_region'] : '');
$zipcode = (isset($settings['seo_organisation_postal_code']) ? $settings['seo_organisation_postal_code'] : '');
$country = (isset($settings['seo_organisation_country']) ? $settings['seo_organisation_country'] : Config::get('general/country') ?? '');
$countryList = AddressManager::getCountryList();
$countryName = '';
if ($country) {
foreach ($countryList as $c) {
if (strtoupper($country) == $c['code']) {
$countryName = $c['name'];
}
}
}
}
$ogLang = self::getBCPLocale($this->lang);
$opengraph = '';
$opengraph .= '<meta property="og:locale" content="' . $ogLang . '">' . PHP_EOL;
$opengraph .= '<meta property="og:site_name" content="' . __('website/index/meta/title', false, $this->lang) . '">' . PHP_EOL;
if (isset($data['title'][$this->lang]) && $data['title'][$this->lang] != '') {
$opengraph .= '<meta property="og:title" content="' . $data['title'][$this->lang] . '">' . PHP_EOL;
}
$opengraph .= '<meta property="og:type" content="' . ($data['type'] ?? 'website') . '">' . PHP_EOL;
$opengraph .= '<meta property="og:url" content="' . $data['url'] . '">' . PHP_EOL;
if (isset($data['image']) && $data['image'] != '') {
$opengraph .= '<meta property="og:image" content="' . static::assetLinkDetermine($data['image']) . '">' . PHP_EOL;
if ($data['type'] != 'business.business') {
$opengraph .= '<meta property="og:image:width" content="1200">' . PHP_EOL;
$opengraph .= '<meta property="og:image:height" content="630">' . PHP_EOL;
}
}
if (isset($data['description'][$this->lang]) && $data['description'][$this->lang] != '') {
$opengraph .= '<meta property="og:description" content="' . $data['description'][$this->lang] . '">' . PHP_EOL;
}
if (isset($data['type']) && $data['type'] == 'article') {
if (isset($data['author']) && $data['author'] != '') {
$opengraph .= '<meta property="article:author" content="' . $data['author'] . '">' . PHP_EOL;
}
if (isset($data['published_time']) && $data['published_time'] != '') {
$opengraph .= '<meta property="article:published_time" content="' . $data['published_time'] . '">' . PHP_EOL;
}
if (isset($data['modified_time']) && $data['modified_time'] != '') {
$opengraph .= '<meta property="article:modified_time" content="' . $data['modified_time'] . '">' . PHP_EOL;
}
if (isset($data['section']) && $data['section'] != '') {
$opengraph .= '<meta property="article:section" content="' . $data['section'] . '">' . PHP_EOL;
}
}
if (isset($data['type']) && $data['type'] == 'business.business') {
if (isset($address) && $address != '') {
$opengraph .= '<meta property="business:contact_data:street_address" content="' . $address . '">' . PHP_EOL;
}
if (isset($region) && $region != '') {
$opengraph .= '<meta property="business:contact_data:locality" content="' . $region . '">' . PHP_EOL;
}
if (isset($city) && $city != '') {
$opengraph .= '<meta property="business:contact_data:region" content="' . $city . '">' . PHP_EOL;
}
if (isset($zipcode) && $zipcode != '') {
$opengraph .= '<meta property="business:contact_data:postal_code" content="' . $zipcode . '">' . PHP_EOL;
}
if (isset($countryName) && $countryName != '') {
$opengraph .= '<meta property="business:contact_data:country_name" content="' . $countryName . '">' . PHP_EOL;
}
}
if (isset($data['type']) && $data['type'] != 'business.business') {
$opengraph .= '<meta name="twitter:card" content="summary">' . PHP_EOL;
$opengraph .= '<meta name="twitter:site" content="' . __('website/index/meta/title', false, $this->lang) . '">' . PHP_EOL;
if (isset($data['description'][$this->lang]) && $data['description'][$this->lang] != '') {
$opengraph .= '<meta property="twitter:description" content="' . $data['description'][$this->lang] . '">' . PHP_EOL;
}
if (isset($data['image']) && $data['image'] != '') {
$opengraph .= '<meta name="twitter:image:src" content="' . static::assetLinkDetermine($data['image']) . '">' . PHP_EOL;
}
}
return $opengraph;
}
private function _gsd_description_create(string $text, int $limit = 250): string
{
$text = strip_tags($text);
if (mb_strlen($text) <= $limit) {
return $text;
}
$short = mb_substr($text, 0, $limit);
$lastSpace = mb_strrpos($short, ' ');
return mb_substr($short, 0, $lastSpace) . '…';
}
public function gsd_get_page_mtime(string|int $id, string $column = 'mtime', string $type = 'pages'): string
{
$time = '';
$pageTimeExist = WDB::query('SHOW COLUMNS FROM `' . $type . '` LIKE \'' . $column . '\'')->rowCount();
if ($pageTimeExist) {
$query = WDB::select('p.' . $column)->from($type . ' AS p')->where('p.id', '=', $id);
$result = ($query->build() ? $query->getAssoc() : '');
if ($result && isset($result[$column]) && $result[$column] != '0000-00-00 00:00:00') {
$time = date(DATE_ATOM, strtotime($result[$column]));
}
}
return $time;
}
public static function wordCount(string $unicode_string): int
{
$unicode_string = preg_replace('/[\\p{P}\\p{N}]/u', '', $unicode_string);
$unicode_string = preg_replace('/\\s+/u', ' ', $unicode_string);
$words_array = preg_split('/\\s+/u', trim($unicode_string), -1, PREG_SPLIT_NO_EMPTY);
return count($words_array);
}
public static function getImageDimensions(string $image_path_or_url, ?string $base_url = NULL): ?string
{
if (empty($base_url)) {
$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http');
$host = $_SERVER['HTTP_HOST'];
$host = preg_replace('/^www\\./', '', $host);
$base_url = $protocol . '://' . $host;
}
$is_remote = (strpos($image_path_or_url, 'http://') === 0) || strpos($image_path_or_url, 'https://') === 0;
$full_path = NULL;
if ($is_remote) {
if (strpos($image_path_or_url, $base_url) === 0) {
$relative_path = substr($image_path_or_url, strlen($base_url));
$base_path = $_SERVER['DOCUMENT_ROOT'];
$full_path = $base_path . '/' . ltrim($relative_path, '/');
if (!file_exists($full_path)) {
return NULL;
}
}
else {
return NULL;
}
}
else {
$base_path = $_SERVER['DOCUMENT_ROOT'];
$full_path = $base_path . '/' . ltrim($image_path_or_url, '/');
if (!file_exists($full_path)) {
return NULL;
}
}
$size_info = @getimagesize($full_path);
if ($size_info !== false && isset($size_info[0]) && isset($size_info[1]) && 0 < $size_info[0] && 0 < $size_info[1]) {
return 'width="' . $size_info[0] . '" height="' . $size_info[1] . '"';
}
return NULL;
}
public static function getImageThumb(string $image, string $type = 'articles'): string
{
$defaultImage = 'resources/uploads/' . $type . '/default.jpg';
if ($type == 'software') {
$defaultImage = 'resources/uploads/' . $type . '/list-image-default.jpg';
}
$defaultImage = static::assetLinkDetermine($defaultImage);
if ($image) {
$image = trim($image);
$parts = parse_url($image);
$itemImagePath = (isset($parts['path']) ? $parts['path'] : '');
$segments = explode('/', trim($itemImagePath, '/'));
$itemImageFolder = $segments[count($segments) - 2] ?? '';
$itemImageFile = end($segments) ?: '';
if (strpos($itemImagePath, '/' . $type . '/thumb/') !== false) {
$defaultImage = $image;
}
else {
$thumbUrl = preg_replace('#/(' . preg_quote($type, '#') . ')/#', '/$1/thumb/', $image, 1);
$thumbPath = RESOURCE_DIR . 'uploads' . DS . $type . DS . 'thumb' . DS . $itemImageFolder . DS . $itemImageFile;
if (file_exists($thumbPath)) {
$defaultImage = $thumbUrl;
}
else {
$defaultImage = $image;
}
}
}
return $defaultImage;
}
private function sanitizeRelativePath(string $path): string
{
$safePath = str_replace('\\', '/', $path);
$safePath = str_replace('..', '', $safePath);
return ltrim($safePath, '/');
}
private function buildGalleryPrettyTitle(string $fileBaseName): string
{
$cleaned = preg_replace('/[^a-zA-Z0-9]+/', ' ', $fileBaseName) ?? '';
$cleaned = trim($cleaned);
if ($cleaned === '') {
return 'Untitled';
}
return ucwords(strtolower($cleaned));
}
private function ensureThumbDirectory(string $path): void
{
if (!is_dir($path)) {
mkdir($path, 509, true);
}
}
private function buildGalleryThumbForImage(string $relativePath, string $baseDir, string $thumbDir, int $width, int $height): array
{
if (!class_exists('Upload')) {
require_once ROOT_DIR . 'coremio' . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'libraries' . DIRECTORY_SEPARATOR . 'Uploads' . DIRECTORY_SEPARATOR . 'class.upload.php';
}
$safeRelativePath = $this->sanitizeRelativePath($relativePath);
$sourcePath = realpath($baseDir . DIRECTORY_SEPARATOR . $safeRelativePath);
$baseRealPath = realpath($baseDir);
if ($sourcePath === false || $baseRealPath === false || strpos($sourcePath, $baseRealPath) !== 0) {
return ['crop' => $safeRelativePath, 'fit' => $safeRelativePath];
}
$sourceDir = (string) pathinfo($safeRelativePath, PATHINFO_DIRNAME);
$baseName = (string) pathinfo($safeRelativePath, PATHINFO_FILENAME);
$safeBaseName = Filter::permalink($baseName);
$sourceDir = ($sourceDir === '.' ? '' : $sourceDir);
$targetDir = $thumbDir . ($sourceDir !== '' ? DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $sourceDir) : '');
$this->ensureThumbDirectory($targetDir);
$fileStem = $safeBaseName . '_' . $width . '_' . $height;
$cropName = $fileStem . '_crop.jpg';
$fitName = $fileStem . '_fit.jpg';
$cropAbsolute = $targetDir . DIRECTORY_SEPARATOR . $cropName;
$fitAbsolute = $targetDir . DIRECTORY_SEPARATOR . $fitName;
if (!is_file($cropAbsolute)) {
$upload = new Upload($sourcePath);
$upload->image_resize = true;
$upload->image_convert = 'jpg';
$upload->image_x = $width;
$upload->image_y = $height;
$upload->image_ratio_crop = true;
$upload->jpeg_quality = 85;
$upload->file_safe_name = false;
$upload->file_overwrite = true;
$upload->file_new_name_body = $fileStem . '_crop';
$upload->file_new_name_ext = 'jpg';
$upload->process($targetDir);
}
if (!is_file($fitAbsolute)) {
$upload = new Upload($sourcePath);
$upload->image_resize = true;
$upload->image_convert = 'jpg';
$upload->image_x = $width;
$upload->image_y = $height;
$upload->image_ratio = true;
$upload->jpeg_quality = 85;
$upload->file_safe_name = false;
$upload->file_overwrite = true;
$upload->file_new_name_body = $fileStem . '_fit';
$upload->file_new_name_ext = 'jpg';
$upload->process($targetDir);
}
$thumbPrefix = 'fongallerythumb/' . ($sourceDir !== '' ? $sourceDir . '/' : '');
return ['crop' => $thumbPrefix . $cropName, 'fit' => $thumbPrefix . $fitName];
}
private function _parseResponsiveBootstrapTextAligns(object|array $alignData): string
{
if (empty($alignData)) {
return '';
}
$alignData = (array) $alignData;
$directionMap = ['left' => 'start', 'right' => 'end', 'center' => 'center', 'justify' => 'justify'];
$classes = [];
foreach ($alignData as $breakpoint => $value) {
if (!isset($directionMap[$value])) {
continue;
}
$bsValue = $directionMap[$value];
if ($breakpoint === 'xs') {
$classes[] = 'text-' . $bsValue;
}
else {
$classes[] = 'text-' . $breakpoint . '-' . $bsValue;
}
}
return implode(' ', $classes);
}
private function _parseResponsiveBootstrapFlexAligns(object|array $alignData): string
{
if (empty($alignData)) {
return '';
}
$alignData = (array) $alignData;
$directionMap = ['left' => 'start', 'right' => 'end', 'center' => 'center', 'justify' => 'between'];
$classes = [];
foreach ($alignData as $breakpoint => $value) {
if (!isset($directionMap[$value])) {
continue;
}
$bsValue = $directionMap[$value];
if ($breakpoint === 'xs') {
$classes[] = 'justify-content-' . $bsValue;
}
else {
$classes[] = 'justify-content-' . $breakpoint . '-' . $bsValue;
}
}
return implode(' ', $classes);
}
public static function getFieldMultilingualText(mixed $field, string $currentLang = 'tr', array|string $default = ''): string
{
if (!isset($field) || empty($field)) {
return $default;
}
if (is_object($field) || is_array($field)) {
$fieldArray = (array) $field;
if (isset($fieldArray[$currentLang]) && $fieldArray[$currentLang] !== '') {
return $fieldArray[$currentLang];
}
$firstValue = array_values($fieldArray)[0] ?? '';
return ($firstValue !== '' ? $firstValue : $default);
}
if (is_string($field)) {
return ($field !== '' ? $field : $default);
}
return $default;
}
private function addPreloadLink(string $imageUrl, string $page = 'index', string $as = 'image'): void
{
$url = static::assetLinkDetermine($imageUrl);
$preloadCode = '<link rel="preload" href="' . $url . '" as="' . $as . '" fetchpriority="high">';
$encoded = htmlentities($preloadCode, ENT_QUOTES, 'UTF-8');
$this->addHeaderCode($page, $encoded . PHP_EOL);
}
private function handlePatternImages(string $classes, string $pageKey, string $tadress, bool $isLcpCandidate = false): string
{
$themeUrl = $tadress . 'images/bg/';
$patterns = [
'bg-data-pattern-left' => [
'images' => ['data-pattern-left.png'],
'pos' => 'left center',
'size' => 'contain'
],
'bg-data-pattern-right' => [
'images' => ['data-pattern-right.png'],
'pos' => 'right center',
'size' => 'contain'
],
'bg-data-pattern-all' => [
'images' => ['data-pattern-left.png', 'data-pattern-right.png'],
'pos' => 'left center, right center',
'size' => '450px, 450px'
],
'bg-data-pattern-all-white' => [
'images' => ['data-pattern-left-white.png', 'data-pattern-right-white.png'],
'pos' => 'left center, right center',
'size' => '450px, 450px'
]
];
$inlineStyle = '';
$classArray = array_filter(explode(' ', $classes));
foreach ($patterns as $classKey => $data) {
if (in_array($classKey, $classArray)) {
if ($isLcpCandidate && self::$lcpHandled === false) {
foreach ($data['images'] as $img) {
$fullUrl = $themeUrl . $img;
$this->addPreloadLink($fullUrl, $pageKey);
}
}
$bgUrls = [];
foreach ($data['images'] as $img) {
$bgUrls[] = 'url(' . $themeUrl . $img . ')';
}
$inlineStyle = 'background-image: ' . implode(',', $bgUrls) . '!important; ';
if (isset($data['pos'])) {
$inlineStyle .= 'background-position: ' . $data['pos'] . '!important; ';
}
if (isset($data['size'])) {
$inlineStyle .= 'background-size: ' . $data['size'] . '!important; ';
}
break;
}
}
return $inlineStyle;
}
}
?>
FonPageBuilder.php lisans mekanizma oldugu yeri paylaştım
PHP:
private function runLicenseCheck($activate = false)
{
if (!function_exists('curl_init') || !function_exists('curl_exec') || !function_exists('curl_setopt')) {
self::$licenseStatus = false;
$this->error = self::$licenseError = 'PHP Curl Library not found';
return false;
}
$licenseFile = __DIR__ . DS . 'LICENSE';
$license_data = self::getLicenseFileData();
$config = include __DIR__ . DS . 'config.php';
$createdAt = (isset($config['created_at']) ? (int) $config['created_at'] : 0);
$cacheHash = (isset($config['settings']['cache_hash']) ? $config['settings']['cache_hash'] : '');
$decodedHash = (!empty($cacheHash) ? Crypt::decode($cacheHash, Config::get('crypt/system')) : '');
$isVerified = $decodedHash === $config['meta']['name'] . '_cache_secure_99';
if (!$activate && !empty($license_data) && isset($license_data['next-check-time'])) {
if (time() < strtotime($license_data['next-check-time'])) {
self::$licenseStatus = true;
return true;
}
}
$retryCount = (isset($license_data['retry-count']) ? (int) $license_data['retry-count'] : 0);
$documentRoot = realpath($_SERVER['DOCUMENT_ROOT']);
$currentDir = realpath(__DIR__);
if (strpos($currentDir, $documentRoot) !== 0) {
return false;
}
$domain = Utility::getDomain();
if (!$domain) {
if (isset($_SERVER['HTTP_X_BALANCED_HOST'])) {
$domain = str_replace('www.', '', $_SERVER['HTTP_X_BALANCED_HOST']);
}
else if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$domain = str_replace('www.', '', $_SERVER['HTTP_X_FORWARDED_HOST']);
}
else if (isset($_SERVER['HTTP_HOST'])) {
$domain = str_replace('www.', '', $_SERVER['HTTP_HOST']);
}
else {
$domain = str_replace('www.', '', $_SERVER['SERVER_NAME']);
}
}
$directory = __DIR__;
if (class_exists('UserManager')) {
$ip = UserManager::GetIP();
}
else {
$ip = static::getClientIP();
}
$server_ip = $_SERVER['SERVER_ADDR'];
if (($server_ip == '127.0.0.1') && isset($_SERVER['HTTP_X_TARGET_IP'])) {
$server_ip = $_SERVER['HTTP_X_TARGET_IP'];
}
$origin = (Utility::isSSL() ? 'https://' : 'http://');
$entered_url = $origin . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$entered_url = parse_url($entered_url);
unset($entered_url['query']);
$entered_url = $entered_url['scheme'] . '://' . $entered_url['host'] . rtrim($entered_url['path'], '/');
$referer_url = (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
if ($referer_url) {
$referer_url = parse_url($referer_url);
unset($referer_url['query']);
$referer_url = $referer_url['scheme'] . '://' . $referer_url['host'] . rtrim($referer_url['path'], '/');
}
$parameters = ['domain' => $domain, 'server_ip' => $server_ip, 'user_ip' => $ip, 'entered_url' => $entered_url, 'referer_url' => $referer_url, 'directory' => $directory];
$address = 'https://fononline.net/license/checking/d153d7b91000f4b1509484fb3b896d03/305?' . http_build_query($parameters);
$resultErr = false;
if (!file_exists($licenseFile) || empty($license_data)) {
$isOldInstall = 86400 < (time() - $createdAt);
$isFirstMigration = !isset($config['settings']['cache_hash']);
if ($isOldInstall || $isVerified) {
if (!$isFirstMigration) {
$result = self::useLicenseCurl($address, $resultErr, true);
if ($result['status'] !== 'success') {
self::$licenseStatus = false;
$this->error = self::$licenseError = 'Güvenlik doğrulaması yapılamadı. Lütfen internet bağlantınızı kontrol edin.';
return false;
}
}
}
}
if (!isset($result)) {
$result = self::useLicenseCurl($address, $resultErr, true);
}
if ($result['status'] !== 'success') {
Modules::save_log('Addons', __CLASS__, __FUNCTION__, $parameters, $address, $result);
$isHardError = ($result['message'] === 'ERROR') || $result['status'] == 'license_error';
if ($isHardError) {
self::setConfigVerified(false);
$report = self::useLicenseCurl('https://fononline.net/license/error?user_ip=' . $ip, $resultErr);
$rawError = $report['message'] ?: ($this->lang['license_error_message'] ?? 'Geçerli bir lisansınız yok.');
$errBody = static::getBodyFromCurlResponse($rawError);
if (!$errBody) {
$errBody = $rawError;
}
$this->error = self::$licenseError = $errBody;
$nextCheckTime = date('Y-m-d H:i:s', strtotime('+1 day'));
$gracePeriodEnd = date('Y-m-d H:i:s');
$retryCount = 0;
self::$licenseStatus = false;
}
else {
++$retryCount;
if ($retryCount <= 8) {
$nextCheckTime = date('Y-m-d H:i:s', strtotime('+3 hours'));
self::$licenseStatus = true;
$gracePeriodEnd = $nextCheckTime;
$rawError = $resultErr ?: ($this->lang['license_error_curl'] ?? 'Bağlantı sorunu, yeniden deneniyor.');
}
else {
$nextCheckTime = date('Y-m-d H:i:s', strtotime('+3 hours'));
$gracePeriodEnd = date('Y-m-d H:i:s');
self::$licenseStatus = false;
$rawError = $this->lang['license_error_timeout'] ?? 'Lisans sunucusuna ulaşılamadı. Lütfen sunucunuzun dış bağlantılarını kontrol edin.';
}
$errBody = static::getBodyFromCurlResponse($rawError);
if (!$errBody) {
$errBody = $rawError;
}
$this->error = self::$licenseError = $errBody;
}
$checkFileData = self::cryptChip('encrypt', Utility::jencode(['last-check-time' => date('Y-m-d H:i:s'), 'next-check-time' => $nextCheckTime, 'license-status' => self::$licenseStatus, 'grace-period-end' => $gracePeriodEnd, 'license-error' => $this->error, 'retry-count' => $retryCount]), 'a2dNeVRxQlJxaGpTUVNUUTZiT2xFM0VyeUJLYVF5YWIvQWtXLytQNTFiK01NR0prL2ZVSmgwTyt3dGhZYkJOdw==');
FileManager::file_write(__DIR__ . DS . 'LICENSE', $checkFileData);
self::getLicenseFileData(true);
return self::$licenseStatus;
}
if (isset($this) && $this instanceof self) {
$set_config = $this->config;
$rawValue = $set_config['meta']['name'] . '_cache_secure_99';
$set_config['settings']['cache_hash'] = Crypt::encode($rawValue, Config::get('crypt/system'));
$this->save_config($set_config);
$this->config = $set_config;
}
else {
self::setConfigVerified(true);
}
$checkFileData = self::cryptChip('encrypt', Utility::jencode(['last-check-time' => date('Y-m-d H:i:s'), 'next-check-time' => date('Y-m-d H:i:s', strtotime('+1 month')), 'license-status' => true, 'retry-count' => 0]), 'a2dNeVRxQlJxaGpTUVNUUTZiT2xFM0VyeUJLYVF5YWIvQWtXLytQNTFiK01NR0prL2ZVSmgwTyt3dGhZYkJOdw==');
FileManager::file_write(__DIR__ . DS . 'LICENSE', $checkFileData);
self::getLicenseFileData(true);
self::$licenseStatus = true;
self::$licenseError = '';
return true;
}
private static function getLicenseFileData($reload = false)
{
if ($reload || !static::$licenseTempFile) {
if (!file_exists(__DIR__ . DS . 'LICENSE')) {
return false;
}
$checkingFileData = FileManager::file_read(__DIR__ . DS . 'LICENSE');
if ($checkingFileData) {
$checkingFileData = self::cryptChip('decrypt', $checkingFileData, 'a2dNeVRxQlJxaGpTUVNUUTZiT2xFM0VyeUJLYVF5YWIvQWtXLytQNTFiK01NR0prL2ZVSmgwTyt3dGhZYkJOdw==');
if ($checkingFileData) {
static::$licenseTempFile = Utility::jdecode($checkingFileData, true);
return static::$licenseTempFile;
}
}
}
else {
return static::$licenseTempFile;
}
return false;
}
private static function cryptChip($action, $string, $salt = '')
{
if ($salt != 'a2dNeVRxQlJxaGpTUVNUUTZiT2xFM0VyeUJLYVF5YWIvQWtXLytQNTFiK01NR0prL2ZVSmgwTyt3dGhZYkJOdw==') {
return false;
}
$key = '0|.%J.MF4AMT$(.VU1J' . $salt . 'O1SbFd$|N83JG' . str_replace('www.', '', $_SERVER['SERVER_NAME']) . '.~&/-_f?fge&';
$output = false;
$encrypt_method = 'AES-256-CBC';
if (is_null($key)) {
$secret_key = 'NULL';
}
else {
$secret_key = $key;
}
$secret_iv = 'JxaGpTUVNUUTZiT2';
$key = hash('sha256', $secret_key);
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if ($action === 'encrypt') {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
else if ($action === 'decrypt') {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
private static function getClientIP()
{
$ipKeys = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
foreach ($ipKeys as $key) {
if (!empty($_SERVER[$key])) {
$ipList = preg_split('/[\\s,]+/', $_SERVER[$key]);
foreach ($ipList as $ip) {
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
}
return '0.0.0.0';
}
private static function useLicenseCurl($address, &$error_msg, $check = false)
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $address,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 3,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 20,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HEADER => true,
CURLOPT_NOBODY => false,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_USERAGENT => 'FonPageBuilder-License-Checker/2.0',
CURLOPT_RESOLVE => ['fononline.net:443:18.102.222.10']
]);
$response = curl_exec($curl);
$errNo = curl_errno($curl);
$error = curl_error($curl);
if ($errNo) {
$error_msg = 'Error Code: ' . $errNo . ' - ' . $error;
curl_close($curl);
return ['status' => 'timeout', 'code' => 'cURL', 'errno' => $errNo, 'message' => $error_msg];
}
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$body = trim(substr($response, $header_size));
if (!mb_check_encoding($body, 'UTF-8')) {
$body = mb_convert_encoding($body, 'UTF-8', 'ISO-8859-9');
}
curl_close($curl);
if ($httpCode == 200) {
if ($check) {
if ($body === 'OK') {
return ['status' => 'success', 'code' => $httpCode, 'message' => $body];
}
else {
return ['status' => 'license_error', 'code' => $httpCode, 'message' => $body];
}
}
return ['status' => 'error', 'code' => $httpCode, 'message' => $body];
}
else if (400 <= $httpCode) {
return ['status' => 'server_error', 'code' => $httpCode, 'message' => $body];
}
return ['status' => 'error', 'code' => $httpCode, 'message' => 'Unknown License Control Response'];
}
private static function getBodyFromCurlResponse($html)
{
if (empty($html)) {
return '';
}
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$utf8_header = '<?xml encoding="utf-8" ?>';
$doc->loadHTML($utf8_header . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOERROR | LIBXML_NOWARNING);
libxml_clear_errors();
$body = $doc->getElementsByTagName('body')->item(0);
if (!$body) {
$text = $doc->saveHTML();
}
else {
$text = $doc->saveHTML($body);
}
$text = strip_tags($text);
$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
$text = preg_replace('/\\s+/', ' ', $text);
return trim($text);
}
public function isLicenseValid(): bool
{
$licenseData = self::getLicenseFileData();
if (isset($licenseData['grace-period-end']) && time() < strtotime($licenseData['grace-period-end'])) {
return true;
}
return self::$licenseStatus === true;
}
private static function setConfigVerified($status = true)
{
$configPath = __DIR__ . DS . 'config.php';
if (!file_exists($configPath)) {
return false;
}
$config = include $configPath;
$rawValue = $config['meta']['name'] . '_cache_secure_99';
$hashValue = ($status ? Crypt::encode($rawValue, Config::get('crypt/system')) : '');
if (isset($config['settings']['cache_hash']) && $hashValue === $config['settings']['cache_hash']) {
return true;
}
$config['settings']['cache_hash'] = $hashValue;
$export = Utility::array_export($config, ['pwith' => true]);
return FileManager::file_write($configPath, $export);
}
public function create_error($error = '')
{
if ($error) {
Helper::Load(['Events']);
return Events::create([
'type' => 'info',
'owner' => 'system',
'owner_id' => '0',
'name' => 'module-addon-error',
'data' => ['name' => __CLASS__, 'message' => $error]
]);
}
return false;
}
private function disableAddon()
{
$config = $this->config;
$config['status'] = 0;
FileManager::file_write(__DIR__ . DS . 'config.php', Utility::array_export($config, ['pwith' => true]));
return true;
}
public function upgrade()
{
if (version_compare($this->version, $this->config['meta']['version'], '>')) {
$set_config = $this->config;
if (isset($set_config['created_at']) && $set_config['created_at'] == 1693916240) {
$set_config['created_at'] = time();
}
$set_config['meta']['version'] = $this->version;
$this->save_config($set_config);
$this->config = $set_config;
$dbPrefix = Config::get('database/prefix');
$tables = [$dbPrefix . 'categories' => 'mtime', $dbPrefix . 'pages' => 'mtime', $dbPrefix . 'knowledgebase' => 'mtime', $dbPrefix . 'fonpagebuilder' => 'mtime'];
foreach ($tables as $table => $column) {
$checkColumn = WDB::query('SHOW COLUMNS FROM `' . $table . '` LIKE \'' . $column . '\'')->rowCount();
if ($checkColumn == 0) {
WDB::query('ALTER TABLE `' . $table . '` ADD COLUMN `' . $column . '` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;');
}
}
$tblSuggestions = $dbPrefix . 'fon_ai_domain_suggestions';
if (!WDB::hasTable($tblSuggestions)) {
$sql = 'CREATE TABLE IF NOT EXISTS `' . $tblSuggestions . '` (' . "\r\n" . ' `id` INT AUTO_INCREMENT PRIMARY KEY,' . "\r\n" . ' `sorgu_hash` CHAR(32) NOT NULL,' . "\r\n" . ' `user_query` TEXT NOT NULL,' . "\r\n" . ' `engine` VARCHAR(30) NOT NULL DEFAULT \'\',' . "\r\n" . ' `model` VARCHAR(120) NOT NULL DEFAULT \'\',' . "\r\n" . ' `lang` CHAR(5) NOT NULL DEFAULT \'\',' . "\r\n" . ' `tlds` VARCHAR(255) NOT NULL DEFAULT \'\',' . "\r\n" . ' `ai_response` JSON NOT NULL,' . "\r\n" . ' `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,' . "\r\n" . ' FULLTEXT KEY `ft_query` (`user_query`),' . "\r\n" . ' INDEX `idx_hash` (`sorgu_hash`),' . "\r\n" . ' INDEX `idx_filter` (`engine`, `lang`)' . "\r\n" . ' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;';
if (!WDB::exec($sql)) {
$this->create_error = 'fon_ai_domain_suggestions veritabanı tablosu oluşturulamadı.';
}
}
$tblStats = $dbPrefix . 'fon_ai_stats';
if (!WDB::hasTable($tblStats)) {
$sql = 'CREATE TABLE IF NOT EXISTS `' . $tblStats . '` (' . "\r\n" . ' `id` INT AUTO_INCREMENT PRIMARY KEY,' . "\r\n" . ' `user_ip` VARCHAR(45) NOT NULL,' . "\r\n" . ' `engine` VARCHAR(30) NOT NULL DEFAULT \'\',' . "\r\n" . ' `model` VARCHAR(120) NOT NULL DEFAULT \'\',' . "\r\n" . ' `prompt_tokens` INT NOT NULL DEFAULT 0,' . "\r\n" . ' `completion_tokens` INT NOT NULL DEFAULT 0,' . "\r\n" . ' `total_tokens` INT NOT NULL DEFAULT 0,' . "\r\n" . ' `estimated_cost` DECIMAL(15,10) NOT NULL DEFAULT 0.0000000000,' . "\r\n" . ' `cache_hit` TINYINT(1) NOT NULL DEFAULT 0,' . "\r\n" . ' `similar_hit` TINYINT(1) NOT NULL DEFAULT 0,' . "\r\n" . ' `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,' . "\r\n" . ' INDEX `idx_created` (`created_at`),' . "\r\n" . ' INDEX `idx_engine` (`engine`)' . "\r\n" . ' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;';
if (!WDB::exec($sql)) {
$this->create_error = 'fon_ai_stats veritabanı tablosu oluşturulamadı.';
}
}
}
return true;
}
private static function logLicense($message)
{
$logFile = __DIR__ . '/license_debug.log';
$timestamp = date('Y-m-d H:i:s');
$logEntry = '[' . $timestamp . '] [IP: ' . $_SERVER['REMOTE_ADDR'] . '] [URL: ' . $_SERVER['REQUEST_URI'] . ('] ' . $message) . PHP_EOL;
file_put_contents($logFile, $logEntry, FILE_APPEND);
}
private static function diffDay($start = '', $end = '')
{
$dStart = new DateTime($start);
$dEnd = new DateTime($end);
$dDiff = $dStart->diff($dEnd);
return $dDiff->days;
}
private static function siteMapCategoryRoute($id, $lang)
{
$hierarchy = [];
$query = WDB::select('c.id, c.parent, cl.route');
$query->from('categories c');
$query->join('INNER', 'categories_lang cl', 'cl.owner_id = c.id');
$query->where('c.type', '=', 'products', '&&');
$query->where('cl.lang', '=', $lang, '&&');
$query->where('c.id', '=', $id);
$category = ($query->build() ? $query->getAssoc() : false);
while ($category) {
array_unshift($hierarchy, $category['route']);
if ($category['parent'] == 0) {
break;
}
$query = WDB::select('c.id, c.parent, cl.route');
$query->from('categories c');
$query->join('INNER', 'categories_lang cl', 'cl.owner_id = c.id');
$query->where('c.id', '=', $category['parent'], '&&');
$query->where('cl.lang', '=', $lang);
$category = $query->build(true)->getAssoc();
}
if (2 < count($hierarchy)) {
$hierarchy = array_slice($hierarchy, -2, 2, true);
}
return $hierarchy;
}
public function save_fields($fields = [])
{
return $fields;
}
public function activate()
{
$set_config = $this->config;
if (isset($set_config['created_at']) && $set_config['created_at'] == 1693916240) {
$set_config['created_at'] = time();
$this->save_config($set_config);
$this->config = $set_config;
}
$licenced = $this->runLicenseCheck(true);
if (!$licenced) {
return false;
}
if (!file_exists($this->imageFolder)) {
@mkdir($this->imageFolder, 511, true);
@touch($this->imageFolder . DS . 'index.html');
}
$operation = WDB::exec('CREATE TABLE IF NOT EXISTS `fonpagebuilder` (' . "\r\n\t\t\t\t" . ' `id` int(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,' . "\r\n\t\t\t\t" . ' `name` varchar(255) NOT NULL,' . "\r\n\t\t\t\t" . ' `type` varchar(100) NOT NULL,' . "\r\n\t\t\t\t" . ' `type_id` int(11) NOT NULL DEFAULT 0,' . "\r\n\t\t\t\t" . ' `page_options` text,' . "\r\n\t\t\t\t" . ' `page_content` longtext,' . "\r\n\t\t\t\t" . ' `page_style` text DEFAULT NULL,' . "\r\n\t\t\t\t" . ' `status` tinyint(1) NOT NULL DEFAULT 1,' . "\r\n\t\t\t\t" . ' `ctime` datetime NOT NULL DEFAULT current_timestamp(),' . "\r\n\t\t\t\t" . ' `mtime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' . "\r\n\t\t\t\t" . ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;' . "\r\n\t\t\t\t" . 'CREATE TABLE IF NOT EXISTS `fonpagebuilder_saved` (' . "\r\n\t\t\t\t" . ' `id` int(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,' . "\r\n\t\t\t\t" . ' `name` varchar(255) NOT NULL,' . "\r\n\t\t\t\t" . ' `type` varchar(100) NOT NULL,' . "\r\n\t\t\t\t" . ' `page_content` text DEFAULT NULL' . "\r\n\t\t\t\t" . ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;' . "\r\n\t\t\t");
if (!$operation) {
$this->error = $this->lang['database_not_created'] ?? 'Veritabanı oluşturulamadı: ';
return false;
}
return true;
}
public function deactivate()
{
$set = ['status' => 0];
$operation = Models::$init->db->update('fonpagebuilder');
$operation->set($set);
$operation->where('status', '=', '1');
$save = $operation->save();
return true;
}

