Файловый менеджер - Редактировать - /home/harasnat/www/mf/com_associations.tar
Назад
src/Controller/AssociationController.php 0000644 00000005471 15062153647 0014527 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Controller; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\FormController; use Joomla\CMS\Router\Route; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Association edit controller class. * * @since 3.7.0 */ class AssociationController extends FormController { /** * Method to edit an existing record. * * @param string $key The name of the primary key of the URL variable. * @param string $urlVar The name of the URL variable if different from the primary key * (sometimes required to avoid router collisions). * * @return FormController|boolean True if access level check and checkout passes, false otherwise. * * @since 3.7.0 */ public function edit($key = null, $urlVar = null) { list($extensionName, $typeName) = explode('.', $this->input->get('itemtype', '', 'string'), 2); $id = $this->input->get('id', 0, 'int'); // Check if reference item can be edited. if (!AssociationsHelper::allowEdit($extensionName, $typeName, $id)) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error'); $this->setRedirect(Route::_('index.php?option=com_associations&view=associations', false)); return false; } return parent::display(); } /** * Method for canceling the edit action * * @param string $key The name of the primary key of the URL variable. * * @return void * * @since 3.7.0 */ public function cancel($key = null) { $this->checkToken(); list($extensionName, $typeName) = explode('.', $this->input->get('itemtype', '', 'string'), 2); // Only check in, if component item type allows to check out. if (AssociationsHelper::typeSupportsCheckout($extensionName, $typeName)) { $ids = []; $targetId = $this->input->get('target-id', '', 'string'); if ($targetId !== '') { $ids = array_unique(explode(',', $targetId)); } $ids[] = $this->input->get('id', 0, 'int'); foreach ($ids as $key => $id) { AssociationsHelper::getItem($extensionName, $typeName, $id)->checkIn(); } } $this->setRedirect(Route::_('index.php?option=com_associations&view=associations', false)); } } src/Controller/AssociationsController.php 0000644 00000007553 15062153647 0014715 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Controller; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\AdminController; use Joomla\CMS\Router\Route; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Associations controller class. * * @since 3.7.0 */ class AssociationsController extends AdminController { /** * The URL view list variable. * * @var string * * @since 3.7.0 */ protected $view_list = 'associations'; /** * Proxy for getModel. * * @param string $name The model name. Optional. * @param string $prefix The class prefix. Optional. * @param array $config The array of possible config values. Optional. * * @return \Joomla\CMS\MVC\Model\BaseDatabaseModel|boolean * * @since 3.7.0 */ public function getModel($name = 'Associations', $prefix = 'Administrator', $config = ['ignore_request' => true]) { return parent::getModel($name, $prefix, $config); } /** * Method to purge the associations table. * * @return void * * @since 3.7.0 */ public function purge() { $this->checkToken(); $this->getModel('associations')->purge(); $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); } /** * Method to delete the orphans from the associations table. * * @return void * * @since 3.7.0 */ public function clean() { $this->checkToken(); $this->getModel('associations')->clean(); $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); } /** * Method to check in an item from the association item overview. * * @return void * * @since 3.7.1 */ public function checkin() { // Set the redirect so we can just stop processing when we find a condition we can't process $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); // Figure out if the item supports checking and check it in list($extensionName, $typeName) = explode('.', $this->input->get('itemtype')); $extension = AssociationsHelper::getSupportedExtension($extensionName); $types = $extension->get('types'); if (!\array_key_exists($typeName, $types)) { return; } if (AssociationsHelper::typeSupportsCheckout($extensionName, $typeName) === false) { // How on earth we came to that point, eject internet return; } $cid = (array) $this->input->get('cid', [], 'int'); if (empty($cid)) { // Seems we don't have an id to work with. return; } // We know the first element is the one we need because we don't allow multi selection of rows $id = $cid[0]; if ($id === 0) { // Seems we don't have an id to work with. return; } if (AssociationsHelper::canCheckinItem($extensionName, $typeName, $id) === true) { $item = AssociationsHelper::getItem($extensionName, $typeName, $id); $item->checkIn($id); return; } $this->setRedirect( Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list), Text::_('COM_ASSOCIATIONS_YOU_ARE_NOT_ALLOWED_TO_CHECKIN_THIS_ITEM') ); } } src/Controller/DisplayController.php 0000644 00000001311 15062153647 0013645 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Controller; use Joomla\CMS\MVC\Controller\BaseController; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Component Controller * * @since 3.7.0 */ class DisplayController extends BaseController { /** * The default view. * * @var string * * @since 3.7.0 */ protected $default_view = 'associations'; } src/Dispatcher/Dispatcher.php 0000644 00000003306 15062153647 0012233 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Dispatcher; use Joomla\CMS\Access\Exception\NotAllowed; use Joomla\CMS\Dispatcher\ComponentDispatcher; use Joomla\CMS\Language\Text; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * ComponentDispatcher class for com_associations * * @since 4.0.0 */ class Dispatcher extends ComponentDispatcher { /** * Method to check component access permission * * @since 4.0.0 * * @return void * * @throws \Exception|NotAllowed */ protected function checkAccess() { parent::checkAccess(); // Check if user has permission to access the component item type. $itemType = $this->input->get('itemtype', '', 'string'); if ($itemType !== '') { list($extensionName, $typeName) = explode('.', $itemType); if (!AssociationsHelper::hasSupport($extensionName)) { throw new \Exception( Text::sprintf('COM_ASSOCIATIONS_COMPONENT_NOT_SUPPORTED', $this->app->getLanguage()->_($extensionName)), 404 ); } if (!$this->app->getIdentity()->authorise('core.manage', $extensionName)) { throw new NotAllowed($this->app->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403); } } } } src/View/Association/HtmlView.php 0000644 00000024142 15062153647 0013005 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\View\Association; use Joomla\CMS\Application\AdministratorApplication; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\GenericDataException; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Pagination\Pagination; use Joomla\CMS\Router\Route; use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; use Joomla\Component\Associations\Administrator\Model\AssociationModel; use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * View class for a list of articles. * * @since 3.7.0 */ class HtmlView extends BaseHtmlView { /** * An array of items * * @var array * * @since 3.7.0 */ protected $items = []; /** * The pagination object * * @var Pagination * * @since 3.7.0 */ protected $pagination; /** * The model state * * @var CMSObject * * @since 3.7.0 */ protected $state; /** * Selected item type properties. * * @var Registry * * @since 3.7.0 */ protected $itemType; /** * The application * * @var AdministratorApplication * @since 3.7.0 */ protected $app; /** * The ID of the reference language * * @var integer * @since 3.7.0 */ protected $referenceId = 0; /** * The type name * * @var string * @since 3.7.0 */ protected $typeName = ''; /** * The reference language * * @var string * @since 3.7.0 */ protected $referenceLanguage = ''; /** * The title of the reference language * * @var string * @since 3.7.0 */ protected $referenceTitle = ''; /** * The value of the reference title * * @var string * @since 3.7.0 */ protected $referenceTitleValue = ''; /** * The URL to the edit screen * * @var string * @since 3.7.0 */ protected $editUri = ''; /** * The ID of the target field * * @var string * @since 3.7.0 */ protected $targetId = ''; /** * The target language * * @var string * @since 3.7.0 */ protected $targetLanguage = ''; /** * The source of the target field * * @var string * @since 3.7.0 */ protected $defaultTargetSrc = ''; /** * The action to perform for the target field * * @var string * @since 3.7.0 */ protected $targetAction = ''; /** * The title of the target field * * @var string * @since 3.7.0 */ protected $targetTitle = ''; /** * The edit form * * @var Form * @since 3.7.0 */ protected $form; /** * Set if the option is set to save as copy * * @var boolean * @since 3.7.0 */ private $save2copy = false; /** * The type of language * * @var Registry * @since 3.7.0 */ private $type; /** * The supported types * * @var array * @since 3.7.0 */ private $typeSupports = []; /** * The extension name * * @var string * @since 3.7.0 */ private $extensionName = ''; /** * Display the view * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return void * * @since 3.7.0 * * @throws \Exception */ public function display($tpl = null): void { /** @var AssociationModel $model */ $model = $this->getModel(); // Check for errors. if (\count($errors = $model->getErrors())) { throw new GenericDataException(implode("\n", $errors), 500); } $this->app = Factory::getApplication(); $this->form = $model->getForm(); /** @var Input $input */ $input = $this->app->getInput(); $this->referenceId = $input->get('id', 0, 'int'); [$extensionName, $typeName] = explode('.', $input->get('itemtype', '', 'string'), 2); /** @var Registry $extension */ $extension = AssociationsHelper::getSupportedExtension($extensionName); $types = $extension->get('types'); if (\array_key_exists($typeName, $types)) { $this->type = $types[$typeName]; $this->typeSupports = []; $details = $this->type->get('details'); $this->save2copy = false; if (\array_key_exists('support', $details)) { $support = $details['support']; $this->typeSupports = $support; } if (!empty($this->typeSupports['save2copy'])) { $this->save2copy = true; } } $this->extensionName = $extensionName; $this->typeName = $typeName; $this->itemType = $extensionName . '.' . $typeName; $languageField = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'language'); $referenceId = $input->get('id', 0, 'int'); $reference = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId)); $this->referenceLanguage = $reference[$languageField]; $this->referenceTitle = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'title'); $this->referenceTitleValue = $reference[$this->referenceTitle]; // Check for special case category $typeNameExploded = explode('.', $typeName); if (array_pop($typeNameExploded) === 'category') { $this->typeName = 'category'; if ($typeNameExploded) { $extensionName .= '.' . implode('.', $typeNameExploded); } $options = [ 'option' => 'com_categories', 'view' => 'category', 'extension' => $extensionName, 'tmpl' => 'component', ]; } else { $options = [ 'option' => $extensionName, 'view' => $typeName, 'extension' => $extensionName, 'tmpl' => 'component', ]; } // Reference and target edit links. $this->editUri = 'index.php?' . http_build_query($options); // Get target language. $this->targetId = '0'; $this->targetLanguage = ''; $this->defaultTargetSrc = ''; $this->targetAction = ''; $this->targetTitle = ''; if ($target = $input->get('target', '', 'string')) { $matches = preg_split("#[\:]+#", $target); $this->targetAction = $matches[2]; $this->targetId = $matches[1]; $this->targetLanguage = $matches[0]; $this->targetTitle = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'title'); $task = $typeName . '.' . $this->targetAction; /** * Let's put the target src into a variable to use in the javascript code * to avoid race conditions when the reference iframe loads. */ $this->getDocument()->addScriptOptions('targetSrc', Route::_($this->editUri . '&task=' . $task . '&id=' . (int) $this->targetId)); $this->form->setValue('itemlanguage', '', $this->targetLanguage . ':' . $this->targetId . ':' . $this->targetAction); } $this->addToolbar(); parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.7.0 * * @throws \Exception */ protected function addToolbar(): void { // Hide main menu. $this->app->getInput()->set('hidemainmenu', 1); $helper = AssociationsHelper::getExtensionHelper($this->extensionName); $title = $helper->getTypeTitle($this->typeName); $languageKey = strtoupper($this->extensionName . '_' . $title . 'S'); if ($this->typeName === 'category') { $languageKey = strtoupper($this->extensionName) . '_CATEGORIES'; } ToolbarHelper::title( Text::sprintf( 'COM_ASSOCIATIONS_TITLE_EDIT', Text::_($this->extensionName), Text::_($languageKey) ), 'language assoc' ); $toolbar = Toolbar::getInstance(); $toolbar->customButton('reference') ->html('<joomla-toolbar-button><button onclick="Joomla.submitbutton(\'reference\')" ' . 'class="btn btn-success"><span class="icon-save" aria-hidden="true"></span>' . Text::_('COM_ASSOCIATIONS_SAVE_REFERENCE') . '</button></joomla-toolbar-button>'); $toolbar->customButton('target') ->html('<joomla-toolbar-button><button onclick="Joomla.submitbutton(\'target\')" ' . 'class="btn btn-success"><span class="icon-save" aria-hidden="true"></span>' . Text::_('COM_ASSOCIATIONS_SAVE_TARGET') . '</button></joomla-toolbar-button>'); if ($this->typeName === 'category' || $this->extensionName === 'com_menus' || $this->save2copy === true) { $toolbar->standardButton('', 'COM_ASSOCIATIONS_COPY_REFERENCE', 'copy') ->icon('icon-copy') ->listCheck(false); } $toolbar->cancel('association.cancel'); $toolbar->help('Multilingual_Associations:_Edit'); } } src/View/Associations/HtmlView.php 0000644 00000017416 15062153647 0013176 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\View\Associations; use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Router\Route; use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * View class for a list of articles. * * @since 3.7.0 */ class HtmlView extends BaseHtmlView { /** * An array of items * * @var array * * @since 3.7.0 */ protected $items; /** * The pagination object * * @var \Joomla\CMS\Pagination\Pagination * * @since 3.7.0 */ protected $pagination; /** * The model state * * @var object * * @since 3.7.0 */ protected $state; /** * Selected item type properties. * * @var \Joomla\Registry\Registry * * @since 3.7.0 */ public $itemType = null; /** * Display the view * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return void * * @since 3.7.0 */ public function display($tpl = null) { $this->state = $this->get('State'); $this->filterForm = $this->get('FilterForm'); $this->activeFilters = $this->get('ActiveFilters'); if (!Associations::isEnabled()) { $link = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . AssociationsHelper::getLanguagefilterPluginId()); Factory::getApplication()->enqueueMessage(Text::sprintf('COM_ASSOCIATIONS_ERROR_NO_ASSOC', $link), 'warning'); } elseif ($this->state->get('itemtype') != '' && $this->state->get('language') != '') { $type = null; list($extensionName, $typeName) = explode('.', $this->state->get('itemtype'), 2); $extension = AssociationsHelper::getSupportedExtension($extensionName); $types = $extension->get('types'); if (\array_key_exists($typeName, $types)) { $type = $types[$typeName]; } $this->itemType = $type; if (\is_null($type)) { Factory::getApplication()->enqueueMessage(Text::_('COM_ASSOCIATIONS_ERROR_NO_TYPE'), 'warning'); } else { $this->extensionName = $extensionName; $this->typeName = $typeName; $this->typeSupports = []; $this->typeFields = []; $details = $type->get('details'); if (\array_key_exists('support', $details)) { $support = $details['support']; $this->typeSupports = $support; } if (\array_key_exists('fields', $details)) { $fields = $details['fields']; $this->typeFields = $fields; } // Dynamic filter form. // This selectors doesn't have to activate the filter bar. unset($this->activeFilters['itemtype']); unset($this->activeFilters['language']); // Remove filters options depending on selected type. if (empty($support['state'])) { unset($this->activeFilters['state']); $this->filterForm->removeField('state', 'filter'); } if (empty($support['category'])) { unset($this->activeFilters['category_id']); $this->filterForm->removeField('category_id', 'filter'); } if ($extensionName !== 'com_menus') { unset($this->activeFilters['menutype']); $this->filterForm->removeField('menutype', 'filter'); } if (empty($support['level'])) { unset($this->activeFilters['level']); $this->filterForm->removeField('level', 'filter'); } if (empty($support['acl'])) { unset($this->activeFilters['access']); $this->filterForm->removeField('access', 'filter'); } // Add extension attribute to category filter. if (empty($support['catid'])) { $this->filterForm->setFieldAttribute('category_id', 'extension', $extensionName, 'filter'); if ($this->getLayout() == 'modal') { // We need to change the category filter to only show categories tagged to All or to the forced language. if ($forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD')) { $this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter'); } } } $this->items = $this->get('Items'); $this->pagination = $this->get('Pagination'); $linkParameters = [ 'layout' => 'edit', 'itemtype' => $extensionName . '.' . $typeName, 'task' => 'association.edit', ]; $this->editUri = 'index.php?option=com_associations&view=association&' . http_build_query($linkParameters); } } // Check for errors. if (\count($errors = $this->get('Errors'))) { throw new \Exception(implode("\n", $errors), 500); } $this->addToolbar(); parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.7.0 */ protected function addToolbar() { $user = $this->getCurrentUser(); if (isset($this->typeName) && isset($this->extensionName)) { $helper = AssociationsHelper::getExtensionHelper($this->extensionName); $title = $helper->getTypeTitle($this->typeName); $languageKey = strtoupper($this->extensionName . '_' . $title . 'S'); if ($this->typeName === 'category') { $languageKey = strtoupper($this->extensionName) . '_CATEGORIES'; } ToolbarHelper::title( Text::sprintf( 'COM_ASSOCIATIONS_TITLE_LIST', Text::_($this->extensionName), Text::_($languageKey) ), 'language assoc' ); } else { ToolbarHelper::title(Text::_('COM_ASSOCIATIONS_TITLE_LIST_SELECT'), 'language assoc'); } $toolbar = Toolbar::getInstance(); if ($user->authorise('core.admin', 'com_associations') || $user->authorise('core.options', 'com_associations')) { if (!isset($this->typeName)) { $toolbar->standardButton('', 'COM_ASSOCIATIONS_PURGE', 'associations.purge') ->icon('icon-purge') ->listCheck(false); $toolbar->standardButton('', 'COM_ASSOCIATIONS_DELETE_ORPHANS', 'associations.clean') ->icon('icon-refresh') ->listCheck(false); } $toolbar->preferences('com_associations'); } $toolbar->help('Multilingual_Associations'); } } src/Model/AssociationsModel.php 0000644 00000047440 15062153647 0012546 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Model; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\Table\Table; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Methods supporting a list of article records. * * @since 3.7.0 */ class AssociationsModel extends ListModel { /** * Override parent constructor. * * @param array $config An optional associative array of configuration settings. * @param MVCFactoryInterface $factory The factory. * * @see \Joomla\CMS\MVC\Model\BaseDatabaseModel * @since 3.7 */ public function __construct($config = [], MVCFactoryInterface $factory = null) { if (empty($config['filter_fields'])) { $config['filter_fields'] = [ 'id', 'title', 'ordering', 'itemtype', 'language', 'association', 'menutype', 'menutype_title', 'level', 'state', 'category_id', 'category_title', 'access', 'access_level', ]; } parent::__construct($config, $factory); } /** * Method to auto-populate the model state. * * Note. Calling getState in this method will result in recursion. * * @param string $ordering An optional ordering field. * @param string $direction An optional direction (asc|desc). * * @return void * * @since 3.7.0 */ protected function populateState($ordering = 'ordering', $direction = 'asc') { $app = Factory::getApplication(); $forcedLanguage = $app->getInput()->get('forcedLanguage', '', 'cmd'); $forcedItemType = $app->getInput()->get('forcedItemType', '', 'string'); // Adjust the context to support modal layouts. if ($layout = $app->getInput()->get('layout')) { $this->context .= '.' . $layout; } // Adjust the context to support forced languages. if ($forcedLanguage) { $this->context .= '.' . $forcedLanguage; } // Adjust the context to support forced component item types. if ($forcedItemType) { $this->context .= '.' . $forcedItemType; } $this->setState('itemtype', $this->getUserStateFromRequest($this->context . '.itemtype', 'itemtype', '', 'string')); $this->setState('language', $this->getUserStateFromRequest($this->context . '.language', 'language', '', 'string')); $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); $this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd')); $this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd')); $this->setState('filter.menutype', $this->getUserStateFromRequest($this->context . '.filter.menutype', 'filter_menutype', '', 'string')); $this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'string')); $this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd')); // List state information. parent::populateState($ordering, $direction); // Force a language. if (!empty($forcedLanguage)) { $this->setState('language', $forcedLanguage); } // Force a component item type. if (!empty($forcedItemType)) { $this->setState('itemtype', $forcedItemType); } } /** * Method to get a store id based on model configuration state. * * This is necessary because the model is used by the component and * different modules that might need different sets of data or different * ordering requirements. * * @param string $id A prefix for the store id. * * @return string A store id. * * @since 3.7.0 */ protected function getStoreId($id = '') { // Compile the store id. $id .= ':' . $this->getState('itemtype'); $id .= ':' . $this->getState('language'); $id .= ':' . $this->getState('filter.search'); $id .= ':' . $this->getState('filter.state'); $id .= ':' . $this->getState('filter.category_id'); $id .= ':' . $this->getState('filter.menutype'); $id .= ':' . $this->getState('filter.access'); $id .= ':' . $this->getState('filter.level'); return parent::getStoreId($id); } /** * Build an SQL query to load the list data. * * @return \Joomla\Database\DatabaseQuery|boolean * * @since 3.7.0 */ protected function getListQuery() { $type = null; list($extensionName, $typeName) = explode('.', $this->state->get('itemtype'), 2); $extension = AssociationsHelper::getSupportedExtension($extensionName); $types = $extension->get('types'); if (\array_key_exists($typeName, $types)) { $type = $types[$typeName]; } if (\is_null($type)) { return false; } // Create a new query object. $user = $this->getCurrentUser(); $db = $this->getDatabase(); $query = $db->getQuery(true); $details = $type->get('details'); if (!\array_key_exists('support', $details)) { return false; } $support = $details['support']; if (!\array_key_exists('fields', $details)) { return false; } $fields = $details['fields']; // Main query. $query->select($db->quoteName($fields['id'], 'id')) ->select($db->quoteName($fields['title'], 'title')) ->select($db->quoteName($fields['alias'], 'alias')); if (!\array_key_exists('tables', $details)) { return false; } $tables = $details['tables']; foreach ($tables as $key => $table) { $query->from($db->quoteName($table, $key)); } if (!\array_key_exists('joins', $details)) { return false; } $joins = $details['joins']; foreach ($joins as $join) { $query->join($join['type'], $db->quoteName($join['condition'])); } // Join over the language. $query->select($db->quoteName($fields['language'], 'language')) ->select($db->quoteName('l.title', 'language_title')) ->select($db->quoteName('l.image', 'language_image')) ->join( 'LEFT', $db->quoteName('#__languages', 'l'), $db->quoteName('l.lang_code') . ' = ' . $db->quoteName($fields['language']) ); $extensionNameItem = $extensionName . '.item'; // Join over the associations. $query->select('COUNT(' . $db->quoteName('asso2.id') . ') > 1 AS ' . $db->quoteName('association')) ->join( 'LEFT', $db->quoteName('#__associations', 'asso'), $db->quoteName('asso.id') . ' = ' . $db->quoteName($fields['id']) . ' AND ' . $db->quoteName('asso.context') . ' = :context' ) ->join( 'LEFT', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso2.key') . ' = ' . $db->quoteName('asso.key') ) ->bind(':context', $extensionNameItem); // Prepare the group by clause. $groupby = [ $fields['id'], $fields['title'], $fields['alias'], $fields['language'], 'l.title', 'l.image', ]; // Select author for ACL checks. if (!empty($fields['created_user_id'])) { $query->select($db->quoteName($fields['created_user_id'], 'created_user_id')); $groupby[] = $fields['created_user_id']; } // Select checked out data for check in checkins. if (!empty($fields['checked_out']) && !empty($fields['checked_out_time'])) { $query->select($db->quoteName($fields['checked_out'], 'checked_out')) ->select($db->quoteName($fields['checked_out_time'], 'checked_out_time')); // Join over the users. $query->select($db->quoteName('u.name', 'editor')) ->join( 'LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName($fields['checked_out']) ); $groupby[] = 'u.name'; $groupby[] = $fields['checked_out']; $groupby[] = $fields['checked_out_time']; } // If component item type supports ordering, select the ordering also. if (!empty($fields['ordering'])) { $query->select($db->quoteName($fields['ordering'], 'ordering')); $groupby[] = $fields['ordering']; } // If component item type supports state, select the item state also. if (!empty($fields['state'])) { $query->select($db->quoteName($fields['state'], 'state')); $groupby[] = $fields['state']; } // If component item type supports level, select the level also. if (!empty($fields['level'])) { $query->select($db->quoteName($fields['level'], 'level')); $groupby[] = $fields['level']; } // If component item type supports categories, select the category also. if (!empty($fields['catid'])) { $query->select($db->quoteName($fields['catid'], 'catid')); // Join over the categories. $query->select($db->quoteName('c.title', 'category_title')) ->join( 'LEFT', $db->quoteName('#__categories', 'c'), $db->quoteName('c.id') . ' = ' . $db->quoteName($fields['catid']) ); $groupby[] = 'c.title'; $groupby[] = $fields['catid']; } // If component item type supports menu type, select the menu type also. if (!empty($fields['menutype'])) { $query->select($db->quoteName($fields['menutype'], 'menutype')); // Join over the menu types. $query->select($db->quoteName('mt.title', 'menutype_title')) ->select($db->quoteName('mt.id', 'menutypeid')) ->join( 'LEFT', $db->quoteName('#__menu_types', 'mt'), $db->quoteName('mt.menutype') . ' = ' . $db->quoteName($fields['menutype']) ); $groupby[] = 'mt.title'; $groupby[] = 'mt.id'; $groupby[] = $fields['menutype']; } // If component item type supports access level, select the access level also. if (\array_key_exists('acl', $support) && $support['acl'] == true && !empty($fields['access'])) { $query->select($db->quoteName($fields['access'], 'access')); // Join over the access levels. $query->select($db->quoteName('ag.title', 'access_level')) ->join( 'LEFT', $db->quoteName('#__viewlevels', 'ag'), $db->quoteName('ag.id') . ' = ' . $db->quoteName($fields['access']) ); $groupby[] = 'ag.title'; $groupby[] = $fields['access']; // Implement View Level Access. if (!$user->authorise('core.admin', $extensionName)) { $groups = $user->getAuthorisedViewLevels(); $query->whereIn($db->quoteName($fields['access']), $groups); } } // If component item type is menus we need to remove the root item and the administrator menu. if ($extensionName === 'com_menus') { $query->where($db->quoteName($fields['id']) . ' > 1') ->where($db->quoteName('a.client_id') . ' = 0'); } // If component item type is category we need to remove all other component categories. if ($typeName === 'category') { $query->where($db->quoteName('a.extension') . ' = :extensionname') ->bind(':extensionname', $extensionName); } elseif ($typeNameExploded = explode('.', $typeName)) { if (\count($typeNameExploded) > 1 && array_pop($typeNameExploded) === 'category') { $section = implode('.', $typeNameExploded); $extensionNameSection = $extensionName . '.' . $section; $query->where($db->quoteName('a.extension') . ' = :extensionsection') ->bind(':extensionsection', $extensionNameSection); } } // Filter on the language. if ($language = $this->getState('language')) { $query->where($db->quoteName($fields['language']) . ' = :language') ->bind(':language', $language); } // Filter by item state. $state = $this->getState('filter.state'); if (is_numeric($state)) { $state = (int) $state; $query->where($db->quoteName($fields['state']) . ' = :state') ->bind(':state', $state, ParameterType::INTEGER); } elseif ($state === '') { $query->whereIn($db->quoteName($fields['state']), [0, 1]); } // Filter on the category. $baselevel = 1; if ($categoryId = $this->getState('filter.category_id')) { $categoryTable = Table::getInstance('Category', 'JTable'); $categoryTable->load($categoryId); $baselevel = (int) $categoryTable->level; $lft = (int) $categoryTable->lft; $rgt = (int) $categoryTable->rgt; $query->where($db->quoteName('c.lft') . ' >= :lft') ->where($db->quoteName('c.rgt') . ' <= :rgt') ->bind(':lft', $lft, ParameterType::INTEGER) ->bind(':rgt', $rgt, ParameterType::INTEGER); } // Filter on the level. if ($level = $this->getState('filter.level')) { $queryLevel = ((int) $level + (int) $baselevel - 1); $query->where($db->quoteName('a.level') . ' <= :alevel') ->bind(':alevel', $queryLevel, ParameterType::INTEGER); } // Filter by menu type. if ($menutype = $this->getState('filter.menutype')) { $query->where($db->quoteName($fields['menutype']) . ' = :menutype2') ->bind(':menutype2', $menutype); } // Filter by access level. if ($access = $this->getState('filter.access')) { $access = (int) $access; $query->where($db->quoteName($fields['access']) . ' = :access') ->bind(':access', $access, ParameterType::INTEGER); } // Filter by search in name. if ($search = $this->getState('filter.search')) { if (stripos($search, 'id:') === 0) { $search = (int) substr($search, 3); $query->where($db->quoteName($fields['id']) . ' = :searchid') ->bind(':searchid', $search, ParameterType::INTEGER); } else { $search = '%' . str_replace(' ', '%', trim($search)) . '%'; $query->where('(' . $db->quoteName($fields['title']) . ' LIKE :title' . ' OR ' . $db->quoteName($fields['alias']) . ' LIKE :alias)') ->bind(':title', $search) ->bind(':alias', $search); } } // Add the group by clause $query->group($db->quoteName($groupby)); // Add the list ordering clause $listOrdering = $this->state->get('list.ordering', 'id'); $orderDirn = $this->state->get('list.direction', 'ASC'); $query->order($db->escape($listOrdering) . ' ' . $db->escape($orderDirn)); return $query; } /** * Delete associations from #__associations table. * * @param string $context The associations context. Empty for all. * @param string $key The associations key. Empty for all. * * @return boolean True on success. * * @since 3.7.0 */ public function purge($context = '', $key = '') { $app = Factory::getApplication(); $db = $this->getDatabase(); $query = $db->getQuery(true)->delete($db->quoteName('#__associations')); // Filter by associations context. if ($context) { $query->where($db->quoteName('context') . ' = :context') ->bind(':context', $context); } // Filter by key. if ($key) { $query->where($db->quoteName('key') . ' = :key') ->bind(':key', $key); } $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { $app->enqueueMessage(Text::_('COM_ASSOCIATIONS_PURGE_FAILED'), 'error'); return false; } $app->enqueueMessage( Text::_((int) $db->getAffectedRows() > 0 ? 'COM_ASSOCIATIONS_PURGE_SUCCESS' : 'COM_ASSOCIATIONS_PURGE_NONE'), 'message' ); return true; } /** * Delete orphans from the #__associations table. * * @param string $context The associations context. Empty for all. * @param string $key The associations key. Empty for all. * * @return boolean True on success * * @since 3.7.0 */ public function clean($context = '', $key = '') { $app = Factory::getApplication(); $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('key') . ', COUNT(*)') ->from($db->quoteName('#__associations')) ->group($db->quoteName('key')) ->having('COUNT(*) = 1'); // Filter by associations context. if ($context) { $query->where($db->quoteName('context') . ' = :context') ->bind(':context', $context); } // Filter by key. if ($key) { $query->where($db->quoteName('key') . ' = :key') ->bind(':key', $key); } $db->setQuery($query); $assocKeys = $db->loadObjectList(); $count = 0; // We have orphans. Let's delete them. foreach ($assocKeys as $value) { $query->clear() ->delete($db->quoteName('#__associations')) ->where($db->quoteName('key') . ' = :valuekey') ->bind(':valuekey', $value->key); $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { $app->enqueueMessage(Text::_('COM_ASSOCIATIONS_DELETE_ORPHANS_FAILED'), 'error'); return false; } $count += (int) $db->getAffectedRows(); } $app->enqueueMessage( Text::_($count > 0 ? 'COM_ASSOCIATIONS_DELETE_ORPHANS_SUCCESS' : 'COM_ASSOCIATIONS_DELETE_ORPHANS_NONE'), 'message' ); return true; } } src/Model/AssociationModel.php 0000644 00000002250 15062153647 0012351 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Model; use Joomla\CMS\MVC\Model\ListModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Methods supporting a list of article records. * * @since 3.7.0 */ class AssociationModel extends ListModel { /** * Method to get the record form. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure * * @since 3.7.0 */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_associations.association', 'association', ['control' => 'jform', 'load_data' => $loadData]); return !empty($form) ? $form : false; } } src/Helper/AssociationsHelper.php 0000644 00000052032 15062153647 0013075 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Helper; use Joomla\CMS\Association\AssociationExtensionInterface; use Joomla\CMS\Association\AssociationServiceInterface; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Associations component helper. * * @since 3.7.0 */ class AssociationsHelper extends ContentHelper { /** * Array of Registry objects of extensions * * @var array * @since 3.7.0 */ public static $extensionsSupport = null; /** * List of extensions name with support * * @var array * @since 3.7.0 */ public static $supportedExtensionsList = []; /** * Get the associated items for an item * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param int $itemId The id of item for which we need the associated items * * @return array * * @since 3.7.0 */ public static function getAssociationList($extensionName, $typeName, $itemId) { if (!self::hasSupport($extensionName)) { return []; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); return $helper->getAssociationList($typeName, $itemId); } /** * Get the instance of the extension helper class * * @param string $extensionName The extension name with com_ * * @return \Joomla\CMS\Association\AssociationExtensionHelper|null * * @since 3.7.0 */ public static function getExtensionHelper($extensionName) { if (!self::hasSupport($extensionName)) { return null; } $support = self::$extensionsSupport[$extensionName]; return $support->get('helper'); } /** * Get item information * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param int $itemId The id of item for which we need the associated items * * @return \Joomla\CMS\Table\Table|null * * @since 3.7.0 */ public static function getItem($extensionName, $typeName, $itemId) { if (!self::hasSupport($extensionName)) { return null; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); return $helper->getItem($typeName, $itemId); } /** * Check if extension supports associations * * @param string $extensionName The extension name with com_ * * @return boolean * * @since 3.7.0 */ public static function hasSupport($extensionName) { if (\is_null(self::$extensionsSupport)) { self::getSupportedExtensions(); } return \in_array($extensionName, self::$supportedExtensionsList); } /** * Loads the helper for the given class. * * @param string $extensionName The extension name with com_ * * @return AssociationExtensionInterface|null * * @since 4.0.0 */ private static function loadHelper($extensionName) { $component = Factory::getApplication()->bootComponent($extensionName); if ($component instanceof AssociationServiceInterface) { return $component->getAssociationsExtension(); } // Check if associations helper exists if (!file_exists(JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php')) { return null; } require_once JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php'; $componentAssociationsHelperClassName = self::getExtensionHelperClassName($extensionName); if (!class_exists($componentAssociationsHelperClassName, false)) { return null; } // Create an instance of the helper class return new $componentAssociationsHelperClassName(); } /** * Get the extension specific helper class name * * @param string $extensionName The extension name with com_ * * @return string * * @since 3.7.0 */ private static function getExtensionHelperClassName($extensionName) { $realName = self::getExtensionRealName($extensionName); return ucfirst($realName) . 'AssociationsHelper'; } /** * Get the real extension name. This means without com_ * * @param string $extensionName The extension name with com_ * * @return string * * @since 3.7.0 */ private static function getExtensionRealName($extensionName) { return strpos($extensionName, 'com_') === false ? $extensionName : substr($extensionName, 4); } /** * Get the associated language edit links Html. * * @param string $extensionName Extension Name * @param string $typeName ItemType * @param integer $itemId Item id. * @param string $itemLanguage Item language code. * @param boolean $addLink True for adding edit links. False for just text. * @param boolean $assocLanguages True for showing non associated content languages. False only languages with associations. * * @return string The language HTML * * @since 3.7.0 */ public static function getAssociationHtmlList($extensionName, $typeName, $itemId, $itemLanguage, $addLink = true, $assocLanguages = true) { // Get the associations list for this item. $items = self::getAssociationList($extensionName, $typeName, $itemId); $titleFieldName = self::getTypeFieldName($extensionName, $typeName, 'title'); // Get all content languages. $languages = LanguageHelper::getContentLanguages([0, 1], false); $content_languages = array_column($languages, 'lang_code'); // Display warning if Content Language is trashed or deleted foreach ($items as $item) { if (!\in_array($item['language'], $content_languages)) { Factory::getApplication()->enqueueMessage(Text::sprintf('JGLOBAL_ASSOCIATIONS_CONTENTLANGUAGE_WARNING', $item['language']), 'warning'); } } $canEditReference = self::allowEdit($extensionName, $typeName, $itemId); $canCreate = self::allowAdd($extensionName, $typeName); // Create associated items list. foreach ($languages as $langCode => $language) { // Don't do for the reference language. if ($langCode == $itemLanguage) { continue; } // Don't show languages with associations, if we don't want to show them. if ($assocLanguages && isset($items[$langCode])) { unset($items[$langCode]); continue; } // Don't show languages without associations, if we don't want to show them. if (!$assocLanguages && !isset($items[$langCode])) { continue; } // Get html parameters. if (isset($items[$langCode])) { $title = $items[$langCode][$titleFieldName]; $additional = ''; if (isset($items[$langCode]['catid'])) { $db = Factory::getDbo(); // Get the category name $query = $db->getQuery(true) ->select($db->quoteName('title')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :id') ->bind(':id', $items[$langCode]['catid'], ParameterType::INTEGER); $db->setQuery($query); $categoryTitle = $db->loadResult(); $additional = '<strong>' . Text::sprintf('JCATEGORY_SPRINTF', $categoryTitle) . '</strong> <br>'; } elseif (isset($items[$langCode]['menutype'])) { $db = Factory::getDbo(); // Get the menutype name $query = $db->getQuery(true) ->select($db->quoteName('title')) ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('menutype') . ' = :menutype') ->bind(':menutype', $items[$langCode]['menutype']); $db->setQuery($query); $menutypeTitle = $db->loadResult(); $additional = '<strong>' . Text::sprintf('COM_MENUS_MENU_SPRINTF', $menutypeTitle) . '</strong><br>'; } $labelClass = 'bg-secondary'; $target = $langCode . ':' . $items[$langCode]['id'] . ':edit'; $allow = $canEditReference && self::allowEdit($extensionName, $typeName, $items[$langCode]['id']) && self::canCheckinItem($extensionName, $typeName, $items[$langCode]['id']); $additional .= $addLink && $allow ? Text::_('COM_ASSOCIATIONS_EDIT_ASSOCIATION') : ''; } else { $items[$langCode] = []; $title = Text::_('COM_ASSOCIATIONS_NO_ASSOCIATION'); $additional = $addLink ? Text::_('COM_ASSOCIATIONS_ADD_NEW_ASSOCIATION') : ''; $labelClass = 'bg-warning text-dark'; $target = $langCode . ':0:add'; $allow = $canCreate; } // Generate item Html. $options = [ 'option' => 'com_associations', 'view' => 'association', 'layout' => 'edit', 'itemtype' => $extensionName . '.' . $typeName, 'task' => 'association.edit', 'id' => $itemId, 'target' => $target, ]; $url = Route::_('index.php?' . http_build_query($options)); $url = $allow && $addLink ? $url : ''; $text = $language->lang_code; $tooltip = '<strong>' . htmlspecialchars($language->title, ENT_QUOTES, 'UTF-8') . '</strong><br>' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '<br><br>' . $additional; $classes = 'badge ' . $labelClass; $items[$langCode]['link'] = '<a href="' . $url . '" class="' . $classes . '">' . $text . '</a>' . '<div role="tooltip">' . $tooltip . '</div>'; } return LayoutHelper::render('joomla.content.associations', $items); } /** * Get all extensions with associations support. * * @return array The extensions. * * @since 3.7.0 */ public static function getSupportedExtensions() { if (!\is_null(self::$extensionsSupport)) { return self::$extensionsSupport; } self::$extensionsSupport = []; $extensions = self::getEnabledExtensions(); foreach ($extensions as $extension) { $support = self::getSupportedExtension($extension->element); if ($support->get('associationssupport') === true) { self::$supportedExtensionsList[] = $extension->element; } self::$extensionsSupport[$extension->element] = $support; } return self::$extensionsSupport; } /** * Get item context based on the item key. * * @param string $extensionName The extension identifier. * * @return \Joomla\Registry\Registry The item properties. * * @since 3.7.0 */ public static function getSupportedExtension($extensionName) { $result = new Registry(); $result->def('component', $extensionName); $result->def('associationssupport', false); $result->def('helper', null); $helper = self::loadHelper($extensionName); if (!$helper) { return $result; } $result->set('helper', $helper); if ($helper->hasAssociationsSupport() === false) { return $result; } $result->set('associationssupport', true); // Get the translated titles. $languagePath = JPATH_ADMINISTRATOR . '/components/' . $extensionName; $lang = Factory::getLanguage(); $lang->load($extensionName . '.sys', JPATH_ADMINISTRATOR); $lang->load($extensionName . '.sys', $languagePath); $lang->load($extensionName, JPATH_ADMINISTRATOR); $lang->load($extensionName, $languagePath); $result->def('title', Text::_(strtoupper($extensionName))); // Get the supported types $types = $helper->getItemTypes(); $rTypes = []; foreach ($types as $typeName) { $details = $helper->getType($typeName); $context = 'component'; $title = $helper->getTypeTitle($typeName); $languageKey = $typeName; $typeNameExploded = explode('.', $typeName); if (array_pop($typeNameExploded) === 'category') { $languageKey = strtoupper($extensionName) . '_CATEGORIES'; $context = 'category'; } if ($lang->hasKey(strtoupper($extensionName . '_' . $title . 'S'))) { $languageKey = strtoupper($extensionName . '_' . $title . 'S'); } $title = $lang->hasKey($languageKey) ? Text::_($languageKey) : Text::_('COM_ASSOCIATIONS_ITEMS'); $rType = new Registry(); $rType->def('name', $typeName); $rType->def('details', $details); $rType->def('title', $title); $rType->def('context', $context); $rTypes[$typeName] = $rType; } $result->def('types', $rTypes); return $result; } /** * Get all installed and enabled extensions * * @return mixed * * @since 3.7.0 */ private static function getEnabledExtensions() { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('component')) ->where($db->quoteName('enabled') . ' = 1'); $db->setQuery($query); return $db->loadObjectList(); } /** * Get all the content languages. * * @return array Array of objects all content languages by language code. * * @since 3.7.0 */ public static function getContentLanguages() { return LanguageHelper::getContentLanguages([0, 1]); } /** * Get the associated items for an item * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param int $itemId The id of item for which we need the associated items * * @return boolean * * @since 3.7.0 */ public static function allowEdit($extensionName, $typeName, $itemId) { if (!self::hasSupport($extensionName)) { return false; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); if (method_exists($helper, 'allowEdit')) { return $helper->allowEdit($typeName, $itemId); } return Factory::getUser()->authorise('core.edit', $extensionName); } /** * Check if user is allowed to create items. * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * * @return boolean True on allowed. * * @since 3.7.0 */ public static function allowAdd($extensionName, $typeName) { if (!self::hasSupport($extensionName)) { return false; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); if (method_exists($helper, 'allowAdd')) { return $helper->allowAdd($typeName); } return Factory::getUser()->authorise('core.create', $extensionName); } /** * Check if an item is checked out * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param int $itemId The id of item for which we need the associated items * * @return boolean True if item is checked out. * * @since 3.7.0 */ public static function isCheckoutItem($extensionName, $typeName, $itemId) { if (!self::hasSupport($extensionName)) { return false; } if (!self::typeSupportsCheckout($extensionName, $typeName)) { return false; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); if (method_exists($helper, 'isCheckoutItem')) { return $helper->isCheckoutItem($typeName, $itemId); } $item = self::getItem($extensionName, $typeName, $itemId); $checkedOutFieldName = $helper->getTypeFieldName($typeName, 'checked_out'); return $item->{$checkedOutFieldName} != 0; } /** * Check if user can checkin an item. * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param int $itemId The id of item for which we need the associated items * * @return boolean True on allowed. * * @since 3.7.0 */ public static function canCheckinItem($extensionName, $typeName, $itemId) { if (!self::hasSupport($extensionName)) { return false; } if (!self::typeSupportsCheckout($extensionName, $typeName)) { return true; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); if (method_exists($helper, 'canCheckinItem')) { return $helper->canCheckinItem($typeName, $itemId); } $item = self::getItem($extensionName, $typeName, $itemId); $checkedOutFieldName = $helper->getTypeFieldName($typeName, 'checked_out'); $userId = Factory::getUser()->id; return ($item->{$checkedOutFieldName} == $userId || $item->{$checkedOutFieldName} == 0); } /** * Check if the type supports checkout * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * * @return boolean True on allowed. * * @since 3.7.0 */ public static function typeSupportsCheckout($extensionName, $typeName) { if (!self::hasSupport($extensionName)) { return false; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); $support = $helper->getTypeSupport($typeName); return !empty($support['checkout']); } /** * Get a table field name for a type * * @param string $extensionName The extension name with com_ * @param string $typeName The item type * @param string $fieldName The item type * * @return boolean True on allowed. * * @since 3.7.0 */ public static function getTypeFieldName($extensionName, $typeName, $fieldName) { if (!self::hasSupport($extensionName)) { return false; } // Get the extension specific helper method $helper = self::getExtensionHelper($extensionName); return $helper->getTypeFieldName($typeName, $fieldName); } /** * Gets the language filter system plugin extension id. * * @return integer The language filter system plugin extension id. * * @since 3.7.2 */ public static function getLanguagefilterPluginId() { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) ->where($db->quoteName('element') . ' = ' . $db->quote('languagefilter')); $db->setQuery($query); try { $result = (int) $db->loadResult(); } catch (\RuntimeException $e) { Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); } return $result; } } src/Field/Modal/AssociationField.php 0000644 00000007411 15062153647 0013357 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Field\Modal; use Joomla\CMS\Factory; use Joomla\CMS\Form\FormField; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Session\Session; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Supports a modal item picker. * * @since 3.7.0 */ class AssociationField extends FormField { /** * The form field type. * * @var string * @since 3.7.0 */ protected $type = 'Modal_Association'; /** * Method to get the field input markup. * * @return string The field input markup. * * @since 3.7.0 */ protected function getInput() { // @todo USE Layouts here!!! // The active item id field. $value = (int) $this->value ?: ''; $doc = Factory::getApplication()->getDocument(); $wa = $doc->getWebAssetManager(); $doc->addScriptOptions('admin_associations_modal', ['itemId' => $value]); $wa->useScript('com_associations.admin-associations-modal'); // Setup variables for display. $html = []; $linkAssociations = 'index.php?option=com_associations&view=associations&layout=modal&tmpl=component' . '&forcedItemType=' . Factory::getApplication()->getInput()->get('itemtype', '', 'string') . '&function=jSelectAssociation_' . $this->id; $linkAssociations .= "&forcedLanguage=' + document.getElementById('target-association').getAttribute('data-language') + '"; $urlSelect = $linkAssociations . '&' . Session::getFormToken() . '=1'; // Select custom association button $html[] = '<button' . ' type="button"' . ' id="select-change"' . ' class="btn btn-secondary' . ($value ? '' : ' hidden') . '"' . ' data-bs-toggle="modal"' . ' data-select="' . Text::_('COM_ASSOCIATIONS_SELECT_TARGET') . '"' . ' data-change="' . Text::_('COM_ASSOCIATIONS_CHANGE_TARGET') . '"' . ' data-bs-target="#associationSelect' . $this->id . 'Modal">' . '<span class="icon-file" aria-hidden="true"></span> ' . '<span id="select-change-text"></span>' . '</button>'; // Clear association button $html[] = '<button' . ' type="button"' . ' class="btn btn-secondary' . ($value ? '' : ' hidden') . '"' . ' onclick="return Joomla.submitbutton(\'undo-association\');"' . ' id="remove-assoc">' . '<span class="icon-times" aria-hidden="true"></span> ' . Text::_('JCLEAR') . '</button>'; $html[] = '<input type="hidden" id="' . $this->id . '_id" name="' . $this->name . '" value="' . $value . '">'; // Select custom association modal $html[] = HTMLHelper::_( 'bootstrap.renderModal', 'associationSelect' . $this->id . 'Modal', [ 'title' => Text::_('COM_ASSOCIATIONS_SELECT_TARGET'), 'backdrop' => 'static', 'url' => $urlSelect, 'height' => '400px', 'width' => '800px', 'bodyHeight' => 70, 'modalWidth' => 80, 'footer' => '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">' . Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>', ] ); return implode("\n", $html); } } src/Field/ItemtypeField.php 0000644 00000003471 15062153647 0011651 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Field; use Joomla\CMS\Form\Field\GroupedlistField; use Joomla\CMS\HTML\HTMLHelper; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * A drop down containing all component item types that implement associations. * * @since 3.7.0 */ class ItemtypeField extends GroupedlistField { /** * The form field type. * * @var string * * @since 3.7.0 */ protected $type = 'Itemtype'; /** * Method to get the field input markup. * * @return array The field option objects as a nested array in groups. * * @since 3.7.0 * * @throws \UnexpectedValueException */ protected function getGroups() { $options = []; $extensions = AssociationsHelper::getSupportedExtensions(); foreach ($extensions as $extension) { if ($extension->get('associationssupport') === true) { foreach ($extension->get('types') as $type) { $context = $extension->get('component') . '.' . $type->get('name'); $options[$extension->get('title')][] = HTMLHelper::_('select.option', $context, $type->get('title')); } } } // Sort by alpha order. uksort($options, 'strnatcmp'); // Add options to parent array. return array_merge(parent::getGroups(), $options); } } src/Field/ItemlanguageField.php 0000644 00000007243 15062153647 0012454 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Associations\Administrator\Field; use Joomla\CMS\Factory; use Joomla\CMS\Form\Field\ListField; use Joomla\CMS\Language\LanguageHelper; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Field listing item languages * * @since 3.7.0 */ class ItemlanguageField extends ListField { /** * The form field type. * * @var string * @since 3.7.0 */ protected $type = 'Itemlanguage'; /** * Method to get the field options. * * @return array The field option objects. * * @since 3.7.0 */ protected function getOptions() { $input = Factory::getApplication()->getInput(); list($extensionName, $typeName) = explode('.', $input->get('itemtype', '', 'string'), 2); // Get the extension specific helper method $helper = AssociationsHelper::getExtensionHelper($extensionName); $languageField = $helper->getTypeFieldName($typeName, 'language'); $referenceId = $input->get('id', 0, 'int'); $reference = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId)); $referenceLang = $reference[$languageField]; // Get item associations given ID and item type $associations = AssociationsHelper::getAssociationList($extensionName, $typeName, $referenceId); // Check if user can create items in this component item type. $canCreate = AssociationsHelper::allowAdd($extensionName, $typeName); // Gets existing languages. $existingLanguages = LanguageHelper::getContentLanguages([0, 1], false); $options = []; // Each option has the format "<lang>|<id>", example: "en-GB|1" foreach ($existingLanguages as $langCode => $language) { // If language code is equal to reference language we don't need it. if ($language->lang_code == $referenceLang) { continue; } $options[$langCode] = new \stdClass(); $options[$langCode]->text = $language->title; // If association exists in this language. if (isset($associations[$language->lang_code])) { $itemId = (int) $associations[$language->lang_code]['id']; $options[$langCode]->value = $language->lang_code . ':' . $itemId . ':edit'; // Check if user does have permission to edit the associated item. $canEdit = AssociationsHelper::allowEdit($extensionName, $typeName, $itemId); // Check if item can be checked out $canCheckout = AssociationsHelper::canCheckinItem($extensionName, $typeName, $itemId); // Disable language if user is not allowed to edit the item associated to it. $options[$langCode]->disable = !($canEdit && $canCheckout); } else { // New item, id = 0 and disabled if user is not allowed to create new items. $options[$langCode]->value = $language->lang_code . ':0:add'; // Disable language if user is not allowed to create items. $options[$langCode]->disable = !$canCreate; } } return array_merge(parent::getOptions(), $options); } } layouts/joomla/searchtools/default.php 0000644 00000012412 15062153647 0014221 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2018 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\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; $data = $displayData; // Receive overridable options $data['options'] = !empty($data['options']) ? $data['options'] : []; $noResultsText = ''; $hideActiveFilters = false; $showFilterButton = false; $showSelector = false; $selectorFieldName = $data['options']['selectorFieldName'] ?? 'client_id'; // If a filter form exists. if (isset($data['view']->filterForm) && !empty($data['view']->filterForm)) { // Checks if a selector (e.g. client_id) exists. if ($selectorField = $data['view']->filterForm->getField($selectorFieldName)) { $showSelector = $selectorField->getAttribute('filtermode', '') === 'selector' ? true : $showSelector; // Checks if a selector should be shown in the current layout. if (isset($data['view']->layout)) { $showSelector = $selectorField->getAttribute('layout', 'default') != $data['view']->layout ? false : $showSelector; } // Unset the selector field from active filters group. unset($data['view']->activeFilters[$selectorFieldName]); } // Checks if the filters button should exist. $filters = $data['view']->filterForm->getGroup('filter'); $showFilterButton = isset($filters['filter_search']) && count($filters) === 1 ? false : true; // Checks if it should show the be hidden. $hideActiveFilters = empty($data['view']->activeFilters); // Check if the no results message should appear. if (isset($data['view']->total) && (int) $data['view']->total === 0) { $noResults = $data['view']->filterForm->getFieldAttribute('search', 'noresults', '', 'filter'); if (!empty($noResults)) { $noResultsText = Text::_($noResults); } } } // Set some basic options. $customOptions = [ 'filtersHidden' => isset($data['options']['filtersHidden']) && $data['options']['filtersHidden'] ? $data['options']['filtersHidden'] : $hideActiveFilters, 'filterButton' => isset($data['options']['filterButton']) && $data['options']['filterButton'] ? $data['options']['filterButton'] : $showFilterButton, 'defaultLimit' => $data['options']['defaultLimit'] ?? Factory::getApplication()->get('list_limit', 20), 'searchFieldSelector' => '#filter_search', 'selectorFieldName' => $selectorFieldName, 'showSelector' => $showSelector, 'orderFieldSelector' => '#list_fullordering', 'showNoResults' => !empty($noResultsText), 'noResultsText' => !empty($noResultsText) ? $noResultsText : '', 'formSelector' => !empty($data['options']['formSelector']) ? $data['options']['formSelector'] : '#adminForm', ]; // Merge custom options in the options array. $data['options'] = array_merge($customOptions, $data['options']); // Add class to hide the active filters if needed. $filtersActiveClass = $hideActiveFilters ? '' : ' js-stools-container-filters-visible'; // Load search tools HTMLHelper::_('searchtools.form', $data['options']['formSelector'], $data['options']); ?> <div class="js-stools" role="search"> <?php // Add the itemtype and language selectors before the form filters. Do not display in modal. ?> <?php $app = Factory::getApplication(); ?> <?php if ($app->getInput()->get('forcedItemType', '', 'string') == '') : ?> <?php $itemTypeField = $data['view']->filterForm->getField('itemtype'); ?> <div class="js-stools-container-selector"> <div class="js-stools-field-selector js-stools-itemtype"> <div class="visually-hidden"><?php echo $itemTypeField->label; ?></div> <?php echo $itemTypeField->input; ?> </div> </div> <?php endif; ?> <?php if ($app->getInput()->get('forcedLanguage', '', 'cmd') == '') : ?> <?php $languageField = $data['view']->filterForm->getField('language'); ?> <div class="js-stools-container-selector"> <div class="js-stools-field-selector js-stools-language"> <div class="visually-hidden"><?php echo $languageField->label; ?></div> <?php echo $languageField->input; ?> </div> </div> <?php endif; ?> <?php if ($data['options']['showSelector']) : ?> <div class="js-stools-container-selector"> <?php echo LayoutHelper::render('joomla.searchtools.default.selector', $data); ?> </div> <?php endif; ?> <div class="js-stools-container-bar ms-auto"> <div class="btn-toolbar"> <?php echo $this->sublayout('bar', $data); ?> <?php echo $this->sublayout('list', $data); ?> </div> </div> <!-- Filters div --> <div class="js-stools-container-filters clearfix<?php echo $filtersActiveClass; ?>"> <?php if ($data['options']['filterButton']) : ?> <?php echo $this->sublayout('filters', $data); ?> <?php endif; ?> </div> </div> <?php if ($data['options']['showNoResults']) : ?> <?php echo $this->sublayout('noitems', $data); ?> <?php endif; ?> tmpl/associations/modal.php 0000644 00000021421 15062153647 0012035 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_associations * * @copyright (C) 2017 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\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; $app = Factory::getApplication(); if ($app->isClient('site')) { Session::checkToken('get') or die(Text::_('JINVALID_TOKEN')); } /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->document->getWebAssetManager(); $wa->useScript('multiselect') ->useScript('com_associations.admin-associations-modal'); $function = $app->getInput()->getCmd('function', 'jSelectAssociation'); $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); $canManageCheckin = Factory::getUser()->authorise('core.manage', 'com_checkin'); $iconStates = [ -2 => 'icon-trash', 0 => 'icon-unpublish', 1 => 'icon-publish', 2 => 'icon-archive', ]; $this->document->addScriptOptions('associations-modal', ['func' => $function]); ?> <div class="container-popup"> <form action="<?php echo Route::_('index.php?option=com_associations&view=associations&layout=modal&tmpl=component&function=' . $function . '&' . Session::getFormToken() . '=1'); ?>" method="post" name="adminForm" id="adminForm"> <?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?> <?php if (empty($this->items)) : ?> <div class="alert alert-info"> <span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span> <?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?> </div> <?php else : ?> <table class="table" id="associationsList"> <caption class="visually-hidden"> <?php echo Text::_('COM_ASSOCIATIONS_TABLE_CAPTION'); ?>, <span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>, <span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span> </caption> <thead> <tr> <?php if (!empty($this->typeSupports['state'])) : ?> <th scope="col" class="w-1 text-center"> <?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'state', $listDirn, $listOrder); ?> </th> <?php endif; ?> <th scope="col"> <?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'title', $listDirn, $listOrder); ?> </th> <th scope="col" class="w-15"> <?php echo Text::_('JGRID_HEADING_LANGUAGE'); ?> </th> <th scope="col" class="w-5"> <?php echo HTMLHelper::_('searchtools.sort', 'COM_ASSOCIATIONS_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?> </th> <?php if (!empty($this->typeFields['menutype'])) : ?> <th scope="col" class="w-10"> <?php echo HTMLHelper::_('searchtools.sort', 'COM_ASSOCIATIONS_HEADING_MENUTYPE', 'menutype_title', $listDirn, $listOrder); ?> </th> <?php endif; ?> <?php if (!empty($this->typeSupports['acl'])) : ?> <th scope="col" class="w-5 d-none d-sm-table-cell"> <?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?> </th> <?php endif; ?> <th scope="col" class="w-1 d-none d-sm-table-cell"> <?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'id', $listDirn, $listOrder); ?> </th> </tr> </thead> <tbody> <?php foreach ($this->items as $i => $item) : $canEdit = AssociationsHelper::allowEdit($this->extensionName, $this->typeName, $item->id); $canCheckin = $canManageCheckin || AssociationsHelper::canCheckinItem($this->extensionName, $this->typeName, $item->id); $isCheckout = AssociationsHelper::isCheckoutItem($this->extensionName, $this->typeName, $item->id); ?> <tr class="row<?php echo $i % 2; ?>"> <?php if (!empty($this->typeSupports['state'])) : ?> <td class="text-center"> <span class="tbody-icon"> <span class="<?php echo $iconStates[$this->escape($item->state)]; ?>" aria-hidden="true"></span> </span> </td> <?php endif; ?> <th scope="row" class="has-context"> <?php if (isset($item->level)) : ?> <?php echo LayoutHelper::render('joomla.html.treeprefix', ['level' => $item->level]); ?> <?php endif; ?> <?php if (($canEdit && !$isCheckout) || ($canEdit && $canCheckin && $isCheckout)) : ?> <a class="select-link" href="javascript:void(0);" data-id="<?php echo $item->id; ?>"> <?php echo $this->escape($item->title); ?></a> <?php elseif ($canEdit && $isCheckout) : ?> <?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'associations.'); ?> <span title="<?php echo Text::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"> <?php echo $this->escape($item->title); ?></span> <?php else : ?> <span title="<?php echo Text::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"> <?php echo $this->escape($item->title); ?></span> <?php endif; ?> <?php if (!empty($this->typeFields['alias'])) : ?> <span class="small"> <?php echo Text::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?> </span> <?php endif; ?> <?php if (!empty($this->typeFields['catid'])) : ?> <div class="small"> <?php echo Text::_('JCATEGORY') . ": " . $this->escape($item->category_title); ?> </div> <?php endif; ?> </th> <td class="small"> <?php echo LayoutHelper::render('joomla.content.language', $item); ?> </td> <td> <?php if (true || $item->association) : ?> <?php echo AssociationsHelper::getAssociationHtmlList($this->extensionName, $this->typeName, (int) $item->id, $item->language, false, false); ?> <?php endif; ?> </td> <?php if (!empty($this->typeFields['menutype'])) : ?> <td class="small"> <?php echo $this->escape($item->menutype_title); ?> </td> <?php endif; ?> <?php if (!empty($this->typeSupports['acl'])) : ?> <td class="small d-none d-sm-table-cell"> <?php echo $this->escape($item->access_level); ?> </td> <?php endif; ?> <td class="d-none d-sm-table-cell"> <?php echo $item->id; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php // load the pagination. ?> <?php echo $this->pagination->getListFooter(); ?> <?php endif; ?> <input type="hidden" name="task" value=""> <input type="hidden" name="forcedItemType" value="<?php echo $app->getInput()->get('forcedItemType', '', 'string'); ?>"> <input type="hidden" name="forcedLanguage" value="<?php echo $app->getInput()->get('forcedLanguage', '', 'cmd'); ?>"> <?php echo HTMLHelper::_('form.token'); ?> </form> </div> tmpl/associations/default.xml 0000644 00000000264 15062153647 0012400 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <metadata> <layout title="COM_ASSOCIATIONS"> <message> <![CDATA[COM_ASSOCIATIONS_XML_DESCRIPTION]]> </message> </layout> </metadata>