diff --git a/source/packages/com_mokosuiteclient/admin/sql/install.mysql.sql b/source/packages/com_mokosuiteclient/admin/sql/install.mysql.sql index 8b744bcf..badd0183 100644 --- a/source/packages/com_mokosuiteclient/admin/sql/install.mysql.sql +++ b/source/packages/com_mokosuiteclient/admin/sql/install.mysql.sql @@ -326,3 +326,27 @@ CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_replacements` ( PRIMARY KEY (`id`), KEY `idx_published` (`published`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Content Templates +-- + +CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_content_templates` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `alias` VARCHAR(100) NOT NULL DEFAULT '', + `name` VARCHAR(255) NOT NULL DEFAULT '', + `description` TEXT NOT NULL, + `category` VARCHAR(50) NOT NULL DEFAULT '', + `color` VARCHAR(8) DEFAULT NULL, + `template_data` MEDIUMTEXT NOT NULL, + `joomla_category_id` INT NOT NULL DEFAULT 0, + `access` INT UNSIGNED NOT NULL DEFAULT 1, + `published` TINYINT(1) NOT NULL DEFAULT 1, + `ordering` INT NOT NULL DEFAULT 0, + `checked_out` INT UNSIGNED DEFAULT NULL, + `checked_out_time` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_published` (`published`), + KEY `idx_alias` (`alias`), + KEY `idx_category` (`joomla_category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php b/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php index 24657043..ad9b4ab5 100644 --- a/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php +++ b/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php @@ -3023,6 +3023,14 @@ class MokoSuiteClient extends CMSPlugin implements BootableExtensionInterface $modified = true; } + if (stripos($text, '{template') !== false + && (int) $this->params->get('content_templates_enabled', 0) === 1 + && $this->contentTemplatesTableExists()) + { + $this->processTemplateTags($text); + $modified = true; + } + if (stripos($text, '{article') !== false && (int) $this->params->get('articles_anywhere_enabled', 0) === 1) { $this->processArticleTags($text); @@ -3119,6 +3127,14 @@ class MokoSuiteClient extends CMSPlugin implements BootableExtensionInterface $changed = true; } + if (stripos($body, '{template') !== false + && (int) $this->params->get('content_templates_enabled', 0) === 1 + && $this->contentTemplatesTableExists()) + { + $this->processTemplateTags($body); + $changed = true; + } + if (stripos($body, '{article') !== false && (int) $this->params->get('articles_anywhere_enabled', 0) === 1) { @@ -3939,4 +3955,95 @@ class MokoSuiteClient extends CMSPlugin implements BootableExtensionInterface }; }, $text); } + + /** + * Process {template alias="..."} content tags. + * + * Loads a content template from the database, decodes the JSON + * `template_data` column, and returns the concatenation of its + * `introtext` and `fulltext` fields. + * + * @param string &$text The text to process (modified in place). + * + * @return void + * + * @since 02.48.00 + */ + private function processTemplateTags(string &$text): void + { + if (!$this->params->get('content_templates_enabled', 0)) + { + return; + } + + $pattern = '#\{template\s+([^}]+)\}#i'; + + $text = preg_replace_callback($pattern, function ($match) { + $attrs = $this->parseTagAttributes($match[1]); + $alias = $attrs['alias'] ?? $attrs['id'] ?? ''; + + if (empty($alias)) + { + return $match[0]; + } + + try + { + $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class); + $query = $db->getQuery(true) + ->select($db->quoteName('template_data')) + ->from($db->quoteName('#__mokosuiteclient_content_templates')) + ->where($db->quoteName('published') . ' = 1'); + + if (is_numeric($alias)) + { + $query->where($db->quoteName('id') . ' = ' . (int) $alias); + } + else + { + $query->where($db->quoteName('alias') . ' = ' . $db->quote($alias)); + } + + $db->setQuery($query); + $data = json_decode($db->loadResult() ?? '{}'); + + return ($data->introtext ?? '') . ($data->fulltext ?? ''); + } + catch (\Throwable $e) + { + return ''; + } + }, $text); + } + + /** + * Check whether the content_templates DB table exists. + * + * @return bool + * + * @since 02.48.00 + */ + private function contentTemplatesTableExists(): bool + { + static $exists = null; + + if ($exists !== null) + { + return $exists; + } + + try + { + $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class); + $tables = $db->getTableList(); + $prefix = $db->getPrefix(); + $exists = \in_array($prefix . 'mokosuiteclient_content_templates', $tables, true); + } + catch (\Exception $e) + { + $exists = false; + } + + return $exists; + } } diff --git a/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php b/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php new file mode 100644 index 00000000..ad5e96d5 --- /dev/null +++ b/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php @@ -0,0 +1,67 @@ + + * + * @since 02.47.62 + */ +class ArticlesField extends ListField +{ + protected $type = 'Articles'; + + protected function getOptions(): array + { + $options = parent::getOptions(); + + $db = Factory::getContainer()->get(DatabaseInterface::class); + $query = $db->getQuery(true) + ->select([ + $db->quoteName('a.id', 'value'), + $db->quoteName('a.title', 'text'), + $db->quoteName('c.title', 'category'), + ]) + ->from($db->quoteName('#__content', 'a')) + ->leftJoin($db->quoteName('#__categories', 'c') . ' ON c.id = a.catid') + ->where($db->quoteName('a.state') . ' = 1') + ->order($db->quoteName('a.title') . ' ASC'); + + $db->setQuery($query); + $articles = $db->loadObjectList() ?: []; + + foreach ($articles as $article) { + $label = $article->text; + if (!empty($article->category)) { + $label .= ' [' . $article->category . ']'; + } + $options[] = HTMLHelper::_('select.option', $article->value, $label); + } + + return $options; + } +} diff --git a/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml b/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml index 0af93bf4..bb1363cf 100644 --- a/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml +++ b/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml @@ -123,6 +123,14 @@ + + + + +