| Server IP : 46.105.57.169 / Your IP : 216.73.216.144 Web Server : Apache System : Linux webd003.cluster120.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : maitricfuz ( 93378) PHP Version : 8.4.10 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/maitricfuz/www/saint-martin-lg/plugins/system/nrframework/fields/ |
Upload File : |
<?php
/**
* @author Tassos Marinos <info@tassos.gr>
* @link https://www.tassos.gr
* @copyright Copyright © 2024 Tassos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
// No direct access to this file
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
require_once __DIR__ . '/ajaxify.php';
/*
* Creates an AJAX-based dropdown
* https://select2.org/
*/
class JFormFieldComponentItems extends JFormFieldAjaxify
{
/**
* List of allowed query presets
*
* @var array
*/
protected static $queryPresets = null;
/**
* Single items table name
*
* @var string
*/
protected $table;
/**
* Primary key column of the single items table
*
* @var string
*/
protected $column_id = 'id';
/**
* The title column of the single items table
*
* @var string
*/
protected $column_title = 'title';
/**
* The state column of the single items table
*
* @var string
*/
protected $column_state = 'state';
/**
* Pass extra where SQL statement
*
* @var string
*/
protected $where;
/**
* Pass extra join SQL statement
*
* @var string
*/
protected $join;
/**
* Pass extra group SQL statement
*
* @var string
*/
protected $query_group;
/**
* The Joomla database object
*
* @var object
*/
protected $db;
/**
* Query preset identifier
*/
protected $preset;
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
*
* @return boolean True on success.
*
* @since 3.2
*/
public function setup(SimpleXMLElement $element, $value, $group = null)
{
if ($return = parent::setup($element, $value, $group))
{
$this->init();
}
return $return;
}
public function init()
{
if ($this->element['preset'])
{
$this->preset = (string) $this->element['preset'];
}
else
{
// Backward compatibility: Support preset detection based on the old field XML elements
$this->preset = self::findPresetByConfig([
'table' => (string) $this->element['table'] ?? 'content',
'column_id' => (string) $this->element['column_id'],
'column_title' => (string) $this->element['column_title'],
'column_state' => (string) $this->element['column_state'],
'where' => (string) $this->element['where'],
'join' => (string) $this->element['join'],
'group' => (string) $this->element['group']
]);
}
// Get query configuration from preset
$queryConfig = $this->getPresetConfig();
$this->table = $queryConfig['table'];
$this->column_id = $this->prefix($queryConfig['column_id']);
$this->column_title = $this->prefix($queryConfig['column_title']);
$this->column_state = $this->prefix($queryConfig['column_state']);
$this->where = $queryConfig['where'] ?? null;
$this->join = $queryConfig['join'] ?? null;
$this->query_group = $queryConfig['group'] ?? null;
$this->append_id_to_label = isset($this->element['append_id_to_label'])
&& (string) $this->element['append_id_to_label'] === 'true';
if (!isset($this->element['placeholder']) && isset($this->element['description']))
{
$this->placeholder = (string) $this->element['description'];
}
// Initialize database Object
$this->db = Factory::getContainer()->get(Joomla\Database\DatabaseInterface::class);
}
/**
* Get ComponentItems AJAX endpoint URL
*/
protected function getAjaxEndpoint()
{
$payload = $this->createAjaxHandlerPayload();
return URI::base() . '?option=com_ajax&format=raw&plugin=nrframework&' . http_build_query($payload);
}
/**
* Create the payload for the AJAX request handler
*/
protected function createAjaxHandlerPayload()
{
return [
'handler' => 'ComponentItems',
Session::getFormToken() => 1,
'preset' => $this->preset,
'append_id_to_label' => $this->append_id_to_label ? 1 : 0
];
}
private function prefix($string)
{
if (strpos($string, '.') === false)
{
$string = 'i.' . $string;
}
return $string;
}
protected function getTemplateResult()
{
return '<span class="row-text">\' + state.text + \'</span><span style="float:right; opacity:.7">\' + state.id + \'</span>';
}
protected function getItemsQuery()
{
$db = $this->db;
$query = $this->getQuery()
->order($db->quoteName($this->column_id) . ' DESC');
if ($this->limit > 0)
{
// Joomla uses offset
$page = $this->page - 1;
$query->setLimit($this->limit, $page * $this->limit);
}
return $query;
}
protected function getItems()
{
$db = $this->db;
$db->setQuery($this->getItemsQuery());
$results = $db->loadObjectList();
if ($this->append_id_to_label && !empty($results))
{
foreach ($results as &$item)
{
$item->text = $item->text . ' (' . $item->id . ')';
}
}
return $results;
}
protected function getItemsTotal()
{
$db = $this->db;
$subQuery = $this->getQuery()
->clear('select')
->select($this->column_id);
if ($this->query_group)
{
$subQuery = $this->getQuery()
->clear('group')
->group($this->column_id);
}
$subQuery = (string) $subQuery;
$query = $db->getQuery(true)
->select('COUNT(*)')
->from("($subQuery) AS x");
$db->setQuery($query);
return (int) $db->loadResult();
}
protected function getQuery()
{
$db = $this->db;
$query = $db->getQuery(true)
->select([
$db->quoteName($this->column_id, 'id'),
$db->quoteName($this->column_title, 'text'),
$db->quoteName($this->column_state, 'state')
])
->from($db->quoteName('#__' . $this->table, 'i'));
if (!empty($this->search_term))
{
$query->where($db->quoteName($this->column_title) . ' LIKE ' . $db->quote('%' . $this->search_term . '%'));
}
if ($this->join)
{
$query->join('INNER', $this->join);
}
if ($this->where)
{
$query->where($this->where);
}
if ($this->query_group)
{
$query->group($this->query_group);
}
return $query;
}
protected function validateOptions($options)
{
$db = $this->db;
// Cast all options to integers before imploding
$safeOptions = array_map('intval', $options);
$query = $this->getQuery()
->where($db->quoteName($this->column_id) . ' IN (' . implode(',', $safeOptions) . ')');
$db->setQuery($query);
$results = $db->loadAssocList('id', 'text');
if ($this->append_id_to_label && !empty($results))
{
foreach ($results as $id => &$text)
{
$text = $text . ' (' . $id . ')';
}
}
return $results;
}
/**
* Factory method to create the appropriate ComponentItems field instance based on query preset
*
* @param string $preset Preset identifier (e.g., 'jshopping', 'virtuemart', 'content')
* @return JFormFieldComponentItems|JFormFieldJShoppingComponentItems|JFormFieldVirtueMartComponentItems
*/
public static function createInstance($preset = 'content')
{
// Map of presets that point to subclasses of ComponentItems
static $specialHandlers = [
'jshopping' => [
'class' => 'JFormFieldJShoppingComponentItems',
'file' => 'jshoppingcomponentitems.php'
],
'virtuemart' => [
'class' => 'JFormFieldVirtueMartComponentItems',
'file' => 'virtuemartcomponentitems.php'
]
];
if (isset($specialHandlers[$preset]))
{
$handler = $specialHandlers[$preset];
require_once __DIR__ . '/' . $handler['file'];
return new $handler['class']();
}
// Default to standard ComponentItems
return new self();
}
/**
* Initializes query presets map
*
* @return array
*/
protected static function getQueryPresetsMap()
{
if (self::$queryPresets !== null)
{
return self::$queryPresets;
}
self::$queryPresets = [
'content' => [
'default' => [
'table' => 'content',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'state'
],
'published' => [
'table' => 'content',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'state',
'where' => 'i.state >= 0'
]
],
'tags' => [
'default' => [
'table' => 'tags',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.published = 1 AND i.alias != \'root\' AND i.level > 0'
],
'acf' => [
'table' => 'tags',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.published = 1 AND i.alias != \'root\''
]
],
'users' => [
'default' => [
'table' => 'users',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'block',
'where' => 'i.block = 0'
],
'authors' => [
'table' => 'users',
'column_id' => 'id',
'column_title' => 'i.name',
'column_state' => 'i.block',
'join' => '#__content as c ON c.created_by = i.id',
'group' => 'i.id'
]
],
'hikashop' => [
'table' => 'hikashop_product',
'column_id' => 'product_id',
'column_title' => 'product_name',
'column_state' => 'product_published'
],
'k2items' => [
'table' => 'k2_items',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.trash = 0'
],
'rseventspro' => [
'table' => 'rseventspro_events',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'published'
],
'jreviews' => [
'table' => 'jreviews_content',
'column_id' => 'c.id',
'column_title' => 'c.title',
'column_state' => 'c.state',
'join' => '#__content as c ON c.id = i.contentid',
'where' => 'c.state >= 0'
],
'dpcalendar' => [
'table' => 'dpcalendar_events',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'state'
],
'j2store' => [
'table' => 'j2store_products',
'column_id' => 'j2store_product_id',
'column_title' => 'c.title',
'column_state' => 'c.state',
'join' => '#__content as c ON i.product_source_id = c.id',
'where' => "i.product_source='com_content' AND c.state >= 0"
],
'zoo' => [
'table' => 'zoo_item',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'state'
],
'icagenda' => [
'table' => 'icagenda_events',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'state'
],
'sppagebuilder' => [
'table' => 'sppagebuilder',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.published >= 0'
],
'jbusinessdirectory' => [
'default' => [
'table' => 'jbusinessdirectory_companies',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'state'
],
'offer' => [
'table' => 'jbusinessdirectory_company_offers',
'column_id' => 'id',
'column_title' => 'subject',
'column_state' => 'state'
],
'event' => [
'table' => 'jbusinessdirectory_company_events',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'state'
]
],
'djcatalog2' => [
'table' => 'djc2_items',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'published'
],
'djclassifieds' => [
'table' => 'djcf_items',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'published'
],
'djevents' => [
'table' => 'djev_events',
'column_id' => 'id',
'column_title' => 'name',
'column_state' => 'published'
],
'easyblog' => [
'table' => 'easyblog_post',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.state = 0'
],
'eventbooking' => [
'table' => 'eb_events',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published'
],
'eshop' => [
'table' => 'eshop_productdetails',
'column_id' => 'product_id',
'column_title' => 'product_name',
'column_state' => 'p.published',
'join' => '#__eshop_products as p ON i.product_id = p.id'
],
'gridbox' => [
'table' => 'gridbox_pages',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published',
'where' => 'i.published = 1'
],
'quix' => [
'table' => 'quix',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'state',
'where' => 'i.state > 0'
],
'rsblog' => [
'table' => 'rsblog_posts',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published'
],
'sobipro' => [
'table' => 'sobipro_object',
'column_id' => 'i.id',
'column_title' => 'f.baseData',
'column_state' => 'i.state',
'join' => '#__sobipro_field_data as f ON i.id = f.sid',
'where' => 'f.fid = 1'
],
'jcalpro' => [
'table' => 'jcalpro_events',
'column_id' => 'id',
'column_title' => 'title',
'column_state' => 'published'
],
'jevents' => [
'table' => 'jevents_vevent',
'column_id' => 'ev_id',
'column_title' => 'summary',
'column_state' => 'state'
]
];
return self::$queryPresets;
}
/**
* Get query preset configuration for this field
*
* @return array Query preset configuration
*/
protected function getPresetConfig()
{
// Parse preset:variant syntax
$parts = explode(':', $this->preset, 2);
$presetBase = $parts[0];
$variant = isset($parts[1]) ? $parts[1] : 'default';
// Get preset map
$map = self::getQueryPresetsMap();
// Validate preset exists
if (!isset($map[$presetBase]))
{
throw new \RuntimeException('ComponentItems: Invalid preset "' . $presetBase . '"');
}
$presetConfig = $map[$presetBase];
// Check if preset has variants
if (isset($presetConfig['table']))
{
// single variant preset
if ($variant !== 'default')
{
throw new \RuntimeException('ComponentItems: Preset "' . $presetBase . '" does not support variants');
}
return $presetConfig;
}
// multi-variant preset
if (!isset($presetConfig[$variant]))
{
throw new \RuntimeException('ComponentItems: Invalid variant "' . $variant . '" for preset "' . $presetBase . '"');
}
return $presetConfig[$variant];
}
/**
*
* Backward compatibility methods
*
* Find the preset that best matches the given old XML configuration values
*
* @param array $queryConfig Configuration to match (table, column_id, column_title, column_state, where, join, group)
* @return string|null Preset identifier (e.g., 'content:published') or null if no match
*/
public static function findPresetByConfig(array $queryConfig)
{
$map = self::getQueryPresetsMap();
$fields = ['table', 'column_id', 'column_title', 'column_state', 'where', 'join', 'group'];
$bestMatch = null;
$bestMatchCount = 0;
foreach ($map as $presetBase => $presetConfig)
{
if (isset($presetConfig['table']))
{
$matchCount = self::countMatchingFields($queryConfig, $presetConfig, $fields);
if ($matchCount > $bestMatchCount) {
$bestMatch = $presetBase;
$bestMatchCount = $matchCount;
}
}
else
{
foreach ($presetConfig as $variant => $variantConfig)
{
$matchCount = self::countMatchingFields($queryConfig, $variantConfig, $fields);
if ($matchCount > $bestMatchCount)
{
$bestMatch = $presetBase . ':' . $variant;
$bestMatchCount = $matchCount;
}
}
}
}
return $bestMatch;
}
private static function countMatchingFields(array $input, array $preset, array $fields)
{
$count = 0;
foreach ($fields as $field)
{
$inputValue = $input[$field] ?? null;
$presetValue = $preset[$field] ?? null;
if ($inputValue !== null && $inputValue === $presetValue)
{
$count++;
}
}
return $count;
}
}