<?php /** * @package Regular Labs Library * @version 25.7.12430 * * @author Peter van Westen <[email protected]> * @link https://regularlabs.com * @copyright Copyright © 2025 Regular Labs All Rights Reserved * @license GNU General Public License version 2 or later */ namespace RegularLabs\Library; defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\HTML\HTMLHelper as JHtml; use Joomla\CMS\Language\Text as JText; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper as JFieldsHelper; class Variables { static $article; static $contact; static $profile; static $user; public static function replaceArticleTags(string &$string, object|false|null $article = null): void { $matches = self::getSingleTagMatches($string, 'article'); self::unique($matches); if (empty($matches)) { return; } $article = self::getArticle($article); foreach ($matches as $match) { $replace = $article->{$match['value']} ?? ''; $string = str_replace($match[0], $replace, $string); } } public static function replaceDateTags(string &$string): void { $matches = self::getSingleTagMatches($string, 'date'); self::unique($matches); foreach ($matches as $match) { $replace = self::getDateValue($match['value']); $string = str_replace($match[0], $replace, $string); } } public static function replaceRandomTags(string &$string): void { $matches = self::getSingleTagMatches($string, 'random'); foreach ($matches as $match) { $replace = self::getRandomValue($match['value']); $string = \RegularLabs\Library\StringHelper::replaceOnce($match[0], $replace, $string); } } public static function replaceReplaceTags(string &$string): void { self::replaceTextConversionTagsByType($string, 'replace'); } public static function replaceTextConversionTags(string &$string): void { $types = ['escape', 'lowercase', 'uppercase', 'notags', 'nowhitespace', 'toalias', 'replace']; foreach ($types as $type) { self::replaceTextConversionTagsByType($string, $type); } } public static function replaceTextTags(string &$string): void { $matches = self::getSingleTagMatches($string, 'j?text'); self::unique($matches); foreach ($matches as $match) { $string = str_replace($match[0], JText::_($match['value']), $string); } } public static function replaceUserTags(string &$string, ?object $user = null): void { $matches = self::getSingleTagMatches($string, 'user'); self::unique($matches); foreach ($matches as $match) { $replace = self::geUserValue($match['value'], $user); $string = str_replace($match[0], $replace, $string); } } private static function flattenObject(?object &$object): object { $flat = (object) []; if (empty($object)) { return $flat; } foreach ($object as $property_key => $property) { if (is_string($property)) { $property = (string) $property; } if (is_string($property) && strlen($property) && $property[0] == '{') { $property = json_decode($property); } if (is_string($property) || is_numeric($property)) { self::setParam($flat, $property_key, $property); continue; } if (!is_object($property) && !is_array($property)) { continue; } foreach ($property as $key => $value) { self::setParam($flat, $key, $value); } } return $flat; } private static function geUserValue(string $key, ?object $user = null): string { if ($key == 'password') { return ''; } $user = self::getUser($user); if ($user->guest) { return ''; } if (isset($user->{$key})) { return $user->{$key}; } $contact = self::getContact(); if (isset($contact->{$key})) { return $contact->{$key}; } $profile = self::getProfile(); if (isset($profile->{$key})) { return $profile->{$key}; } return ''; } private static function getArticle(object|false|null $article = null): object { if (!$article && is_null(self::$article)) { self::$article = \RegularLabs\Library\Article::get(); } $article = $article ?: self::$article; self::setArticleFieldsData($article); return self::flattenObject($article); } private static function getContact(): object { if (self::$contact) { return self::$contact; } $db = JFactory::getDbo(); $query = 'SHOW TABLES LIKE ' . $db->quote($db->getPrefix() . 'contact_details'); $db->setQuery($query); $has_contact_table = $db->loadResult(); if (!$has_contact_table) { self::$contact = (object) ['x' => '']; return self::$contact; } $query = $db->getQuery(\true)->select('c.*')->from('#__contact_details as c')->where('c.user_id = ' . (int) self::$user->id); $db->setQuery($query); self::$contact = $db->loadObject(); if (!self::$contact) { self::$contact = (object) ['x' => '']; return self::$contact; } self::flattenObject(self::$contact); return self::$contact; } private static function getDateFromFormat(?string $date): string { if ($date && str_contains($date, '%')) { $date = \RegularLabs\Library\Date::strftimeToDateFormat($date); } $date = str_replace('[TH]', '[--==--]', $date); $date = JHtml::_('date', 'now', $date); self::replaceThIndDate($date, '[--==--]'); return $date; } private static function getDateValue(?string $value): string { return self::getDateFromFormat($value); } /** * double [[tag]]...[[/tag]] style tag on multiple lines */ private static function getDoubleTagMatches(string $string, string $type): array { if (!\RegularLabs\Library\RegEx::match('\[\[/' . $type . '\]\]', $string)) { return []; } \RegularLabs\Library\RegEx::matchAll('\[\[' . $type . '(?<attributes>(?: [^\]]+)?)\]\](?<content>.*?)\[\[/' . $type . '\]\]', $string, $matches); return $matches ?: []; } private static function getProfile(): object { if (self::$profile) { return self::$profile; } $db = JFactory::getDbo(); $query = $db->getQuery(\true)->select('p.profile_key, p.profile_value')->from('#__user_profiles as p')->where('p.user_id = ' . (int) self::$user->id); $db->setQuery($query); $rows = $db->loadObjectList(); $profile = (object) []; $profile->x = ''; foreach ($rows as $row) { $data = json_decode($row->profile_value); if (is_null($data)) { $data = (object) []; } $profile->{substr($row->profile_key, 8)} = $data; } self::$profile = $profile; return self::$profile; } private static function getRandomValue(mixed $value): mixed { $values = \RegularLabs\Library\ArrayHelper::toArray($value); foreach ($values as $i => $value) { if (\RegularLabs\Library\RegEx::match('^([0-9]+)-([0-9]+)$', trim($value), $range)) { $values[$i] = self::getRandomValueFromRange($range); } } return $values[rand(0, count($values) - 1)]; } private static function getRandomValueFromRange(array $range): int { return rand((int) $range[1], (int) $range[2]); } /** * single [[tag:...]] style tag on single line */ private static function getSingleTagMatches(string $string, string $type): array { if (!\RegularLabs\Library\RegEx::match('\[\[' . $type . '\:', $string)) { return []; } \RegularLabs\Library\RegEx::matchAll('\[\[' . $type . '\:(?<value>.*?)\]\]', $string, $matches); return $matches ?: []; } private static function getUser(?object $user = null): object { if (is_null($user) && is_null(self::$user)) { self::$user = JFactory::getUser(); } $user = $user ?? self::$user; return self::flattenObject($user); } private static function replaceTextConversionTagsByType(string &$string, string $type): void { $matches = self::getDoubleTagMatches($string, $type); self::unique($matches); foreach ($matches as $match) { $attributes = \RegularLabs\Library\PluginTag::getAttributesFromString($match['attributes']); $replace = \RegularLabs\Library\StringHelper::applyConversion($type, $match['content'], $attributes); $string = str_replace($match[0], $replace, $string); } } private static function replaceThIndDate(string &$date, string $th = '[TH]'): void { if (!str_contains($date, $th)) { return; } \RegularLabs\Library\RegEx::matchAll('([0-9]+)' . \RegularLabs\Library\RegEx::quote($th), $date, $date_matches); if (empty($date_matches)) { $date = str_replace($th, 'th', $date); return; } foreach ($date_matches as $date_match) { $suffix = match ($date_match[1]) { 1, 21, 31 => 'st', 2, 22, 32 => 'nd', 3, 23 => 'rd', default => 'th', }; $date = \RegularLabs\Library\StringHelper::replaceOnce($date_match[0], $date_match[1] . $suffix, $date); } $date = str_replace($th, 'th', $date); } private static function setArticleFieldsData(?object &$article): void { if (empty($article->id)) { return; } $fields = $article->jcfields ?? JFieldsHelper::getFields('com_content.article', $article, \true); foreach ($fields as $field) { if (!isset($field->name) || isset($article->{$field->name})) { continue; } $article->{$field->name} = $field->value; $article->{$field->name . '-raw'} = \RegularLabs\Library\ArrayHelper::implode($field->rawvalue); } } private static function setParam(object &$object, string $key, mixed $value): void { if (isset($object->{$key}) || is_numeric($key) || is_object($value) || is_array($value)) { return; } $object->{$key} = $value; } private static function unique(array &$matches): void { $unique_matches = []; foreach ($matches as $match) { if (in_array($match[0], $unique_matches)) { continue; } $unique_matches[] = $match; } $matches = $unique_matches; } }