* @git Joomla Component Builder * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace VDM\Joomla\Componentbuilder\Compiler\Model; use VDM\Joomla\Componentbuilder\Compiler\Config; use VDM\Joomla\Componentbuilder\Compiler\Customcode\Dispenser; use VDM\Joomla\Componentbuilder\Compiler\Builder\Router as Builder; use VDM\Joomla\Utilities\ArrayHelper; use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Utilities\JsonHelper; /** * Model Component Site Router Class * * @since 3.2.0 */ class Router { /** * The Config Class. * * @var Config * @since 3.2.0 */ protected Config $config; /** * The Dispenser Class. * * @var Dispenser * @since 3.2.0 */ protected Dispenser $dispenser; /** * The Router Class. * * @var Builder * @since 3.2.0 */ protected Builder $builder; /** * The gui mapper array * * @var array * @since 3.2.0 */ protected array $guiMapper = [ 'table' => 'component_router', 'id' => null, 'field' => null, 'type' => 'php' ]; /** * The field targets * * @var array * @since 3.2.0 */ protected array $targets = [ 'before' => 'constructor_before_parent', 'after' => 'constructor_after_parent', 'method' => 'methods' ]; /** * Constructor. * * @param Config $config The Config Class. * @param Dispenser $dispenser The Dispenser Class. * @param Builder $builder The Router Class. * * @since 3.2.0 */ public function __construct(Config $config, Dispenser $dispenser, Builder $builder) { $this->config = $config; $this->dispenser = $dispenser; $this->builder = $builder; } /** * Set Router * * @param object $item The item data * * @return void * @since 3.2.0 */ public function set(object &$item) { $this->config->lang_target = 'site'; foreach ($this->targets as $target) { // add the code if ($item->{"router_mode_{$target}"} == 3 && StringHelper::check($item->{"router_{$target}_code"})) { // update GUI mapper field $this->guiMapper['field'] = "{$target}_code"; $this->dispenser->set( $item->{"router_{$target}_code"}, "_site_router_", $target, null, $this->guiMapper ); } unset($item->{"router_{$target}_code"}); } // get the site views $views = $this->getSiteViews($item->site_views ?? [], $item->admin_views ?? []); $edit_views = $this->getSiteEditViews($item->admin_views); // get the edit site views $this->builder->set('views', ArrayHelper::merge([$views, $edit_views]) ); if ($item->router_mode_constructor_before_parent == 2 && JsonHelper::check($item->router_constructor_before_parent_manual)) { // build and validate the constructor before parent call code $this->builder->set('manual', json_decode($item->router_constructor_before_parent_manual) ); } // clear the data from the item foreach ($this->targets as $key => $target) { // set the modes $this->builder->set("mode_{$key}", (int) $item->{"router_mode_{$target}"} ); unset($item->{"router_mode_{$target}"}); } unset($item->router_constructor_before_parent_manual); } /** * Get the array of site views with additional details. * * This method processes each site view to enrich it with additional details such as the associated table, * alias keys, and other relevant information. The enrichment is based on the view's settings and the admin views. * * @param array $siteViews The site views to be processed. * @param array $adminViews The admin views used for fetching additional data. * * @return array An array of objects, each representing a site view with enriched details. * @since 3.2.0 */ protected function getSiteViews(array $siteViews, array $adminViews): array { return array_map(function ($view) use ($adminViews) { // Attempt to get the main selection details from the view's settings. $selection = $this->getMainSelection($view['settings']->main_get->main_get ?? null); // We can only work with ID if the [main get] is a [getItem] dynamicGet for this site view. $key = ($view['settings']->main_get->gettype == 1) ? 'id' : null; // Construct the enriched view object. return (object) [ 'view' => $view['settings']->code, 'View' => $view['settings']->Code, 'stable' => ($selection['view'] === $view['settings']->code), // sanity check 'target_view' => $selection['view'], 'table' => $selection['table'], 'table_name' => $selection['name'], 'alias' => $this->getSiteViewAliasKey($selection['name'] ?? null, $adminViews), 'key' => $key, 'form' => false ]; }, $siteViews); } /** * Get the array of site edit views * * This method processes the provided admin views to extract and return an array of site edit views. * Each site edit view is constructed based on specific conditions from the admin view's settings. * * @param array|null $views The admin views to process. * * @return array An array of site edit views, each as an object with view, table, alias, key, and form properties. * @since 3.2.0 */ protected function getSiteEditViews(?array $views): array { $siteEditViews = []; // Return early if no views are provided. if (empty($views)) { return $siteEditViews; } foreach ($views as $view) { // Check if the view is marked for edit/create on the site. if (!empty($view['edit_create_site_view'])) { $siteEditViews[] = (object) [ 'view' => $view['settings']->name_single_code, 'View' => StringHelper::safe($view['settings']->name_single_code, 'F'), 'stable' => true, 'target_view' => $view['settings']->name_single_code, 'table' => '#__' . $this->config->component_code_name . '_' . $view['settings']->name_single_code, 'alias' => $this->getSiteEditViewAliasKey($view['settings']->fields ?? null), 'key' => 'id', 'form' => true ]; } } return $siteEditViews; } /** * Get the site edit view alias key value * * This method fetches the alias keys for a given site edit view by matching the view name * against a list of admin views. It processes the admin views to find a match and then * retrieves the alias keys from the matched view's settings. * * @param string|null $viewName The view name to match. * @param array $adminViews The admin views to search within. * * @return string|null The alias key for the site edit view, or null if not found. * @since 3.2.0 */ protected function getSiteViewAliasKey(?string $viewName, array $adminViews): ?string { // Return early if no view name is provided or admin views are empty. if ($viewName === null || empty($adminViews)) { return null; } foreach ($adminViews as $view) { // Check if the current view matches the specified view name and has fields defined. if ($view['settings']->name_single_code === $viewName && is_array($view['settings']->fields ?? null)) { // If a match is found, retrieve and return the site edit view alias keys. return $this->getSiteEditViewAliasKey($view['settings']->fields); } } // Return an empty array if no matching view is found. return null; } /** * Get the site view alias key value * * @param array|null $fields The main get object * * @return string|null * @since 3.2.0 */ protected function getSiteEditViewAliasKey(?array $fields): ?string { if ($fields !== null) { foreach ($fields as $field) { if (isset($field['alias']) && $field['alias'] && $field['type_name'] === 'text') { return $field['base_name']; } } } return null; } /** * Get the view (main selection) table and view name value * from the main get object * * @param array|null $gets The main get objects * * @return array * @since 3.2.0 */ protected function getMainSelection(?array $gets): array { if ($gets !== null) { foreach ($gets as $get) { // get the main table if (isset($get['as']) && $get['as'] === 'a' && isset($get['selection']) && ArrayHelper::check($get['selection']) && isset($get['selection']['select_gets']) && ArrayHelper::check($get['selection']['select_gets']) && isset($get['selection']['name']) && isset($get['selection']['table'])) { $name = $get['selection']['name']; $view = $get['selection']['view']; $table = $get['selection']['table']; return ['table' => $table, 'view' => $view, 'name' => $name]; } } } return []; } }