| Current Path : /home/chauffn/vuzelia/20230/components/com_sppagebuilder/controllers/ |
| Current File : /home/chauffn/vuzelia/20230/components/com_sppagebuilder/controllers/articles.php |
<?php
/**
* @package SP Page Builder
* @author JoomShaper http://www.joomshaper.com
* @copyright Copyright (c) 2010 - 2025 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\MVC\Controller\FormController;
use Joomla\CMS\Factory;
class SppagebuilderControllerArticles extends FormController
{
private function sendResponse($response, int $statusCode = 200)
{
return response()->json($response, $statusCode);
}
/**
* Load more articles for pagination
*
* @return void
* @since 6.0.0
*/
public function loadMoreArticles()
{
$app = Factory::getApplication();
$input = $app->input;
$rawData = file_get_contents('php://input');
$data = json_decode($rawData, true);
if (!$data) {
$this->sendResponse(['error' => 'Invalid JSON data'], 400);
return;
}
$addonId = $data['addon_id'] ?? '';
$limit = (int) ($data['limit'] ?? 5);
$ordering = $data['ordering'] ?? 'latest';
$catid = $data['catid'] ?? [];
$includeSubcat = (bool) ($data['include_subcat'] ?? true);
$postType = $data['post_type'] ?? '';
$tagids = $data['tagids'] ?? [];
$page = (int) ($data['page'] ?? 1);
$addonSettings = $data['addonSettings'] ?? [];
require_once JPATH_ROOT . '/components/com_sppagebuilder/helpers/articles.php';
try {
$items = SppagebuilderHelperArticles::getArticles(
$limit,
$ordering,
$catid,
$includeSubcat,
$postType,
$tagids,
1,
$page
);
if (empty($items)) {
$this->sendResponse(['data' => '', 'message' => 'No more articles']);
return;
}
$html = $this->renderArticlesHTML($items, $addonId, $addonSettings);
$this->sendResponse(['data' => $html, 'success' => true]);
} catch (Exception $e) {
$this->sendResponse(['error' => $e->getMessage()], 500);
}
}
/**
* Render articles HTML for pagination
*
* @param array $items The articles to render
* @param string $addonId The addon ID
* @param string $addonSettings The addon settings JSON
* @return string The rendered HTML
* @since 6.0.0
*/
private function renderArticlesHTML($items, $addonId, $addonSettings)
{
$html = '';
$addonId = $addonId ?? null;
$settings = json_decode($addonSettings, true);
$layout = $settings['layout'] ?? 'default';
$columns_lg = !empty($settings['columns_original']['xl']) ? $settings['columns_original']['xl'] : 3;
$columns_md = !empty($settings['columns_original']['lg']) ? $settings['columns_original']['lg'] : $columns_lg;
$columns_sm = !empty($settings['columns_original']['md']) ? $settings['columns_original']['md'] : $columns_md;
$columns_xs = !empty($settings['columns_original']['sm']) ? $settings['columns_original']['sm'] : 2;
$columns = !empty($settings['columns_original']['xs']) ? $settings['columns_original']['xs'] : 1;
$article_heading_selector = $settings['article_heading_selector'] ?? 'h3';
$show_intro = (int) ($settings['show_intro'] ?? 1);
$intro_limit = (int) ($settings['intro_limit'] ?? 200);
$hide_thumbnail = (int) ($settings['hide_thumbnail'] ?? 0);
$show_author = (int) ($settings['show_author'] ?? 1);
$show_tags = (int) ($settings['show_tags'] ?? 1);
$show_category = (int) ($settings['show_category'] ?? 1);
$show_date = (int) ($settings['show_date'] ?? 1);
$show_readmore = (int) ($settings['show_readmore'] ?? 1);
$readmore_text = $settings['readmore_text'] ?? 'Read More';
$thumb_size = $settings['thumb_size'] ?? 'image_thumbnail';
$show_date_text = $settings['show_date_text'] ?? '';
$show_last_modified_date = (int) ($settings['show_last_modified_date'] ?? 0);
$show_last_modified_date_text = $settings['show_last_modified_date_text'] ?? '';
$show_custom_field = (int) ($settings['show_custom_field'] ?? 0);
$version = new \Joomla\CMS\Version();
$JoomlaVersion = $version->getShortVersion();
$article_modified_date = \Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_modify_date');
$article_created_date = \Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_publish_date');
$layoutWrapperCls = 'sppb-addon-article-layout ';
$layoutContentCls = 'sppb-addon-article-layout-content ';
if ($layout === 'default' || $layout === '' || $layout === null) {
$layoutWrapperCls .= 'sppb-col-xs-' . round(12 / $columns_xs) . ' sppb-col-sm-' . round(12 / $columns_sm) . ' sppb-col-md-' . round(12 / $columns_md) . ' sppb-col-lg-' . round(12 / $columns_lg) . ' sppb-col-' . round(12 / $columns);
}
if ($layout === 'editorial') {
$layoutWrapperCls .= ' sppb-addon-article-layout-editorial-wrapper';
$layoutContentCls .= ' sppb-addon-article-layout-editorial-content';
} elseif ($layout === 'side') {
$layoutWrapperCls .= ' sppb-col-12 sppb-addon-article-layout-side-wrapper';
$layoutContentCls .= ' sppb-addon-article-layout-side-content';
} elseif ($layout === 'magazine') {
$layoutWrapperCls .= ' sppb-addon-article-layout-magazine-wrapper';
$layoutContentCls .= ' sppb-addon-article-layout-magazine-content';
} elseif ($layout === 'masonry') {
$layoutWrapperCls .= ' sppb-addon-article-layout-masonry-wrapper';
$layoutContentCls .= ' sppb-addon-article-layout-masonry-content';
}
foreach ($items as $key => $item) {
$html .= '<div class="' . $layoutWrapperCls . '">';
$html .= '<div class="sppb-addon-article ' . $layoutContentCls . '">';
if (!$hide_thumbnail) {
$image = $item->{$thumb_size} ?? $item->image_thumbnail;
if ($item->post_format === 'gallery') {
if (count((array) $item->imagegallery->images)) {
$html .= '<div class="sppb-carousel sppb-slide" data-sppb-ride="sppb-carousel">';
$html .= '<div class="sppb-carousel-inner">';
foreach ($item->imagegallery->images as $key => $gallery_item) {
$active_class = '';
if ($key == 0) {
$active_class = ' active';
}
if (isset($gallery_item['thumbnail']) && $gallery_item['thumbnail']) {
$html .= '<div class="sppb-item' . $active_class . '">';
$html .= '<img src="' . $gallery_item['thumbnail'] . '" alt="">';
$html .= '</div>';
} elseif (isset($gallery_item['full']) && $gallery_item['full']) {
$html .= '<div class="sppb-item' . $active_class . '">';
$html .= '<img src="' . $gallery_item['full'] . '" alt="">';
$html .= '</div>';
}
}
$html .= '</div>';
if ($layout !== 'magazine') {
$html .= '<a class="left sppb-carousel-control" role="button" data-slide="prev" aria-label="Previous"><i class="fa fa-angle-left" aria-hidden="true"></i></a>';
$html .= '<a class="right sppb-carousel-control" role="button" data-slide="next" aria-label="Next"><i class="fa fa-angle-right" aria-hidden="true"></i></a>';
}
$html .= '</div>';
} elseif (isset($item->image_thumbnail) && $item->image_thumbnail) {
$placeholder = $item->image_thumbnail == '' ? false : $this->get_image_placeholder($item->image_thumbnail);
$img_obj = json_decode($item->images);
$img_obj_helix = json_decode($item->attribs);
$img_blog_op_alt_text = (isset($img_obj->image_intro_alt) && $img_obj->image_intro_alt) ? $img_obj->image_intro_alt : "";
$img_helix_alt_text = (isset($img_obj_helix->helix_ultimate_image_alt_txt) && $img_obj_helix->helix_ultimate_image_alt_txt) ? $img_obj_helix->helix_ultimate_image_alt_txt : "";
$img_alt_text = "";
if ($img_helix_alt_text) {
$img_alt_text = $img_helix_alt_text;
} else if ($img_blog_op_alt_text) {
$img_alt_text = $img_blog_op_alt_text;
} else {
$img_alt_text = $item->title;
}
$html .= '<a href="' . $item->link . '" itemprop="url"><img class="sppb-img-responsive' . ($placeholder ? ' sppb-element-lazy' : '') . '" src="' . ($placeholder ? $placeholder : $item->image_thumbnail) . '" alt="' . $img_alt_text . '" itemprop="thumbnailUrl" ' . ($placeholder ? 'loading="lazy" data-large="' . $image . '"' : '') . '></a>';
}
} elseif ($item->post_format == 'video' && isset($item->video_src) && $item->video_src) {
$html .= '<div class="entry-video embed-responsive embed-responsive-16by9">';
$html .= '<object class="embed-responsive-item" style="width:100%;height:100%;" data="' . $item->video_src . '">';
$html .= '<param name="movie" value="' . $item->video_src . '">';
$html .= '<param name="wmode" value="transparent" />';
$html .= '<param name="allowFullScreen" value="true">';
$html .= '<param name="allowScriptAccess" value="always"></param>';
$html .= '<embed src="' . $item->video_src . '" type="application/x-shockwave-flash" allowscriptaccess="always"></embed>';
$html .= '</object>';
$html .= '</div>';
} elseif ($item->post_format == 'audio' && isset($item->audio_embed) && $item->audio_embed) {
$html .= '<div class="entry-audio embed-responsive embed-responsive-16by9">';
$html .= $item->audio_embed;
$html .= '</div>';
} elseif ($item->post_format == 'link' && isset($item->link_url) && $item->link_url) {
$html .= '<div class="entry-link">';
$html .= '<a target="_blank" rel="noopener noreferrer" href="' . $item->link_url . '"><h4>' . $item->link_title . '</h4></a>';
$html .= '</div>';
} else {
if (isset($image) && $image) {
$default_placeholder = $image == '' ? false : $this->get_image_placeholder($image);
$img_obj = json_decode($item->images);
$img_obj_helix = json_decode($item->attribs);
$img_blog_op_alt_text = (isset($img_obj->image_intro_alt) && $img_obj->image_intro_alt) ? $img_obj->image_intro_alt : "";
$img_helix_alt_text = (isset($img_obj_helix->helix_ultimate_image_alt_txt) && $img_obj_helix->helix_ultimate_image_alt_txt) ? $img_obj_helix->helix_ultimate_image_alt_txt : "";
$img_alt_text = "";
if ($img_helix_alt_text) {
$img_alt_text = $img_helix_alt_text;
} else if ($img_blog_op_alt_text) {
$img_alt_text = $img_blog_op_alt_text;
} else {
$img_alt_text = $item->title;
}
$html .= '<a class="sppb-article-img-wrap" href="' . $item->link . '" itemprop="url"><img class="sppb-img-responsive' . ($default_placeholder ? ' sppb-element-lazy' : '') . '" src="' . ($default_placeholder ? $default_placeholder : $image) . '" alt="' . $img_alt_text . '" itemprop="thumbnailUrl" ' . ($default_placeholder ? 'loading="lazy" data-large="' . $image . '"' : '') . '></a>';
}
}
}
$html .= '<div class="sppb-article-info-wrap" role="article">';
$html .= '<' . $article_heading_selector . '><a href="' . $item->link . '" itemprop="url">' . $item->title . '</a></' . $article_heading_selector . '>';
if ($show_author || $show_category || $show_date || $show_tags) {
$html .= '<div class="sppb-article-meta">';
if ($show_date) {
$date = ($article_created_date) ? \Joomla\CMS\HTML\HTMLHelper::_('date', $item->publish_up, 'DATE_FORMAT_LC3') : '<p class="alert alert-warning">Date display is disabled in Joomla settings</p>';
$date_text = ($show_date_text) ? '<b>' . $show_date_text . ': </b>' : '';
$date_format = ($article_created_date) ? \Joomla\CMS\HTML\HTMLHelper::_('date', $item->publish_up, 'c') : '';
$html .= '<time datetime="' . $date_format . '" class="sppb-meta-date sppb-meta-date-unmodified">' . $date_text . $date . '</time>';
}
if ($show_last_modified_date) {
$modify_date = ($article_modified_date) ? \Joomla\CMS\HTML\HTMLHelper::_('date', $item->modified, 'DATE_FORMAT_LC3') : '<p class="alert alert-warning">Modified date display is disabled in Joomla settings</p>';
$modify_text = ($show_last_modified_date_text) ? '<b>' . $show_last_modified_date_text . ': </b>' : '';
$modify_date_format = ($article_modified_date) ? \Joomla\CMS\HTML\HTMLHelper::_('date', $item->modified, 'c') : '';
$html .= '<time datetime="' . $modify_date_format . '" class="sppb-meta-date sppb-meta-date-modified">' . $modify_text . $modify_date . '</time>';
}
if ($show_category) {
$item->catUrl = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getCategoryRoute($item->catslug));
$html .= '<span class="sppb-meta-category"><a href="' . $item->catUrl . '" itemprop="genre">' . $item->category . '</a></span>';
}
if ($show_author) {
$author = ($item->created_by_alias ? $item->created_by_alias : $item->username);
$html .= '<span class="sppb-meta-author" itemprop="name">' . $author . '</span>';
}
if ($show_tags) {
$tagLayout = new \Joomla\CMS\Layout\FileLayout('joomla.content.tags');
$html .= $tagLayout->render($item->tags->itemTags);
}
$html .= '</div>';
}
if ($show_custom_field) {
if ((float) $JoomlaVersion >= 4) {
\JLoader::registerAlias('FieldsHelper', 'Joomla\Component\Fields\Administrator\Helper\FieldsHelper');
} else {
\JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
}
$custom_fields = FieldsHelper::getFields('com_content.article', $item);
$this->renderCustomFields($custom_fields);
$html .= FieldsHelper::render(
'com_content.article',
'fields.render',
array(
'context' => 'com_content.article',
'item' => $item,
'fields' => $custom_fields,
)
);
}
if ($show_intro) {
if (!isset($custom_fields)) {
if ((float) $JoomlaVersion >= 4) {
\JLoader::registerAlias('FieldsHelper', 'Joomla\Component\Fields\Administrator\Helper\FieldsHelper');
} else {
\JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
}
$custom_fields = FieldsHelper::getFields('com_content.article', $item);
$this->renderCustomFields($custom_fields);
}
$introtext = $this->replaceFieldShortcodes($item->introtext, $custom_fields);
$html .= '<div class="sppb-article-introtext">' . $this->truncateHtml($introtext, $intro_limit) . '</div>';
}
if ($show_readmore) {
$max_title_characters = 25;
$aria_label = strlen($item->title) > $max_title_characters ? mb_substr(strip_tags($item->title), 0, $max_title_characters, 'UTF-8') . '...' : strip_tags($item->title);
$full_aria_label = 'Read more about ' . $aria_label;
$html .= '<a class="sppb-readmore" href="' . $item->link . '" aria-label="' . $full_aria_label . '" itemprop="url">' . $readmore_text . '</a>';
}
$html .= '</div>'; // .sppb-article-info-wrap
$html .= '</div>';
$html .= '</div>';
}
return $html;
}
/**
* Truncate HTML content
*
* @param string $html The HTML content
* @param int $limit The character limit
* @return string The truncated HTML
* @since 6.0.0
*/
private function truncateHtml($html, $limit)
{
if (empty($html)) {
return '';
}
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$content = '';
$charCount = 0;
$this->traverseNodes($dom->documentElement, $content, $charCount, $limit);
return $content;
}
/**
* Traverse DOM nodes for HTML truncation
*
* @param DOMNode $node The DOM node
* @param string $content The content string
* @param int $charCount The character count
* @param int $limit The character limit
* @return void
* @since 6.0.0
*/
private function traverseNodes($node, &$content, &$charCount, $limit)
{
foreach ($node->childNodes as $child) {
if ($child->nodeType == XML_TEXT_NODE) {
$text = $child->textContent;
$remainingChars = $limit - $charCount;
if (mb_strlen($text) <= $remainingChars) {
$content .= htmlspecialchars($text);
$charCount += mb_strlen($text);
} else {
$content .= htmlspecialchars(mb_substr($text, 0, $remainingChars)) . '...';
$charCount = $limit;
return;
}
} elseif ($child->nodeType == XML_ELEMENT_NODE) {
$content .= '<' . $child->nodeName;
if ($child->hasAttributes()) {
foreach ($child->attributes as $attr) {
$content .= ' ' . $attr->nodeName . '="' . htmlspecialchars($attr->nodeValue) . '"';
}
}
$content .= '>';
$this->traverseNodes($child, $content, $charCount, $limit);
$content .= '</' . $child->nodeName . '>';
if ($charCount >= $limit) return;
}
}
}
/**
* Replace field shortcodes in text
*
* @param string $text The text content
* @param array $custom_fields The custom fields
* @return string The processed text
* @since 6.0.0
*/
private function replaceFieldShortcodes($text, $custom_fields)
{
$fieldMap = [];
foreach ($custom_fields as $field) {
if (isset($field->id)) {
$fieldMap[$field->id] = $field->value;
}
}
return preg_replace_callback('/\{field\s+(\d+)\}/', function($matches) use ($fieldMap) {
$fieldId = $matches[1];
return isset($fieldMap[$fieldId]) ? $fieldMap[$fieldId] : '';
}, $text);
}
/**
* Render custom fields
*
* @param array $custom_fields The custom fields
* @since 6.0.0
*/
private function renderCustomFields(&$custom_fields)
{
foreach ($custom_fields as $custom_field) {
if (!empty($custom_field->type) && $custom_field->type === 'url' && !empty($custom_field->value)) {
$custom_field->value = '<a href="' . $custom_field->value . '">' . $custom_field->value . '</a>';
}
if (!empty($custom_field->type) && $custom_field->type === 'media' && !empty($custom_field->value)) {
$media = json_decode($custom_field->value);
if (isset($media->imagefile) && !empty($media->imagefile)) {
$custom_field->value = '<img src="' . $media->imagefile . '" alt="' . htmlspecialchars($media->alt_text, ENT_QUOTES, 'UTF-8') . '" />';
} else {
$custom_field->value = '';
}
}
if(!empty($custom_field->type) && $custom_field->type === 'calendar' && !empty($custom_field->value)) {
$date = explode(' ', $custom_field->value)[0];
$custom_field->value = '<span>' . $date . '</span>';
}
if(!empty($custom_field->type) && $custom_field->type === 'checkboxes' && !empty($custom_field->value)){
$values = $custom_field->value;
$updated_values = [];
$checkbox_values = $custom_field->fieldparams->get('options', []);
if(is_array($values)) {
foreach($values as $value){
foreach($checkbox_values as $option){
if($option->value === $value){
$updated_values[] = $option->name;
}
}
}
} else {
foreach($checkbox_values as $option){
if($option->value === $values){
$updated_values = $option->name;
break;
}
}
}
if(is_array($updated_values)){
$custom_field->value = implode(', ', $updated_values);
} else {
$custom_field->value = $updated_values;
}
}
if(!empty($custom_field->type) && $custom_field->type === 'radio' && !empty($custom_field->value)){
$radio_values = $custom_field->fieldparams->get('options', []);
foreach($radio_values as $option){
if($option->value === $custom_field->value){
$custom_field->value = $option->name;
break;
}
}
}
if(!empty($custom_field->type) && $custom_field->type === 'list' && !empty($custom_field->value)){
$list_values = $custom_field->fieldparams->get('options', []);
foreach($list_values as $option){
if($option->value === $custom_field->value){
$custom_field->value = $option->name;
break;
}
}
}
if(!empty($custom_field->type) && $custom_field->type === 'user' && !empty($custom_field->value)){
$user = \Joomla\CMS\Factory::getUser((int)$custom_field->value);
$custom_field->value = $user->name ?? '';
}
if(!empty($custom_field->type) && $custom_field->type === 'usergrouplist' && !empty($custom_field->value)){
$db = \Joomla\CMS\Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('title'))
->from($db->quoteName('#__usergroups'))
->where($db->quoteName('id') . ' = ' . (int) $custom_field->value);
$db->setQuery($query);
$groupName = $db->loadResult();
$custom_field->value = $groupName ? $groupName : '';
}
}
}
/**
* Get image placeholder for lazy loading
*
* @param string $src The image source
* @return mixed The placeholder path or false
* @since 6.0.0
*/
protected function get_image_placeholder($src)
{
$config = \Joomla\CMS\Component\ComponentHelper::getParams('com_sppagebuilder');
$lazyload = $config->get('lazyloadimg', '0');
if ($lazyload)
{
$filename = basename($src);
$mediaPath = 'media/com_sppagebuilder/placeholder';
$basePath = JPATH_ROOT . '/' . $mediaPath . '/' . $filename;
$defaultImg = 'https://sppagebuilder.com/addons/image/image1.jpg';
if (\Joomla\CMS\Filesystem\File::exists($basePath))
{
return $mediaPath . '/' . $filename;
}
else
{
return $defaultImg;
}
}
return false;
}
}