<?php
/********************************************************************
Product : Simple Tabs Plugin
Date : 1 December 2023
Copyright : Les Arbres Design 2022-2023
Contact : https://www.lesarbresdesign.info
Licence : GNU General Public License
*********************************************************************/
defined('_JEXEC') or die('Restricted Access');
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Factory;
use Joomla\CMS\Utility\Utility;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Language\Text;
class plgContentsimpletabs extends CMSPlugin
{
//-------------------------------------------------------------------------------
// Joomla calls this for every article so we must determine as quickly as possible
// if there are any calls for us in this article
//
function onContentPrepare($context, &$article, &$plugin_params, $limitstart=null)
{
$app = Factory::getApplication();
if (!$app->isClient('site'))
return;
if (empty($article->text))
return;
if (strpos($article->text, '{tab ') === false)
return;
$document = $app->getDocument();
if ($document instanceof \Joomla\CMS\Document\HtmlDocument)
$doc_type = 'html';
else
$doc_type = '';
// load our CSS and JS
$css = '/media/plg_simpletabs/simpletabs.css';
$override_css = '/media/plg_simpletabs/_simpletabs.css';
if (file_exists(JPATH_SITE.$override_css))
$css = $override_css;
if (file_exists(JPATH_SITE.$css))
{
$ftime = @filemtime(JPATH_SITE.$css);
if (!$ftime)
$ftime = '0';
if ($doc_type == 'html')
$document->addStyleSheet(URI::root(true).$css.'?'.$ftime);
}
if ($doc_type == 'html')
$document->addScript(URI::root(true).'/media/plg_simpletabs/simpletabs.js?104');
static $set_num = 1; // needed to handle multiple articles on the same page
// if there is a "tab" URL variable, we'll try to find the matching tab and open it
$jinput = Factory::getApplication()->input;
$url_tab = $jinput->get('tab', '', 'string');
$url_tab = strtolower(str_replace(' ','',$url_tab));
// get a list of all tab tags including {tab-whatever}...{/tabs-whatever}
// for nested tab syntax see https://docs3.regularlabs.com/tabs/going-further/nested-tabs#syntax
$tabnames[] = 'tab';
$regex = "#\{(tab\-\S*).*?\}#s";
if (preg_match_all($regex, $article->text, $matches))
foreach (array_unique($matches[1]) as $subset)
$tabnames[] = $subset;
$tabnames = array_reverse($tabnames);
// get an array of {tab...} tags in the article
foreach ($tabnames as $tabname)
{
$close_tag = substr($tabname,0,3).'s'.substr($tabname,3);
$regex = '#{'.$tabname.'\s(.*?)}|{/'.$close_tag.'}#s';
if (preg_match_all($regex, $article->text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE) == 0)
continue;
$first_offset = $matches[0][0][1]; // get the text before the first {tab call
$new_text = substr($article->text, 0, $first_offset);
// for each call, generate the tab structure
$tab_num = 1;
$tab_text = '<div class="sst-outer">';
$content_text = '';
foreach ($matches as $i => $match)
{
$call = $match[0][0]; // e.g. {tab title="Blah blah blah" class="blue" open="true"} or {/tabs}
$params = self::parse($call, $tabname, $tab_num);
$alias = $params['alias'];
if (empty($alias))
$alias = $set_num.'-'.$tab_num;
if (!strstr($call, '{/'.$close_tag.'}') && (!empty($url_tab) && ($url_tab == $alias)))
$params['open'] = 'true'; // URL param takes precedence over plugin param
$call_offset = $match[0][1];
$call_offset_end = $call_offset + strlen($call);
if (isset($matches[$i+1]))
{
$next_match_offset = $matches[$i+1][0][1];
$content_length = $next_match_offset - $call_offset_end;
$content = substr($article->text,$call_offset_end,$content_length);
}
else
$content = substr($article->text,$call_offset_end); // take the rest of the buffer
if (strstr($call, '{/'.$close_tag.'}'))
{
$tab_text .= '</div>'; // close the tab controls
$new_text .= $tab_text; // add tab controls to output buffer
$new_text .= $content_text; // add content divs to output buffer
$new_text .= $content; // add any text after {/tabs}
$tab_text = '<div class="sst-outer">'; // ready for another set of tabs
$content_text = '';
$set_num ++;
$tab_num = 1;
continue;
}
if ($params['open'] == 'true')
$tab_class = ' class="sst-title sstt-iopen sstt-'.$set_num.' '.$params['class'].'"';
else
$tab_class = ' class="sst-title sstt-'.$set_num.' '.$params['class'].'"';
$tab_text .= '<div id="sstt-'.$set_num.'-'.$tab_num.'"'.$tab_class.' data-set="'.$set_num.'" data-tab="'.$tab_num.'" data-alias="'.$alias.'">'.$params['title'].'</div>';
$content_text .= '<div id="sstc-'.$set_num.'-'.$tab_num.'" class="sst-content sstc-'.$set_num.' '.$params['class'].'">'.$content.'</div>';
$tab_num ++;
}
$article->text = $new_text;
}
}
//-------------------------------------------------------------------------------
// Parse and validate the plugin parameters, which may be in two formats:
// {tab This Is The Title}
// {tab title="This Is The Title" alias="tab-1" open="true" class="blue"}
//
static function parse($call, $tabname, $tab_num)
{
$offset = strlen($tabname) + 2;
if (!strstr($call, '='))
$params['title'] = substr($call, $offset, -1);
else
$params = Utility::parseAttributes($call);
if (!isset($params['title'])) $params['title'] = Text::_('JNONE');
if (!isset($params['open']))
if ($tab_num == 1)
$params['open'] = 'true';
else
$params['open'] = 'false';
if (!isset($params['class'])) $params['class'] = '';
if (empty($params['alias']))
{
$title = strip_tags($params['title']);
$title = strtolower(str_replace(' ', '-', $title));
$params['alias'] = trim(preg_replace('/[^a-z0-9\-]/', '', $title),'-');
}
return $params;
}
}