first commit

This commit is contained in:
2025-06-17 11:53:18 +02:00
commit 9f0f7ba12b
8804 changed files with 1369176 additions and 0 deletions

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="module" client="administrator" method="upgrade">
<name>mod_guidedtours</name>
<author>Joomla! Project</author>
<creationDate>2023-02</creationDate>
<copyright>(C) 2023 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>4.3.0</version>
<description>MOD_GUIDEDTOURS_XML_DESCRIPTION</description>
<namespace path="src">Joomla\Module\GuidedTours</namespace>
<files>
<folder module="mod_guidedtours">services</folder>
<folder>src</folder>
<folder>tmpl</folder>
</files>
<languages>
<language tag="en-GB">language/en-GB/mod_guidedtours.ini</language>
<language tag="en-GB">language/en-GB/mod_guidedtours.sys.ini</language>
</languages>
<help key="Admin_Modules:_Tours_Menu" />
<config>
<fields name="params">
<fieldset name="basic">
<field
name="contextcount"
type="number"
label="MOD_GUIDEDTOURS_FIELD_CONTEXT_TOUR_COUNT_LABEL"
description="MOD_GUIDEDTOURS_FIELD_CONTEXT_TOUR_COUNT_DESC"
default="7"
filter="integer"
min="0"
validate="number"
/>
<field
name="tourscount"
type="number"
label="MOD_GUIDEDTOURS_FIELD_TOUR_COUNT_LABEL"
description="MOD_GUIDEDTOURS_FIELD_TOUR_COUNT_DESC"
default="7"
filter="integer"
min="0"
validate="number"
/>
</fieldset>
<fieldset name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="form-select"
validate="moduleLayout"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
validate="CssIdentifier"
/>
</fieldset>
</fields>
</config>
</extension>

View File

@ -0,0 +1,41 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_guidedtours
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
\defined('_JEXEC') or die;
use Joomla\CMS\Extension\Service\Provider\HelperFactory;
use Joomla\CMS\Extension\Service\Provider\Module;
use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
/**
* The guided tours module service provider.
*
* @since 4.3.0
*/
return new class () implements ServiceProviderInterface {
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.3.0
*/
public function register(Container $container)
{
$container->registerServiceProvider(new ModuleDispatcherFactory('\\Joomla\\Module\\GuidedTours'));
$container->registerServiceProvider(new HelperFactory('\\Joomla\\Module\\GuidedTours\\Administrator\\Helper'));
$container->registerServiceProvider(new Module());
}
};

View File

@ -0,0 +1,69 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_guidedtours
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Module\GuidedTours\Administrator\Dispatcher;
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
use Joomla\CMS\Plugin\PluginHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Dispatcher class for mod_guidedtours
*
* @since 4.3.0
*/
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
{
use HelperFactoryAwareTrait;
/**
* Runs the dispatcher.
*
* @return void
*
* @since 4.3.0
*/
public function dispatch()
{
// The guided tour will not show if no user is logged in.
$user = $this->getApplication()->getIdentity();
if ($user === null || $user->id === 0) {
return;
}
// The module can't show if the plugin is not enabled.
if (!PluginHelper::isEnabled('system', 'guidedtours')) {
return;
}
parent::dispatch();
}
/**
* Returns the layout data.
*
* @return array
*
* @since 4.3.0
*/
protected function getLayoutData()
{
$data = parent::getLayoutData();
$data['tours'] = $this->getHelperFactory()->getHelper('GuidedToursHelper')->getTours($data['params'], $this->getApplication());
return $data;
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_guidedtours
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Module\GuidedTours\Administrator\Helper;
use Joomla\CMS\Application\AdministratorApplication;
use Joomla\CMS\Language\Multilanguage;
use Joomla\Registry\Registry;
use Joomla\Uri\Uri;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Helper for mod_guidedtours
*
* @since 4.3.0
*/
class GuidedToursHelper
{
/**
* Get a list of tours from a specific context.
*
* @param Registry $params Object holding the module parameters
* @param AdministratorApplication $app The application
*
* @return mixed
*
* @since 4.3.0
*/
public function getTours(Registry $params, AdministratorApplication $app)
{
$factory = $app->bootComponent('com_guidedtours')->getMVCFactory();
$user = $app->getIdentity();
// Get an instance of the guided tour model
$tourModel = $factory->createModel('Tours', 'Administrator', ['ignore_request' => true]);
$tourModel->setState('filter.published', 1);
$tourModel->setState('filter.access', $app->getIdentity()->getAuthorisedViewLevels());
if (Multilanguage::isEnabled()) {
$tourModel->setState('filter.language', ['*', $app->getLanguage()->getTag()]);
}
$items = $tourModel->getItems();
foreach ($items as $key => $item) {
// The user can only see the tours of extensions that are allowed.
$uri = new Uri($item->url);
if ($extension = $uri->getVar('option')) {
if (!$user->authorise('core.manage', $extension)) {
unset($items[$key]);
}
}
}
return $items;
}
}

View File

@ -0,0 +1,168 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_guidedtours
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
$hideLinks = $app->getInput()->getBool('hidemainmenu');
if ($hideLinks || !$tours) {
return;
}
// Load the Bootstrap Dropdown
$app->getDocument()
->getWebAssetManager()
->useScript('bootstrap.dropdown')
->useScript('joomla.dialog-autocreate');
$lang = $app->getLanguage();
$extension = $app->getInput()->get('option');
$contextTours = [];
$starTours = [];
$listTours = [];
$allTours = [];
$contextCount = $params->get('contextcount', 7);
$toursCount = $params->get('tourscount', 7);
foreach ($tours as $tour) :
$uri = new Uri($tour->url);
if (in_array('*', $tour->extensions)) :
$starTours[] = $tour;
elseif (in_array($extension, $tour->extensions)) :
if ($extension === 'com_categories') :
// Special case for the categories page, where the context is complemented with the extension the categories apply to
if ($uri->getVar('option', '') === 'com_categories') :
if ($uri->getVar('extension', '') === $app->getInput()->get('extension', '')) :
if ($contextCount > 0) :
$contextTours[] = $tour;
$contextCount--;
endif;
elseif ($toursCount > 0) :
$listTours[] = $tour;
$toursCount--;
endif;
else :
if (in_array($app->getInput()->get('extension', ''), $tour->extensions)) :
if ($contextCount > 0) :
$contextTours[] = $tour;
$contextCount--;
endif;
elseif ($toursCount > 0) :
$listTours[] = $tour;
$toursCount--;
endif;
endif;
elseif ($contextCount > 0) :
$contextTours[] = $tour;
$contextCount--;
endif;
elseif ($toursCount > 0) :
$listTours[] = $tour;
$toursCount--;
endif;
// We assume the url is the starting point
$key = $uri->getVar('option') ?? 'com_cpanel';
if (!isset($allTours[$key])) :
$lang->load("$key.sys", JPATH_ADMINISTRATOR)
|| $lang->load("$key.sys", JPATH_ADMINISTRATOR . '/components/' . $key);
$allTours[$key] = [];
endif;
$allTours[$key][] = $tour;
endforeach;
if ($contextCount > 0) :
// The '*' tours have lower priority than contextual tours and are added after them, room permitting
$contextTours = array_slice(array_merge($contextTours, $starTours), 0, $params->get('contextcount', 7));
endif;
$popupId = 'guidedtours-popup-content' . $module->id;
$popupOptions = json_encode([
'src' => '#' . $popupId,
'width' => '800px',
'height' => 'fit-content',
'textHeader' => Text::_('MOD_GUIDEDTOURS_START_TOUR'),
'preferredParent' => 'body',
]);
?>
<div class="header-item-content dropdown header-tours d-none d-sm-block">
<button class="dropdown-toggle d-flex align-items-center ps-0 py-0" data-bs-toggle="dropdown" type="button" title="<?php echo Text::_('MOD_GUIDEDTOURS_MENU'); ?>">
<div class="header-item-icon">
<span class="icon-map-signs" aria-hidden="true"></span>
</div>
<div class="header-item-text">
<?php echo Text::_('MOD_GUIDEDTOURS_MENU'); ?>
</div>
<span class="icon-angle-down" aria-hidden="true"></span>
</button>
<div class="dropdown-menu dropdown-menu-end">
<?php if (count($contextTours) > 0) : ?>
<ul class="list-unstyled m-0">
<?php foreach ($contextTours as $tour) : ?>
<li>
<button type="button" class="button-start-guidedtour dropdown-item" data-id="<?php echo $tour->id; ?>">
<span class="icon-star icon-fw" aria-hidden="true"></span>
<?php echo $tour->title; ?>
</button>
</li>
<?php endforeach; ?>
</ul>
<hr class="dropdown-divider m-0" role="separator" />
<?php endif; ?>
<?php if (count($listTours) > 0) : ?>
<ul class="list-unstyled m-0">
<?php foreach ($listTours as $tour) : ?>
<li>
<button type="button" class="button-start-guidedtour dropdown-item" data-id="<?php echo $tour->id; ?>">
<span class="icon-map-signs icon-fw" aria-hidden="true"></span>
<?php echo $tour->title; ?>
</button>
</li>
<?php endforeach; ?>
</ul>
<hr class="dropdown-divider m-0" role="separator" />
<?php endif; ?>
<button type="button" class="dropdown-item text-center" data-joomla-dialog="<?php echo htmlspecialchars($popupOptions); ?>">
<?php echo Text::_('MOD_GUIDEDTOURS_SHOW_ALL'); ?>
</button>
</div>
</div>
<?php
$modalHtml = [];
$modalHtml[] = '<div class="p-3">';
$modalHtml[] = '<div class="row">';
foreach ($allTours as $extension => $tours) :
$modalHtml[] = '<div class="col-lg-6">';
$modalHtml[] = '<h4>' . Text::_($extension) . '</h4>';
$modalHtml[] = '<ul class="list-unstyled">';
foreach ($tours as $tour) :
$modalHtml[] = '<li>';
$modalHtml[] = '<a href="#" role="button" class="button-start-guidedtour" data-id="' . (int) $tour->id . '">' . htmlentities($tour->title) . '</a>';
$modalHtml[] = '</li>';
endforeach;
$modalHtml[] = '</ul>';
$modalHtml[] = '</div>';
endforeach;
$modalHtml[] = '</div>';
$modalHtml[] = '</div>';
$modalBody = implode($modalHtml);
?>
<template id="<?php echo $popupId; ?>"><?php echo $modalBody; ?></template>