first commit
This commit is contained in:
28
administrator/components/com_categories/categories.xml
Normal file
28
administrator/components/com_categories/categories.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_categories</name>
|
||||
<author>Joomla! Project</author>
|
||||
<creationDate>2007-12</creationDate>
|
||||
<copyright>(C) 2007 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.0.0</version>
|
||||
<description>COM_CATEGORIES_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Component\Categories</namespace>
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<filename>categories.xml</filename>
|
||||
<folder>forms</folder>
|
||||
<folder>helpers</folder>
|
||||
<folder>layouts</folder>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<languages folder="admin">
|
||||
<language tag="en-GB">language/en-GB/com_categories.ini</language>
|
||||
<language tag="en-GB">language/en-GB/com_categories.sys.ini</language>
|
||||
</languages>
|
||||
</administration>
|
||||
</extension>
|
||||
280
administrator/components/com_categories/forms/category.xml
Normal file
280
administrator/components/com_categories/forms/category.xml
Normal file
@ -0,0 +1,280 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Categories\Administrator\Field">
|
||||
|
||||
<field
|
||||
name="id"
|
||||
type="text"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
default="0"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="hits"
|
||||
type="text"
|
||||
label="JGLOBAL_HITS"
|
||||
default="0"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="asset_id"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="parent_id"
|
||||
type="categoryedit"
|
||||
label="COM_CATEGORIES_FIELD_PARENT_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="lft"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="rgt"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="level"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="path"
|
||||
type="text"
|
||||
label="COM_CATEGORIES_PATH_LABEL"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="extension"
|
||||
type="hidden"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="JGLOBAL_TITLE"
|
||||
required="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="alias"
|
||||
type="text"
|
||||
label="JFIELD_ALIAS_LABEL"
|
||||
description="JFIELD_ALIAS_DESC"
|
||||
hint="JFIELD_ALIAS_PLACEHOLDER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="version_note"
|
||||
type="text"
|
||||
label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
|
||||
maxlength="255"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="note"
|
||||
type="text"
|
||||
label="COM_CATEGORIES_FIELD_NOTE_LABEL"
|
||||
maxlength="255"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="description"
|
||||
type="editor"
|
||||
label="JGLOBAL_DESCRIPTION"
|
||||
filter="\Joomla\CMS\Component\ComponentHelper::filterText"
|
||||
buttons="true"
|
||||
hide="readmore,pagebreak"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="published"
|
||||
type="list"
|
||||
label="JSTATUS"
|
||||
default="1"
|
||||
class="form-select-color-state"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">JPUBLISHED</option>
|
||||
<option value="0">JUNPUBLISHED</option>
|
||||
<option value="2">JARCHIVED</option>
|
||||
<option value="-2">JTRASHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="checked_out"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="checked_out_time"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="access"
|
||||
type="accesslevel"
|
||||
label="JFIELD_ACCESS_LABEL"
|
||||
filter="UINT"
|
||||
validate="options"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="metadesc"
|
||||
type="textarea"
|
||||
label="JFIELD_META_DESCRIPTION_LABEL"
|
||||
rows="3"
|
||||
cols="30"
|
||||
maxlength="300"
|
||||
charcounter="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="metakey"
|
||||
type="textarea"
|
||||
label="JFIELD_META_KEYWORDS_LABEL"
|
||||
rows="3"
|
||||
cols="40"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="created_user_id"
|
||||
type="user"
|
||||
label="JGLOBAL_FIELD_CREATED_BY_LABEL"
|
||||
validate="UserId"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="created_time"
|
||||
type="calendar"
|
||||
label="JGLOBAL_CREATED_DATE"
|
||||
translateformat="true"
|
||||
showtime="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="modified_user_id"
|
||||
type="user"
|
||||
label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
filter="unset"
|
||||
validate="UserId"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="modified_time"
|
||||
type="calendar"
|
||||
label="JGLOBAL_FIELD_MODIFIED_LABEL"
|
||||
class="readonly"
|
||||
translateformat="true"
|
||||
showtime="true"
|
||||
readonly="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="language"
|
||||
type="contentlanguage"
|
||||
label="JFIELD_LANGUAGE_LABEL"
|
||||
>
|
||||
<option value="*">JALL</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="tags"
|
||||
type="tag"
|
||||
label="JTAG"
|
||||
multiple="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JFIELD_RULES_LABEL"
|
||||
translate_label="false"
|
||||
filter="rules"
|
||||
validate="rules"
|
||||
component="com_content"
|
||||
section="category"
|
||||
/>
|
||||
|
||||
<fields name="params">
|
||||
|
||||
<fieldset name="options">
|
||||
|
||||
<fieldset name="basic" label="COM_CATEGORIES_FIELD_BASIC_LABEL">
|
||||
|
||||
<field
|
||||
name="category_layout"
|
||||
type="componentlayout"
|
||||
label="JFIELD_ALT_LAYOUT_LABEL"
|
||||
class="form-select"
|
||||
view="category"
|
||||
useglobal="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="image"
|
||||
type="media"
|
||||
label="COM_CATEGORIES_FIELD_IMAGE_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="image_alt"
|
||||
type="text"
|
||||
label="COM_CATEGORIES_FIELD_IMAGE_ALT_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="image_alt_empty"
|
||||
type="checkbox"
|
||||
label="COM_CATEGORIES_FIELD_IMAGE_ALT_EMPTY_LABEL"
|
||||
description="COM_CATEGORIES_FIELD_IMAGE_ALT_EMPTY_DESC"
|
||||
/>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</fields>
|
||||
|
||||
<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
|
||||
|
||||
<fieldset name="jmetadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
|
||||
|
||||
<field
|
||||
name="author"
|
||||
type="text"
|
||||
label="JAUTHOR"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="robots"
|
||||
type="list"
|
||||
label="JFIELD_METADATA_ROBOTS_LABEL"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_USE_GLOBAL</option>
|
||||
<option value="index, follow"></option>
|
||||
<option value="noindex, follow"></option>
|
||||
<option value="index, nofollow"></option>
|
||||
<option value="noindex, nofollow"></option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
|
||||
<fields name="filter">
|
||||
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_CATEGORIES_FILTER_SEARCH_LABEL"
|
||||
description="COM_CATEGORIES_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="published"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="access"
|
||||
type="accesslevel"
|
||||
label="JGRID_HEADING_ACCESS"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_ACCESS</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="language"
|
||||
type="contentlanguage"
|
||||
label="JGRID_HEADING_LANGUAGE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_LANGUAGE</option>
|
||||
<option value="*">JALL</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="tag"
|
||||
type="tag"
|
||||
label="JTAG"
|
||||
hint="JOPTION_SELECT_TAG"
|
||||
multiple="true"
|
||||
mode="nested"
|
||||
custom="false"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="level"
|
||||
type="integer"
|
||||
label="JGLOBAL_MAXLEVEL_LABEL"
|
||||
first="1"
|
||||
last="10"
|
||||
step="1"
|
||||
languages="*"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_MAX_LEVELS</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="category_id"
|
||||
type="category"
|
||||
label="JOPTION_SELECT_CATEGORY"
|
||||
multiple="true"
|
||||
extension="dynamic"
|
||||
layout="joomla.form.field.list-fancy-select"
|
||||
hint="JOPTION_SELECT_CATEGORY"
|
||||
published="0,1,2"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
default="a.lft ASC"
|
||||
statuses="*,0,1,2,-2"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
|
||||
<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
|
||||
<option value="a.published ASC">JSTATUS_ASC</option>
|
||||
<option value="a.published DESC">JSTATUS_DESC</option>
|
||||
<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
|
||||
<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
|
||||
<option value="access_level ASC">JGRID_HEADING_ACCESS_ASC</option>
|
||||
<option value="access_level DESC">JGRID_HEADING_ACCESS_DESC</option>
|
||||
<option value="association ASC" requires="associations">JASSOCIATIONS_ASC</option>
|
||||
<option value="association DESC" requires="associations">JASSOCIATIONS_DESC</option>
|
||||
<option value="language_title ASC" requires="multilanguage">JGRID_HEADING_LANGUAGE_ASC</option>
|
||||
<option value="language_title DESC" requires="multilanguage">JGRID_HEADING_LANGUAGE_DESC</option>
|
||||
<option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
*/
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Categories helper.
|
||||
*
|
||||
* @since 1.6
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Categories\Administrator\Helper\CategoriesHelper instead
|
||||
*/
|
||||
class CategoriesHelper extends \Joomla\Component\Categories\Administrator\Helper\CategoriesHelper
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @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;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $autocomplete Autocomplete attribute for the field.
|
||||
* @var boolean $autofocus Is autofocus enabled?
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $description Description of the field.
|
||||
* @var boolean $disabled Is this field disabled?
|
||||
* @var string $group Group the field belongs to. <fields> section in form XML.
|
||||
* @var boolean $hidden Is this field hidden in the form?
|
||||
* @var string $hint Placeholder for the field.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $label Label of the field.
|
||||
* @var string $labelclass Classes to apply to the label.
|
||||
* @var boolean $multiple Does this field support multiple values?
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $onchange Onchange attribute for the field.
|
||||
* @var string $onclick Onclick attribute for the field.
|
||||
* @var string $pattern Pattern (Reg Ex) of value of the form field.
|
||||
* @var boolean $readonly Is this field read only?
|
||||
* @var boolean $repeat Allows extensions to duplicate elements.
|
||||
* @var boolean $required Is this field required?
|
||||
* @var integer $size Size attribute of the input.
|
||||
* @var boolean $spellcheck Spellcheck state for the form field.
|
||||
* @var string $validate Validation rules to apply.
|
||||
* @var string $value Value attribute of the field.
|
||||
* @var array $checkedOptions Options that will be set as checked.
|
||||
* @var boolean $hasValue Has this field a value assigned?
|
||||
* @var array $options Options available for this field.
|
||||
* @var array $inputType Options available for this field.
|
||||
* @var string $accept File types that are accepted.
|
||||
* @var string $customPrefix Optional prefix for new categories.
|
||||
*/
|
||||
|
||||
$html = [];
|
||||
$classes = [];
|
||||
$attr = '';
|
||||
$attr2 = '';
|
||||
|
||||
// Initialize some field attributes.
|
||||
$attr .= !empty($size) ? ' size="' . $size . '"' : '';
|
||||
$attr .= $multiple ? ' multiple' : '';
|
||||
$attr .= $autofocus ? ' autofocus' : '';
|
||||
$attr .= $onchange ? ' onchange="' . $onchange . '"' : '';
|
||||
|
||||
// To avoid user's confusion, readonly="true" should imply disabled="disabled".
|
||||
if ($readonly || $disabled) {
|
||||
$attr .= ' disabled="disabled"';
|
||||
}
|
||||
|
||||
$attr2 .= !empty($class) ? ' class="' . $class . '"' : '';
|
||||
|
||||
$placeholder = $this->escape(Text::_('JGLOBAL_TYPE_OR_SELECT_CATEGORY'));
|
||||
|
||||
$attr2 .= ' placeholder="' . $placeholder . '" ';
|
||||
$attr2 .= ' search-placeholder="' . $placeholder . '" ';
|
||||
|
||||
if ($allowCustom) {
|
||||
$attr2 .= ' allow-custom';
|
||||
|
||||
if ($customPrefix !== '') {
|
||||
$attr2 .= ' new-item-prefix="' . $customPrefix . '" ';
|
||||
}
|
||||
}
|
||||
|
||||
if ($required) {
|
||||
$attr .= ' required class="required"';
|
||||
$attr2 .= ' required';
|
||||
}
|
||||
|
||||
// Create a read-only list (no name) with hidden input(s) to store the value(s).
|
||||
if ($readonly) {
|
||||
$html[] = HTMLHelper::_('select.genericlist', $options, '', trim($attr), 'value', 'text', $value, $id);
|
||||
|
||||
// E.g. form field type tag sends $this->value as array
|
||||
if ($multiple && is_array($value)) {
|
||||
if (!count($value)) {
|
||||
$value[] = '';
|
||||
}
|
||||
|
||||
foreach ($value as $val) {
|
||||
$html[] = '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($val, ENT_COMPAT, 'UTF-8') . '">';
|
||||
}
|
||||
} else {
|
||||
$html[] = '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '">';
|
||||
}
|
||||
} else {
|
||||
// Create a regular list.
|
||||
if (count($options) === 0) {
|
||||
// All Categories have been deleted, so we need a new category (This will create on save if selected).
|
||||
$options[0] = new \stdClass();
|
||||
$options[0]->value = 'Uncategorised';
|
||||
$options[0]->text = 'Uncategorised';
|
||||
$options[0]->level = '1';
|
||||
$options[0]->published = '1';
|
||||
$options[0]->lft = '1';
|
||||
}
|
||||
|
||||
$html[] = HTMLHelper::_('select.genericlist', $options, $name, trim($attr), 'value', 'text', $value, $id);
|
||||
}
|
||||
|
||||
if ($refreshPage === true) {
|
||||
$attr2 .= ' data-refresh-catid="' . $refreshCatId . '" data-refresh-section="' . $refreshSection . '"';
|
||||
$attr2 .= ' onchange="Joomla.categoryHasChanged(this)"';
|
||||
|
||||
Factory::getDocument()->getWebAssetManager()
|
||||
->registerAndUseScript('field.category-change', 'layouts/joomla/form/field/category-change.min.js', [], ['defer' => true], ['core'])
|
||||
->useScript('webcomponent.core-loader');
|
||||
|
||||
// Pass the element id to the javascript
|
||||
Factory::getDocument()->addScriptOptions('category-change', $id);
|
||||
} else {
|
||||
$attr2 .= $onchange ? ' onchange="' . $onchange . '"' : '';
|
||||
}
|
||||
|
||||
Text::script('JGLOBAL_SELECT_NO_RESULTS_MATCH');
|
||||
Text::script('JGLOBAL_SELECT_PRESS_TO_SELECT');
|
||||
|
||||
Factory::getDocument()->getWebAssetManager()
|
||||
->usePreset('choicesjs')
|
||||
->useScript('webcomponent.field-fancy-select');
|
||||
?>
|
||||
|
||||
<joomla-field-fancy-select <?php echo $attr2; ?>><?php echo implode($html); ?></joomla-field-fancy-select>
|
||||
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @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\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
|
||||
use Joomla\CMS\HTML\Registry;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Component\Categories\Administrator\Extension\CategoriesComponent;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* The categories service provider.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Categories'));
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Categories'));
|
||||
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
function (Container $container) {
|
||||
$component = new CategoriesComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
||||
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
$component->setRegistry($container->get(Registry::class));
|
||||
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Associations;
|
||||
use Joomla\CMS\Language\LanguageHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Table\Table;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The categories controller for ajax requests
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class AjaxController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to fetch associations of a category
|
||||
*
|
||||
* The method assumes that the following http parameters are passed in an Ajax Get request:
|
||||
* token: the form token
|
||||
* assocId: the id of the category whose associations are to be returned
|
||||
* excludeLang: the association for this language is to be excluded
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function fetchAssociations()
|
||||
{
|
||||
if (!Session::checkToken('get')) {
|
||||
echo new JsonResponse(null, Text::_('JINVALID_TOKEN'), true);
|
||||
} else {
|
||||
$extension = $this->input->get('extension');
|
||||
|
||||
$assocId = $this->input->getInt('assocId', 0);
|
||||
|
||||
if ($assocId == 0) {
|
||||
echo new JsonResponse(null, Text::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$excludeLang = $this->input->get('excludeLang', '', 'STRING');
|
||||
|
||||
$associations = Associations::getAssociations($extension, '#__categories', 'com_categories.item', (int) $assocId, 'id', 'alias', '');
|
||||
|
||||
unset($associations[$excludeLang]);
|
||||
|
||||
// Add the title to each of the associated records
|
||||
Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/tables');
|
||||
$categoryTable = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\');
|
||||
|
||||
foreach ($associations as $lang => $association) {
|
||||
$categoryTable->load($association->id);
|
||||
$associations[$lang]->title = $categoryTable->title;
|
||||
}
|
||||
|
||||
$countContentLanguages = \count(LanguageHelper::getContentLanguages([0, 1], false));
|
||||
|
||||
if (\count($associations) == 0) {
|
||||
$message = Text::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
|
||||
} elseif ($countContentLanguages > \count($associations) + 2) {
|
||||
$tags = implode(', ', array_keys($associations));
|
||||
$message = Text::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
|
||||
} else {
|
||||
$message = Text::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
|
||||
}
|
||||
|
||||
echo new JsonResponse($associations, $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @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\Categories\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The Categories List Controller
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoriesController extends AdminController
|
||||
{
|
||||
/**
|
||||
* 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 The model.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getModel($name = 'Category', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the JSON-encoded amount of published content categories
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getQuickiconContent()
|
||||
{
|
||||
$model = $this->getModel('Categories');
|
||||
$model->setState('filter.published', 1);
|
||||
$model->setState('filter.extension', 'com_content');
|
||||
|
||||
$amount = (int) $model->getTotal();
|
||||
|
||||
$result = [];
|
||||
|
||||
$result['amount'] = $amount;
|
||||
$result['sronly'] = Text::plural('COM_CATEGORIES_N_QUICKICON_SRONLY', $amount);
|
||||
$result['name'] = Text::plural('COM_CATEGORIES_N_QUICKICON', $amount);
|
||||
|
||||
echo new JsonResponse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the nested set tree.
|
||||
*
|
||||
* @return boolean False on failure or error, true on success.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function rebuild()
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
$extension = $this->input->get('extension');
|
||||
$this->setRedirect(Route::_('index.php?option=com_categories&view=categories&extension=' . $extension, false));
|
||||
|
||||
/** @var \Joomla\Component\Categories\Administrator\Model\CategoryModel $model */
|
||||
$model = $this->getModel();
|
||||
|
||||
if ($model->rebuild()) {
|
||||
// Rebuild succeeded.
|
||||
$this->setMessage(Text::_('COM_CATEGORIES_REBUILD_SUCCESS'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rebuild failed.
|
||||
$this->setMessage(Text::_('COM_CATEGORIES_REBUILD_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$extension = $this->input->getCmd('extension', null);
|
||||
|
||||
return '&extension=' . $extension;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\CMS\Versioning\VersionableControllerTrait;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The Category Controller
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoryController extends FormController
|
||||
{
|
||||
use VersionableControllerTrait;
|
||||
|
||||
/**
|
||||
* The extension for which the categories apply.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface|null $factory The factory.
|
||||
* @param CMSApplication|null $app The Application for the dispatcher
|
||||
* @param Input|null $input Input
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, CMSApplication $app = null, Input $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
if (empty($this->extension)) {
|
||||
$this->extension = $this->input->get('extension', 'com_content');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can add a new record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function allowAdd($data = [])
|
||||
{
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
return ($user->authorise('core.create', $this->extension) || \count($user->getAuthorisedCategories($this->extension, 'core.create')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can edit a record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
* @param string $key The name of the key for the primary key.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function allowEdit($data = [], $key = 'parent_id')
|
||||
{
|
||||
$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
// Check "edit" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit', $this->extension . '.category.' . $recordId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check "edit own" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit.own', $this->extension . '.category.' . $recordId)) {
|
||||
// Need to do a lookup from the model to get the owner
|
||||
$record = $this->getModel()->getItem($recordId);
|
||||
|
||||
if (empty($record)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ownerId = $record->created_user_id;
|
||||
|
||||
// If the owner matches 'me' then do the test.
|
||||
if ($ownerId == $user->id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override parent save method to store form data with right key as expected by edit category page
|
||||
*
|
||||
* @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 boolean True if successful, false otherwise.
|
||||
*
|
||||
* @since 3.10.3
|
||||
*/
|
||||
public function save($key = null, $urlVar = null)
|
||||
{
|
||||
$result = parent::save($key, $urlVar);
|
||||
|
||||
$oldKey = $this->option . '.edit.category.data';
|
||||
$newKey = $this->option . '.edit.category.' . substr($this->extension, 4) . '.data';
|
||||
$this->app->setUserState($newKey, $this->app->getUserState($oldKey));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override cancel method to clear form data for a failed edit action
|
||||
*
|
||||
* @param string $key The name of the primary key of the URL variable.
|
||||
*
|
||||
* @return boolean True if access level checks pass, false otherwise.
|
||||
*
|
||||
* @since 3.10.3
|
||||
*/
|
||||
public function cancel($key = null)
|
||||
{
|
||||
$result = parent::cancel($key);
|
||||
|
||||
$newKey = $this->option . '.edit.category.' . substr($this->extension, 4) . '.data';
|
||||
$this->app->setUserState($newKey, null);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to run batch operations.
|
||||
*
|
||||
* @param object|null $model The model.
|
||||
*
|
||||
* @return boolean True if successful, false otherwise and internal error is set.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function batch($model = null)
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
/** @var \Joomla\Component\Categories\Administrator\Model\CategoryModel $model */
|
||||
$model = $this->getModel('Category');
|
||||
|
||||
// Preset the redirect
|
||||
$this->setRedirect('index.php?option=com_categories&view=categories&extension=' . $this->extension);
|
||||
|
||||
return parent::batch($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to an item redirect.
|
||||
*
|
||||
* @param integer|null $recordId The primary key id for the item.
|
||||
* @param string $urlVar The name of the URL variable for the id.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
|
||||
{
|
||||
$append = parent::getRedirectToItemAppend($recordId);
|
||||
|
||||
// In case extension is not passed in the URL, get it directly from category instead of default to com_content
|
||||
if (!$this->input->exists('extension') && $recordId > 0) {
|
||||
$table = $this->getModel('Category')->getTable();
|
||||
|
||||
if ($table->load($recordId)) {
|
||||
$this->extension = $table->extension;
|
||||
}
|
||||
}
|
||||
|
||||
$append .= '&extension=' . $this->extension;
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$append = parent::getRedirectToListAppend();
|
||||
$append .= '&extension=' . $this->extension;
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that allows child controller access to model data after the data has been saved.
|
||||
*
|
||||
* @param \Joomla\CMS\MVC\Model\BaseDatabaseModel $model The data model object.
|
||||
* @param array $validData The validated data.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function postSaveHook(BaseDatabaseModel $model, $validData = [])
|
||||
{
|
||||
$item = $model->getItem();
|
||||
|
||||
if (isset($item->params) && \is_array($item->params)) {
|
||||
$registry = new Registry($item->params);
|
||||
$item->params = (string) $registry;
|
||||
}
|
||||
|
||||
if (isset($item->metadata) && \is_array($item->metadata)) {
|
||||
$registry = new Registry($item->metadata);
|
||||
$item->metadata = (string) $registry;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Input\Input;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Categories view class for the Category package.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The default view.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $default_view = 'categories';
|
||||
|
||||
/**
|
||||
* The extension for which the categories apply.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface|null $factory The factory.
|
||||
* @param CMSApplication|null $app The Application for the dispatcher
|
||||
* @param Input|null $input Input
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// Guess the Text message prefix. Defaults to the option.
|
||||
if (empty($this->extension)) {
|
||||
$this->extension = $this->input->get('extension', 'com_content');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param boolean $cachable If true, the view output will be cached
|
||||
* @param array $urlparams An array of safe URL parameters and their variable types.
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return static|boolean This object to support chaining.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = [])
|
||||
{
|
||||
// Get the document object.
|
||||
$document = $this->app->getDocument();
|
||||
|
||||
// Set the default view name and format from the Request.
|
||||
$vName = $this->input->get('view', 'categories');
|
||||
$vFormat = $document->getType();
|
||||
$lName = $this->input->get('layout', 'default', 'string');
|
||||
$id = $this->input->getInt('id');
|
||||
|
||||
// Check for edit form.
|
||||
if ($vName == 'category' && $lName == 'edit' && !$this->checkEditId('com_categories.edit.category', $id)) {
|
||||
// Somehow the person just went to the form - we don't allow that.
|
||||
if (!\count($this->app->getMessageQueue())) {
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_categories&view=categories&extension=' . $this->extension, false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get and render the view.
|
||||
if ($view = $this->getView($vName, $vFormat)) {
|
||||
// Get the model for the view.
|
||||
$model = $this->getModel($vName, 'Administrator', ['name' => $vName . '.' . substr($this->extension, 4)]);
|
||||
|
||||
// Push the model into the view (as default).
|
||||
$view->setModel($model, true);
|
||||
$view->setLayout($lName);
|
||||
|
||||
// Push document object into the view.
|
||||
$view->document = $document;
|
||||
$view->display();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Dispatcher;
|
||||
|
||||
use Joomla\CMS\Access\Exception\NotAllowed;
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcher;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* ComponentDispatcher class for com_categories
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Dispatcher extends ComponentDispatcher
|
||||
{
|
||||
/**
|
||||
* Categories have to check for extension permission
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function checkAccess()
|
||||
{
|
||||
$extension = $this->getApplication()->getInput()->getCmd('extension', '');
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
// Check the user has permission to access this component if in the backend
|
||||
if ($this->app->isClient('administrator') && !$this->app->getIdentity()->authorise('core.manage', $parts[0])) {
|
||||
throw new NotAllowed($this->app->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Extension;
|
||||
|
||||
use Joomla\CMS\Extension\BootableExtensionInterface;
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
use Joomla\CMS\HTML\HTMLRegistryAwareTrait;
|
||||
use Joomla\Component\Categories\Administrator\Service\HTML\AdministratorService;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Component class for com_categories
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class CategoriesComponent extends MVCComponent implements BootableExtensionInterface
|
||||
{
|
||||
use HTMLRegistryAwareTrait;
|
||||
|
||||
/**
|
||||
* Booting the extension. This is the function to set up the environment of the extension like
|
||||
* registering new class loaders, etc.
|
||||
*
|
||||
* If required, some initial set up can be done from services of the container, eg.
|
||||
* registering HTML services.
|
||||
*
|
||||
* @param ContainerInterface $container The container
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function boot(ContainerInterface $container)
|
||||
{
|
||||
$this->getRegistry()->register('categoriesadministrator', new AdministratorService());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,371 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Category Edit field..
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoryeditField extends ListField
|
||||
{
|
||||
/**
|
||||
* To allow creation of new categories.
|
||||
*
|
||||
* @var integer
|
||||
* @since 3.6
|
||||
*/
|
||||
protected $allowAdd;
|
||||
|
||||
/**
|
||||
* Optional prefix for new categories.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.9.11
|
||||
*/
|
||||
protected $customPrefix;
|
||||
|
||||
/**
|
||||
* A flexible category list that respects access controls
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
public $type = 'CategoryEdit';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $layout = 'joomla.form.field.categoryedit';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string|null $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see FormField::setup()
|
||||
* @since 3.2
|
||||
*/
|
||||
public function setup(\SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
if ($return) {
|
||||
$this->allowAdd = isset($this->element['allowAdd']) ? (bool) $this->element['allowAdd'] : false;
|
||||
$this->customPrefix = (string) $this->element['customPrefix'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get certain otherwise inaccessible properties from the form field object.
|
||||
*
|
||||
* @param string $name The property name for which to get the value.
|
||||
*
|
||||
* @return mixed The property value or null.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'allowAdd':
|
||||
return (bool) $this->$name;
|
||||
case 'customPrefix':
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
return parent::__get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set certain otherwise inaccessible properties of the form field object.
|
||||
*
|
||||
* @param string $name The property name for which to set the value.
|
||||
* @param mixed $value The value of the property.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$value = (string) $value;
|
||||
|
||||
switch ($name) {
|
||||
case 'allowAdd':
|
||||
$value = (string) $value;
|
||||
$this->$name = ($value === 'true' || $value === $name || $value === '1');
|
||||
break;
|
||||
case 'customPrefix':
|
||||
$this->$name = (string) $value;
|
||||
break;
|
||||
default:
|
||||
parent::__set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a list of categories that respects access controls and can be used for
|
||||
* either category assignment or parent category assignment in edit screens.
|
||||
* Use the parent element to indicate that the field will be used for assigning parent categories.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = [];
|
||||
$published = $this->element['published'] ? explode(',', (string) $this->element['published']) : [0, 1];
|
||||
$name = (string) $this->element['name'];
|
||||
|
||||
// Let's get the id for the current item, either category or content item.
|
||||
$jinput = Factory::getApplication()->getInput();
|
||||
|
||||
// Load the category options for a given extension.
|
||||
|
||||
// For categories the old category is the category id or 0 for new category.
|
||||
if ($this->element['parent'] || $jinput->get('option') == 'com_categories') {
|
||||
$oldCat = $jinput->get('id', 0);
|
||||
$oldParent = $this->form->getValue($name, 0);
|
||||
$extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('extension', 'com_content');
|
||||
} else { // For items the old category is the category they are in when opened or 0 if new.
|
||||
$oldCat = $this->form->getValue($name, 0);
|
||||
$extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('option', 'com_content');
|
||||
}
|
||||
|
||||
// Account for case that a submitted form has a multi-value category id field (e.g. a filtering form), just use the first category
|
||||
$oldCat = \is_array($oldCat)
|
||||
? (int) reset($oldCat)
|
||||
: (int) $oldCat;
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
[
|
||||
$db->quoteName('a.id', 'value'),
|
||||
$db->quoteName('a.title', 'text'),
|
||||
$db->quoteName('a.level'),
|
||||
$db->quoteName('a.published'),
|
||||
$db->quoteName('a.lft'),
|
||||
$db->quoteName('a.language'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__categories', 'a'));
|
||||
|
||||
// Filter by the extension type
|
||||
if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories') {
|
||||
$query->where('(' . $db->quoteName('a.extension') . ' = :extension OR ' . $db->quoteName('a.parent_id') . ' = 0)')
|
||||
->bind(':extension', $extension);
|
||||
} else {
|
||||
$query->where($db->quoteName('a.extension') . ' = :extension')
|
||||
->bind(':extension', $extension);
|
||||
}
|
||||
|
||||
// Filter language
|
||||
if (!empty($this->element['language'])) {
|
||||
if (strpos($this->element['language'], ',') !== false) {
|
||||
$language = explode(',', $this->element['language']);
|
||||
} else {
|
||||
$language = $this->element['language'];
|
||||
}
|
||||
|
||||
$query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
|
||||
}
|
||||
|
||||
// Filter on the published state
|
||||
$state = ArrayHelper::toInteger($published);
|
||||
$query->whereIn($db->quoteName('a.published'), $state);
|
||||
|
||||
// Filter categories on User Access Level
|
||||
// Filter by access level on categories.
|
||||
if (!$user->authorise('core.admin')) {
|
||||
$groups = $user->getAuthorisedViewLevels();
|
||||
$query->whereIn($db->quoteName('a.access'), $groups);
|
||||
}
|
||||
|
||||
$query->order($db->quoteName('a.lft') . ' ASC');
|
||||
|
||||
// If parent isn't explicitly stated but we are in com_categories assume we want parents
|
||||
if ($oldCat != 0 && ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')) {
|
||||
// Prevent parenting to children of this item.
|
||||
// To rearrange parents and children move the children up, not the parents down.
|
||||
$query->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__categories', 'p'),
|
||||
$db->quoteName('p.id') . ' = :oldcat'
|
||||
)
|
||||
->bind(':oldcat', $oldCat, ParameterType::INTEGER)
|
||||
->where('NOT(' . $db->quoteName('a.lft') . ' >= ' . $db->quoteName('p.lft')
|
||||
. ' AND ' . $db->quoteName('a.rgt') . ' <= ' . $db->quoteName('p.rgt') . ')');
|
||||
}
|
||||
|
||||
// Get the options.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$options = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
// Pad the option text with spaces using depth level as a multiplier.
|
||||
for ($i = 0, $n = \count($options); $i < $n; $i++) {
|
||||
// Translate ROOT
|
||||
if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories') {
|
||||
if ($options[$i]->level == 0) {
|
||||
$options[$i]->text = Text::_('JGLOBAL_ROOT_PARENT');
|
||||
}
|
||||
}
|
||||
|
||||
if ($options[$i]->published == 1) {
|
||||
$options[$i]->text = str_repeat('- ', !$options[$i]->level ? 0 : $options[$i]->level - 1) . $options[$i]->text;
|
||||
} else {
|
||||
$options[$i]->text = str_repeat('- ', !$options[$i]->level ? 0 : $options[$i]->level - 1) . '[' . $options[$i]->text . ']';
|
||||
}
|
||||
|
||||
// Displays language code if not set to All
|
||||
if ($options[$i]->language !== '*') {
|
||||
$options[$i]->text .= ' (' . $options[$i]->language . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// For new items we want a list of categories you are allowed to create in.
|
||||
if ($oldCat == 0) {
|
||||
foreach ($options as $i => $option) {
|
||||
/*
|
||||
* To take save or create in a category you need to have create rights for that category unless the item is already in that category.
|
||||
* Unset the option if the user isn't authorised for it. In this field assets are always categories.
|
||||
*/
|
||||
if ($option->level != 0 && !$user->authorise('core.create', $extension . '.category.' . $option->value)) {
|
||||
unset($options[$i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If you have an existing category id things are more complex.
|
||||
/*
|
||||
* If you are only allowed to edit in this category but not edit.state, you should not get any
|
||||
* option to change the category parent for a category or the category for a content item,
|
||||
* but you should be able to save in that category.
|
||||
*/
|
||||
foreach ($options as $i => $option) {
|
||||
$assetKey = $extension . '.category.' . $oldCat;
|
||||
|
||||
if ($option->level != 0 && !isset($oldParent) && $option->value != $oldCat && !$user->authorise('core.edit.state', $assetKey)) {
|
||||
unset($options[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($option->level != 0 && isset($oldParent) && $option->value != $oldParent && !$user->authorise('core.edit.state', $assetKey)) {
|
||||
unset($options[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* However, if you can edit.state you can also move this to another category for which you have
|
||||
* create permission and you should also still be able to save in the current category.
|
||||
*/
|
||||
$assetKey = $extension . '.category.' . $option->value;
|
||||
|
||||
if ($option->level != 0 && !isset($oldParent) && $option->value != $oldCat && !$user->authorise('core.create', $assetKey)) {
|
||||
unset($options[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($option->level != 0 && isset($oldParent) && $option->value != $oldParent && !$user->authorise('core.create', $assetKey)) {
|
||||
unset($options[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$oldCat != 0 && ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
|
||||
&& !isset($options[0])
|
||||
&& isset($this->element['show_root'])
|
||||
) {
|
||||
$rowQuery = $db->getQuery(true)
|
||||
->select(
|
||||
[
|
||||
$db->quoteName('a.id', 'value'),
|
||||
$db->quoteName('a.title', 'text'),
|
||||
$db->quoteName('a.level'),
|
||||
$db->quoteName('a.parent_id'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__categories', 'a'))
|
||||
->where($db->quoteName('a.id') . ' = :aid')
|
||||
->bind(':aid', $oldCat, ParameterType::INTEGER);
|
||||
$db->setQuery($rowQuery);
|
||||
$row = $db->loadObject();
|
||||
|
||||
if ($row->parent_id == '1') {
|
||||
$parent = new \stdClass();
|
||||
$parent->text = Text::_('JGLOBAL_ROOT_PARENT');
|
||||
array_unshift($options, $parent);
|
||||
}
|
||||
|
||||
array_unshift($options, HTMLHelper::_('select.option', '0', Text::_('JGLOBAL_ROOT')));
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for a generic list.
|
||||
* Use the multiple attribute to enable multiselect.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$data = $this->getLayoutData();
|
||||
|
||||
$data['options'] = $this->getOptions();
|
||||
$data['allowCustom'] = $this->allowAdd;
|
||||
$data['customPrefix'] = $this->customPrefix;
|
||||
$data['refreshPage'] = (bool) $this->element['refresh-enabled'];
|
||||
$data['refreshCatId'] = (string) $this->element['refresh-cat-id'];
|
||||
$data['refreshSection'] = (string) $this->element['refresh-section'];
|
||||
|
||||
$renderer = $this->getRenderer($this->layout);
|
||||
$renderer->setComponent('com_categories');
|
||||
$renderer->setClient(1);
|
||||
|
||||
return $renderer->render($data);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @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\Categories\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Components Category field.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ComponentsCategoryField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $type = 'ComponentsCategory';
|
||||
|
||||
/**
|
||||
* Method to get a list of options for a list input.
|
||||
*
|
||||
* @return array An array of JHtml options.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
// Initialise variable.
|
||||
$db = $this->getDatabase();
|
||||
$options = [];
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
$query->select('DISTINCT ' . $db->quoteName('extension'))
|
||||
->from($db->quoteName('#__categories'))
|
||||
->where($db->quoteName('extension') . ' != ' . $db->quote('system'));
|
||||
|
||||
$db->setQuery($query);
|
||||
$categoryTypes = $db->loadColumn();
|
||||
|
||||
foreach ($categoryTypes as $categoryType) {
|
||||
$option = new \stdClass();
|
||||
$option->value = $categoryType;
|
||||
|
||||
// Extract the component name and optional section name
|
||||
$parts = explode('.', $categoryType);
|
||||
$component = $parts[0];
|
||||
$section = (\count($parts) > 1) ? $parts[1] : null;
|
||||
|
||||
// Load component language files
|
||||
$lang = Factory::getLanguage();
|
||||
$lang->load($component, JPATH_BASE)
|
||||
|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component);
|
||||
|
||||
// If the component section string exists, let's use it
|
||||
if ($lang->hasKey($component_section_key = strtoupper($component . ($section ? "_$section" : '')))) {
|
||||
$option->text = Text::_($component_section_key);
|
||||
} else { // Else use the component title
|
||||
$option->text = Text::_(strtoupper($component));
|
||||
}
|
||||
|
||||
$options[] = $option;
|
||||
}
|
||||
|
||||
// Sort by name
|
||||
$options = ArrayHelper::sortObjects($options, 'text', 1, true, true);
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
$options = array_merge(parent::getOptions(), $options);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,307 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Field\Modal;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\FormField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\LanguageHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Supports a modal category picker.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
class CategoryField extends FormField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $type = 'Modal_Category';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
if ($this->element['extension']) {
|
||||
$extension = (string) $this->element['extension'];
|
||||
} else {
|
||||
$extension = (string) Factory::getApplication()->getInput()->get('extension', 'com_content');
|
||||
}
|
||||
|
||||
$allowNew = ((string) $this->element['new'] == 'true');
|
||||
$allowEdit = ((string) $this->element['edit'] == 'true');
|
||||
$allowClear = ((string) $this->element['clear'] != 'false');
|
||||
$allowSelect = ((string) $this->element['select'] != 'false');
|
||||
$allowPropagate = ((string) $this->element['propagate'] == 'true');
|
||||
|
||||
$languages = LanguageHelper::getContentLanguages([0, 1], false);
|
||||
|
||||
// Load language.
|
||||
Factory::getLanguage()->load('com_categories', JPATH_ADMINISTRATOR);
|
||||
|
||||
// The active category id field.
|
||||
$value = (int) $this->value ?: '';
|
||||
|
||||
// Create the modal id.
|
||||
$modalId = 'Category_' . $this->id;
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
|
||||
|
||||
// Add the modal field script to the document head.
|
||||
$wa->useScript('field.modal-fields');
|
||||
|
||||
// Script to proxy the select modal function to the modal-fields.js file.
|
||||
if ($allowSelect) {
|
||||
static $scriptSelect = null;
|
||||
|
||||
if (\is_null($scriptSelect)) {
|
||||
$scriptSelect = [];
|
||||
}
|
||||
|
||||
if (!isset($scriptSelect[$this->id])) {
|
||||
$wa->addInlineScript(
|
||||
"
|
||||
window.jSelectCategory_" . $this->id . " = function (id, title, object) {
|
||||
window.processModalSelect('Category', '" . $this->id . "', id, title, '', object);
|
||||
}",
|
||||
[],
|
||||
['type' => 'module']
|
||||
);
|
||||
|
||||
Text::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');
|
||||
|
||||
$scriptSelect[$this->id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup variables for display.
|
||||
$linkCategories = 'index.php?option=com_categories&view=categories&layout=modal&tmpl=component&' . Session::getFormToken() . '=1'
|
||||
. '&extension=' . $extension;
|
||||
$linkCategory = 'index.php?option=com_categories&view=category&layout=modal&tmpl=component&' . Session::getFormToken() . '=1'
|
||||
. '&extension=' . $extension;
|
||||
$modalTitle = Text::_('COM_CATEGORIES_SELECT_A_CATEGORY');
|
||||
|
||||
if (isset($this->element['language'])) {
|
||||
$linkCategories .= '&forcedLanguage=' . $this->element['language'];
|
||||
$linkCategory .= '&forcedLanguage=' . $this->element['language'];
|
||||
$modalTitle .= ' — ' . $this->element['label'];
|
||||
}
|
||||
|
||||
$urlSelect = $linkCategories . '&function=jSelectCategory_' . $this->id;
|
||||
$urlEdit = $linkCategory . '&task=category.edit&id=\' + document.getElementById("' . $this->id . '_id").value + \'';
|
||||
$urlNew = $linkCategory . '&task=category.add';
|
||||
|
||||
if ($value) {
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('title'))
|
||||
->from($db->quoteName('#__categories'))
|
||||
->where($db->quoteName('id') . ' = :value')
|
||||
->bind(':value', $value, ParameterType::INTEGER);
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$title = $db->loadResult();
|
||||
} catch (\RuntimeException $e) {
|
||||
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$title = empty($title) ? Text::_('COM_CATEGORIES_SELECT_A_CATEGORY') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
// The current category display field.
|
||||
$html = '';
|
||||
|
||||
if ($allowSelect || $allowNew || $allowEdit || $allowClear) {
|
||||
$html .= '<span class="input-group">';
|
||||
}
|
||||
|
||||
$html .= '<input class="form-control" id="' . $this->id . '_name" type="text" value="' . $title . '" readonly size="35">';
|
||||
|
||||
// Select category button.
|
||||
if ($allowSelect) {
|
||||
$html .= '<button'
|
||||
. ' class="btn btn-primary' . ($value ? ' hidden' : '') . '"'
|
||||
. ' id="' . $this->id . '_select"'
|
||||
. ' data-bs-toggle="modal"'
|
||||
. ' type="button"'
|
||||
. ' data-bs-target="#ModalSelect' . $modalId . '">'
|
||||
. '<span class="icon-file" aria-hidden="true"></span> ' . Text::_('JSELECT')
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
// New category button.
|
||||
if ($allowNew) {
|
||||
$html .= '<button'
|
||||
. ' class="btn btn-secondary' . ($value ? ' hidden' : '') . '"'
|
||||
. ' id="' . $this->id . '_new"'
|
||||
. ' data-bs-toggle="modal"'
|
||||
. ' type="button"'
|
||||
. ' data-bs-target="#ModalNew' . $modalId . '">'
|
||||
. '<span class="icon-plus" aria-hidden="true"></span> ' . Text::_('JACTION_CREATE')
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
// Edit category button.
|
||||
if ($allowEdit) {
|
||||
$html .= '<button'
|
||||
. ' class="btn btn-primary' . ($value ? '' : ' hidden') . '"'
|
||||
. ' id="' . $this->id . '_edit"'
|
||||
. ' data-bs-toggle="modal"'
|
||||
. ' type="button"'
|
||||
. ' data-bs-target="#ModalEdit' . $modalId . '">'
|
||||
. '<span class="icon-pen-square" aria-hidden="true"></span> ' . Text::_('JACTION_EDIT')
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
// Clear category button.
|
||||
if ($allowClear) {
|
||||
$html .= '<button'
|
||||
. ' class="btn btn-secondary' . ($value ? '' : ' hidden') . '"'
|
||||
. ' id="' . $this->id . '_clear"'
|
||||
. ' type="button"'
|
||||
. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
|
||||
. '<span class="icon-times" aria-hidden="true"></span> ' . Text::_('JCLEAR')
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
// Propagate category button
|
||||
if ($allowPropagate && \count($languages) > 2) {
|
||||
// Strip off language tag at the end
|
||||
$tagLength = (int) \strlen($this->element['language']);
|
||||
$callbackFunctionStem = substr("jSelectCategory_" . $this->id, 0, -$tagLength);
|
||||
|
||||
$html .= '<button'
|
||||
. ' class="btn btn-primary' . ($value ? '' : ' hidden') . '"'
|
||||
. ' type="button"'
|
||||
. ' id="' . $this->id . '_propagate"'
|
||||
. ' title="' . Text::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
|
||||
. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
|
||||
. '<span class="icon-sync" aria-hidden="true"></span> ' . Text::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
if ($allowSelect || $allowNew || $allowEdit || $allowClear) {
|
||||
$html .= '</span>';
|
||||
}
|
||||
|
||||
// Select category modal.
|
||||
if ($allowSelect) {
|
||||
$html .= HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'ModalSelect' . $modalId,
|
||||
[
|
||||
'title' => $modalTitle,
|
||||
'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>',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// New category modal.
|
||||
if ($allowNew) {
|
||||
$html .= HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'ModalNew' . $modalId,
|
||||
[
|
||||
'title' => Text::_('COM_CATEGORIES_NEW_CATEGORY'),
|
||||
'backdrop' => 'static',
|
||||
'keyboard' => false,
|
||||
'closeButton' => false,
|
||||
'url' => $urlNew,
|
||||
'height' => '400px',
|
||||
'width' => '800px',
|
||||
'bodyHeight' => 70,
|
||||
'modalWidth' => 80,
|
||||
'footer' => '<button type="button" class="btn btn-secondary"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'cancel\', \'item-form\'); return false;">'
|
||||
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
|
||||
. '<button type="button" class="btn btn-primary"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'save\', \'item-form\'); return false;">'
|
||||
. Text::_('JSAVE') . '</button>'
|
||||
. '<button type="button" class="btn btn-success"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'apply\', \'item-form\'); return false;">'
|
||||
. Text::_('JAPPLY') . '</button>',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Edit category modal.
|
||||
if ($allowEdit) {
|
||||
$html .= HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'ModalEdit' . $modalId,
|
||||
[
|
||||
'title' => Text::_('COM_CATEGORIES_EDIT_CATEGORY'),
|
||||
'backdrop' => 'static',
|
||||
'keyboard' => false,
|
||||
'closeButton' => false,
|
||||
'url' => $urlEdit,
|
||||
'height' => '400px',
|
||||
'width' => '800px',
|
||||
'bodyHeight' => 70,
|
||||
'modalWidth' => 80,
|
||||
'footer' => '<button type="button" class="btn btn-secondary"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'cancel\', \'item-form\'); return false;">'
|
||||
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
|
||||
. '<button type="button" class="btn btn-primary"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'save\', \'item-form\'); return false;">'
|
||||
. Text::_('JSAVE') . '</button>'
|
||||
. '<button type="button" class="btn btn-success"'
|
||||
. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'apply\', \'item-form\'); return false;">'
|
||||
. Text::_('JAPPLY') . '</button>',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Note: class='required' for client side validation
|
||||
$class = $this->required ? ' class="required modal-value"' : '';
|
||||
|
||||
$html .= '<input type="hidden" id="' . $this->id . '_id"' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
|
||||
. '" data-text="' . htmlspecialchars(Text::_('COM_CATEGORIES_SELECT_A_CATEGORY', true), ENT_COMPAT, 'UTF-8') . '" value="' . $value . '">';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field label markup.
|
||||
*
|
||||
* @return string The field label markup.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function getLabel()
|
||||
{
|
||||
return str_replace($this->id, $this->id . '_name', parent::getLabel());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @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\Categories\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Associations;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Categories helper.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoriesHelper
|
||||
{
|
||||
/**
|
||||
* Gets a list of associations for a given item.
|
||||
*
|
||||
* @param integer $pk Content item key.
|
||||
* @param string $extension Optional extension name.
|
||||
*
|
||||
* @return array of associations.
|
||||
*/
|
||||
public static function getAssociations($pk, $extension = 'com_content')
|
||||
{
|
||||
$langAssociations = Associations::getAssociations($extension, '#__categories', 'com_categories.item', $pk, 'id', 'alias', '');
|
||||
$associations = [];
|
||||
$user = Factory::getUser();
|
||||
$groups = $user->getAuthorisedViewLevels();
|
||||
|
||||
foreach ($langAssociations as $langAssociation) {
|
||||
// Include only published categories with user access
|
||||
$arrId = explode(':', $langAssociation->id);
|
||||
$assocId = (int) $arrId[0];
|
||||
$db = Factory::getDbo();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('published'))
|
||||
->from($db->quoteName('#__categories'))
|
||||
->whereIn($db->quoteName('access'), $groups)
|
||||
->where($db->quoteName('id') . ' = :associd')
|
||||
->bind(':associd', $assocId, ParameterType::INTEGER);
|
||||
|
||||
$result = (int) $db->setQuery($query)->loadResult();
|
||||
|
||||
if ($result === 1) {
|
||||
$associations[$langAssociation->language] = $langAssociation->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $associations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Category ID exists otherwise assign to ROOT category.
|
||||
*
|
||||
* @param mixed $catid Name or ID of category.
|
||||
* @param string $extension Extension that triggers this function
|
||||
*
|
||||
* @return integer $catid Category ID.
|
||||
*/
|
||||
public static function validateCategoryId($catid, $extension)
|
||||
{
|
||||
$categoryTable = Table::getInstance('CategoryTable', '\\Joomla\\Component\\Categories\\Administrator\\Table\\');
|
||||
|
||||
$data = [];
|
||||
$data['id'] = $catid;
|
||||
$data['extension'] = $extension;
|
||||
|
||||
if (!$categoryTable->load($data)) {
|
||||
$catid = 0;
|
||||
}
|
||||
|
||||
return (int) $catid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new Category from within item view.
|
||||
*
|
||||
* @param array $data Array of data for new category.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function createCategory($data)
|
||||
{
|
||||
$categoryModel = Factory::getApplication()->bootComponent('com_categories')
|
||||
->getMVCFactory()->createModel('Category', 'Administrator', ['ignore_request' => true]);
|
||||
$categoryModel->save($data);
|
||||
|
||||
$catid = $categoryModel->getState('category.id');
|
||||
|
||||
return $catid;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Helper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Category Component Association Helper
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
abstract class CategoryAssociationHelper
|
||||
{
|
||||
/**
|
||||
* Flag if associations are present for categories
|
||||
*
|
||||
* @var boolean
|
||||
* @since 3.0
|
||||
*/
|
||||
public static $category_association = true;
|
||||
|
||||
/**
|
||||
* Method to get the associations for a given category
|
||||
*
|
||||
* @param integer $id Id of the item
|
||||
* @param string $extension Name of the component
|
||||
* @param string|null $layout Category layout
|
||||
*
|
||||
* @return array Array of associations for the component categories
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static function getCategoryAssociations($id = 0, $extension = 'com_content', $layout = null)
|
||||
{
|
||||
$return = [];
|
||||
|
||||
if ($id) {
|
||||
$helperClassname = ucfirst(substr($extension, 4)) . 'HelperRoute';
|
||||
|
||||
$associations = CategoriesHelper::getAssociations($id, $extension);
|
||||
|
||||
foreach ($associations as $tag => $item) {
|
||||
if (class_exists($helperClassname) && \is_callable([$helperClassname, 'getCategoryRoute'])) {
|
||||
$return[$tag] = $helperClassname::getCategoryRoute($item, $tag, $layout);
|
||||
} else {
|
||||
$link = 'index.php?option=' . $extension . '&view=category&id=' . $item;
|
||||
|
||||
if ($tag && $tag !== '*') {
|
||||
$link .= '&lang=' . $tag;
|
||||
}
|
||||
|
||||
if ($layout) {
|
||||
$link .= '&layout=' . $layout;
|
||||
}
|
||||
|
||||
$return[$tag] = $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,513 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Association\AssociationServiceInterface;
|
||||
use Joomla\CMS\Categories\CategoryServiceInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Associations;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Categories Component Categories Model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoriesModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Does an association exist? Caches the result of getAssoc().
|
||||
*
|
||||
* @var boolean|null
|
||||
* @since 4.0.5
|
||||
*/
|
||||
private $hasAssociation;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface|null $factory The factory.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'id', 'a.id',
|
||||
'title', 'a.title',
|
||||
'alias', 'a.alias',
|
||||
'published', 'a.published',
|
||||
'access', 'a.access', 'access_level',
|
||||
'language', 'a.language', 'language_title',
|
||||
'checked_out', 'a.checked_out',
|
||||
'checked_out_time', 'a.checked_out_time',
|
||||
'created_time', 'a.created_time',
|
||||
'created_user_id', 'a.created_user_id',
|
||||
'lft', 'a.lft',
|
||||
'rgt', 'a.rgt',
|
||||
'level', 'a.level',
|
||||
'path', 'a.path',
|
||||
'tag',
|
||||
'category_id', 'a.id',
|
||||
];
|
||||
}
|
||||
|
||||
if (Associations::isEnabled()) {
|
||||
$config['filter_fields'][] = 'association';
|
||||
}
|
||||
|
||||
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 1.6
|
||||
*/
|
||||
protected function populateState($ordering = 'a.lft', $direction = 'asc')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$forcedLanguage = $app->getInput()->get('forcedLanguage', '', 'cmd');
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
$extension = $app->getUserStateFromRequest($this->context . '.filter.extension', 'extension', 'com_content', 'cmd');
|
||||
|
||||
$this->setState('filter.extension', $extension);
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
// Extract the component name
|
||||
$this->setState('filter.component', $parts[0]);
|
||||
|
||||
// Extract the optional section name
|
||||
$this->setState('filter.section', (\count($parts) > 1) ? $parts[1] : null);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
|
||||
// Force a language.
|
||||
if (!empty($forcedLanguage)) {
|
||||
$this->setState('filter.language', $forcedLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 1.6
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.extension');
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
$id .= ':' . $this->getState('filter.published');
|
||||
$id .= ':' . $this->getState('filter.access');
|
||||
$id .= ':' . $this->getState('filter.language');
|
||||
$id .= ':' . $this->getState('filter.level');
|
||||
$id .= ':' . serialize($this->getState('filter.tag'));
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a database query to list categories.
|
||||
*
|
||||
* @return \Joomla\Database\DatabaseQuery
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
// Create a new query object.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
// Select the required fields from the table.
|
||||
$query->select(
|
||||
$this->getState(
|
||||
'list.select',
|
||||
'a.id, a.title, a.alias, a.note, a.published, a.access' .
|
||||
', a.checked_out, a.checked_out_time, a.created_user_id' .
|
||||
', a.path, a.parent_id, a.level, a.lft, a.rgt' .
|
||||
', a.language, a.description'
|
||||
)
|
||||
);
|
||||
$query->from($db->quoteName('#__categories', 'a'));
|
||||
|
||||
// Join over the language
|
||||
$query->select(
|
||||
[
|
||||
$db->quoteName('l.title', 'language_title'),
|
||||
$db->quoteName('l.image', 'language_image'),
|
||||
]
|
||||
)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__languages', 'l'),
|
||||
$db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language')
|
||||
);
|
||||
|
||||
// Join over the users for the checked out user.
|
||||
$query->select($db->quoteName('uc.name', 'editor'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__users', 'uc'),
|
||||
$db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out')
|
||||
);
|
||||
|
||||
// Join over the asset groups.
|
||||
$query->select($db->quoteName('ag.title', 'access_level'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__viewlevels', 'ag'),
|
||||
$db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access')
|
||||
);
|
||||
|
||||
// Join over the users for the author.
|
||||
$query->select($db->quoteName('ua.name', 'author_name'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__users', 'ua'),
|
||||
$db->quoteName('ua.id') . ' = ' . $db->quoteName('a.created_user_id')
|
||||
);
|
||||
|
||||
// Join over the associations.
|
||||
$assoc = $this->getAssoc();
|
||||
|
||||
if ($assoc) {
|
||||
$query->select('COUNT(asso2.id)>1 as association')
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__associations', 'asso'),
|
||||
$db->quoteName('asso.id') . ' = ' . $db->quoteName('a.id')
|
||||
. ' AND ' . $db->quoteName('asso.context') . ' = ' . $db->quote('com_categories.item')
|
||||
)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__associations', 'asso2'),
|
||||
$db->quoteName('asso2.key') . ' = ' . $db->quoteName('asso.key')
|
||||
)
|
||||
->group('a.id, l.title, uc.name, ag.title, ua.name');
|
||||
}
|
||||
|
||||
// Filter by extension
|
||||
if ($extension = $this->getState('filter.extension')) {
|
||||
$query->where($db->quoteName('a.extension') . ' = :extension')
|
||||
->bind(':extension', $extension);
|
||||
}
|
||||
|
||||
// Filter by categories and by level
|
||||
$categoryId = $this->getState('filter.category_id', []);
|
||||
$level = $this->getState('filter.level');
|
||||
|
||||
if (!\is_array($categoryId)) {
|
||||
$categoryId = $categoryId ? [$categoryId] : [];
|
||||
}
|
||||
|
||||
// Case: Using both categories filter and by level filter
|
||||
if (\count($categoryId)) {
|
||||
$categoryTable = Table::getInstance('Category', 'JTable');
|
||||
$subCatItemsWhere = [];
|
||||
|
||||
foreach ($categoryId as $filterCatId) {
|
||||
$categoryTable->load($filterCatId);
|
||||
$subCatItemsWhere[] = '(' .
|
||||
($level ? 'a.level <= ' . ((int) $level + (int) $categoryTable->level - 1) . ' AND ' : '') .
|
||||
'a.lft >= ' . (int) $categoryTable->lft . ' AND ' .
|
||||
'a.rgt <= ' . (int) $categoryTable->rgt . ')';
|
||||
}
|
||||
|
||||
$query->where('(' . implode(' OR ', $subCatItemsWhere) . ')');
|
||||
|
||||
// Case: Using only the by level filter
|
||||
} elseif ($level) {
|
||||
$query->where($db->quoteName('a.level') . ' <= :level')
|
||||
->bind(':level', $level, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Filter by access level.
|
||||
if ($access = (int) $this->getState('filter.access')) {
|
||||
$query->where($db->quoteName('a.access') . ' = :access')
|
||||
->bind(':access', $access, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Implement View Level Access
|
||||
if (!$user->authorise('core.admin')) {
|
||||
$groups = $user->getAuthorisedViewLevels();
|
||||
$query->whereIn($db->quoteName('a.access'), $groups);
|
||||
}
|
||||
|
||||
// Filter by published state
|
||||
$published = (string) $this->getState('filter.published');
|
||||
|
||||
if (is_numeric($published)) {
|
||||
$published = (int) $published;
|
||||
$query->where($db->quoteName('a.published') . ' = :published')
|
||||
->bind(':published', $published, ParameterType::INTEGER);
|
||||
} elseif ($published === '') {
|
||||
$query->whereIn($db->quoteName('a.published'), [0, 1]);
|
||||
}
|
||||
|
||||
// Filter by search in title
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
if (stripos($search, 'id:') === 0) {
|
||||
$search = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('a.id') . ' = :search')
|
||||
->bind(':search', $search, ParameterType::INTEGER);
|
||||
} else {
|
||||
$search = '%' . str_replace(' ', '%', trim($search)) . '%';
|
||||
$query->extendWhere(
|
||||
'AND',
|
||||
[
|
||||
$db->quoteName('a.title') . ' LIKE :title',
|
||||
$db->quoteName('a.alias') . ' LIKE :alias',
|
||||
$db->quoteName('a.note') . ' LIKE :note',
|
||||
],
|
||||
'OR'
|
||||
)
|
||||
->bind(':title', $search)
|
||||
->bind(':alias', $search)
|
||||
->bind(':note', $search);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter on the language.
|
||||
if ($language = $this->getState('filter.language')) {
|
||||
$query->where($db->quoteName('a.language') . ' = :language')
|
||||
->bind(':language', $language);
|
||||
}
|
||||
|
||||
// Filter by a single or group of tags.
|
||||
$tag = $this->getState('filter.tag');
|
||||
$typeAlias = $extension . '.category';
|
||||
|
||||
// Run simplified query when filtering by one tag.
|
||||
if (\is_array($tag) && \count($tag) === 1) {
|
||||
$tag = $tag[0];
|
||||
}
|
||||
|
||||
if ($tag && \is_array($tag)) {
|
||||
$tag = ArrayHelper::toInteger($tag);
|
||||
|
||||
$subQuery = $db->getQuery(true)
|
||||
->select('DISTINCT ' . $db->quoteName('content_item_id'))
|
||||
->from($db->quoteName('#__contentitem_tag_map'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('tag_id') . ' IN (' . implode(',', $query->bindArray($tag)) . ')',
|
||||
$db->quoteName('type_alias') . ' = :typeAlias',
|
||||
]
|
||||
);
|
||||
|
||||
$query->join(
|
||||
'INNER',
|
||||
'(' . $subQuery . ') AS ' . $db->quoteName('tagmap'),
|
||||
$db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
|
||||
)
|
||||
->bind(':typeAlias', $typeAlias);
|
||||
} elseif ($tag = (int) $tag) {
|
||||
$query->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__contentitem_tag_map', 'tagmap'),
|
||||
$db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
|
||||
)
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('tagmap.tag_id') . ' = :tag',
|
||||
$db->quoteName('tagmap.type_alias') . ' = :typeAlias',
|
||||
]
|
||||
)
|
||||
->bind(':tag', $tag, ParameterType::INTEGER)
|
||||
->bind(':typeAlias', $typeAlias);
|
||||
}
|
||||
|
||||
// Add the list ordering clause
|
||||
$listOrdering = $this->getState('list.ordering', 'a.lft');
|
||||
$listDirn = $db->escape($this->getState('list.direction', 'ASC'));
|
||||
|
||||
if ($listOrdering == 'a.access') {
|
||||
$query->order('a.access ' . $listDirn . ', a.lft ' . $listDirn);
|
||||
} else {
|
||||
$query->order($db->escape($listOrdering) . ' ' . $listDirn);
|
||||
}
|
||||
|
||||
// Group by on Categories for \JOIN with component tables to count items
|
||||
$query->group('a.id,
|
||||
a.title,
|
||||
a.alias,
|
||||
a.note,
|
||||
a.published,
|
||||
a.access,
|
||||
a.checked_out,
|
||||
a.checked_out_time,
|
||||
a.created_user_id,
|
||||
a.path,
|
||||
a.parent_id,
|
||||
a.level,
|
||||
a.lft,
|
||||
a.rgt,
|
||||
a.language,
|
||||
l.title,
|
||||
l.image,
|
||||
uc.name,
|
||||
ag.title,
|
||||
ua.name');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine if an association exists
|
||||
*
|
||||
* @return boolean True if the association exists
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function getAssoc()
|
||||
{
|
||||
if (!\is_null($this->hasAssociation)) {
|
||||
return $this->hasAssociation;
|
||||
}
|
||||
|
||||
$extension = $this->getState('filter.extension');
|
||||
|
||||
$this->hasAssociation = Associations::isEnabled();
|
||||
$extension = explode('.', $extension);
|
||||
$component = array_shift($extension);
|
||||
$cname = str_replace('com_', '', $component);
|
||||
|
||||
if (!$this->hasAssociation || !$component || !$cname) {
|
||||
$this->hasAssociation = false;
|
||||
|
||||
return $this->hasAssociation;
|
||||
}
|
||||
|
||||
$componentObject = $this->bootComponent($component);
|
||||
|
||||
if ($componentObject instanceof AssociationServiceInterface && $componentObject instanceof CategoryServiceInterface) {
|
||||
$this->hasAssociation = true;
|
||||
|
||||
return $this->hasAssociation;
|
||||
}
|
||||
|
||||
$hname = $cname . 'HelperAssociation';
|
||||
\JLoader::register($hname, JPATH_SITE . '/components/' . $component . '/helpers/association.php');
|
||||
|
||||
$this->hasAssociation = class_exists($hname) && !empty($hname::$category_association);
|
||||
|
||||
return $this->hasAssociation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of data items.
|
||||
*
|
||||
* @return mixed An array of data items on success, false on failure.
|
||||
*
|
||||
* @since 3.0.1
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$items = parent::getItems();
|
||||
|
||||
if ($items != false) {
|
||||
$extension = $this->getState('filter.extension');
|
||||
|
||||
$this->countItems($items, $extension);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to load the countItems method from the extensions
|
||||
*
|
||||
* @param \stdClass[] $items The category items
|
||||
* @param string $extension The category extension
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function countItems(&$items, $extension)
|
||||
{
|
||||
$parts = explode('.', $extension, 2);
|
||||
$section = '';
|
||||
|
||||
if (\count($parts) > 1) {
|
||||
$section = $parts[1];
|
||||
}
|
||||
|
||||
$component = Factory::getApplication()->bootComponent($parts[0]);
|
||||
|
||||
if ($component instanceof CategoryServiceInterface) {
|
||||
$component->countItems($items, $section);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulate the query to be used to evaluate if this is an Empty State to provide specific conditions for this extension.
|
||||
*
|
||||
* @return DatabaseQuery
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getEmptyStateQuery()
|
||||
{
|
||||
$query = parent::getEmptyStateQuery();
|
||||
|
||||
// Get the extension from the filter
|
||||
$extension = $this->getState('filter.extension');
|
||||
|
||||
$query->where($this->getDatabase()->quoteName('extension') . ' = :extension')
|
||||
->bind(':extension', $extension);
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
1309
administrator/components/com_categories/src/Model/CategoryModel.php
Normal file
1309
administrator/components/com_categories/src/Model/CategoryModel.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\LanguageHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Administrator category HTML
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
class AdministratorService
|
||||
{
|
||||
/**
|
||||
* Render the list of associated items
|
||||
*
|
||||
* @param integer $catid Category identifier to search its associations
|
||||
* @param string $extension Category Extension
|
||||
*
|
||||
* @return string The language HTML
|
||||
*
|
||||
* @since 3.2
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function association($catid, $extension = 'com_content')
|
||||
{
|
||||
// Defaults
|
||||
$html = '';
|
||||
|
||||
// Get the associations
|
||||
if ($associations = CategoriesHelper::getAssociations($catid, $extension)) {
|
||||
$associations = ArrayHelper::toInteger($associations);
|
||||
|
||||
// Get the associated categories
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
[
|
||||
$db->quoteName('c.id'),
|
||||
$db->quoteName('c.title'),
|
||||
$db->quoteName('l.sef', 'lang_sef'),
|
||||
$db->quoteName('l.lang_code'),
|
||||
$db->quoteName('l.image'),
|
||||
$db->quoteName('l.title', 'language_title'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__categories', 'c'))
|
||||
->whereIn($db->quoteName('c.id'), array_values($associations))
|
||||
->where($db->quoteName('c.id') . ' != :catid')
|
||||
->bind(':catid', $catid, ParameterType::INTEGER)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__languages', 'l'),
|
||||
$db->quoteName('c.language') . ' = ' . $db->quoteName('l.lang_code')
|
||||
);
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$items = $db->loadObjectList('id');
|
||||
} catch (\RuntimeException $e) {
|
||||
throw new \Exception($e->getMessage(), 500, $e);
|
||||
}
|
||||
|
||||
if ($items) {
|
||||
$languages = LanguageHelper::getContentLanguages([0, 1]);
|
||||
$content_languages = array_column($languages, 'lang_code');
|
||||
|
||||
foreach ($items as &$item) {
|
||||
if (\in_array($item->lang_code, $content_languages)) {
|
||||
$text = $item->lang_code;
|
||||
$url = Route::_('index.php?option=com_categories&task=category.edit&id=' . (int) $item->id . '&extension=' . $extension);
|
||||
$tooltip = '<strong>' . htmlspecialchars($item->language_title, ENT_QUOTES, 'UTF-8') . '</strong><br>'
|
||||
. htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8');
|
||||
$classes = 'badge bg-secondary';
|
||||
|
||||
$item->link = '<a href="' . $url . '" class="' . $classes . '">' . $text . '</a>'
|
||||
. '<div role="tooltip" id="tip-' . (int) $catid . '-' . (int) $item->id . '">' . $tooltip . '</div>';
|
||||
} else {
|
||||
// Display warning if Content Language is trashed or deleted
|
||||
Factory::getApplication()->enqueueMessage(Text::sprintf('JGLOBAL_ASSOCIATIONS_CONTENTLANGUAGE_WARNING', $item->lang_code), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html = LayoutHelper::render('joomla.content.associations', $items);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\Table;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Category table
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class CategoryTable extends \Joomla\CMS\Table\Category
|
||||
{
|
||||
/**
|
||||
* Method to delete a node and, optionally, its child nodes from the table.
|
||||
*
|
||||
* @param integer|null $pk The primary key of the node to delete.
|
||||
* @param boolean $children True to delete child nodes, false to move them up a level.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function delete($pk = null, $children = false)
|
||||
{
|
||||
return parent::delete($pk, $children);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\View\Categories;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Pagination\Pagination;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Filesystem\Path;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Categories view class for the Category package.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var Pagination
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Flag if an association exists
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $assoc;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* Is this view an Empty State
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* The ordering list for the categories
|
||||
*
|
||||
* @var array
|
||||
* @since 4.4.0
|
||||
*/
|
||||
protected $ordering = [];
|
||||
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string|null $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @throws GenericDataException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->state = $this->get('State');
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->assoc = $this->get('Assoc');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
// Written this way because we only want to call IsEmptyState if no items, to prevent always calling it when not needed.
|
||||
if (!\count($this->items) && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Preprocess the list of items to find ordering divisions.
|
||||
foreach ($this->items as &$item) {
|
||||
$this->ordering[$item->parent_id][] = $item->id;
|
||||
}
|
||||
|
||||
// We don't need toolbar in the modal window.
|
||||
if ($this->getLayout() !== 'modal') {
|
||||
$this->addToolbar();
|
||||
|
||||
// We do not need to filter by language when multilingual is disabled
|
||||
if (!Multilanguage::isEnabled()) {
|
||||
unset($this->activeFilters['language']);
|
||||
$this->filterForm->removeField('language', 'filter');
|
||||
}
|
||||
} else {
|
||||
// In article associations modal we need to remove language filter if forcing a language.
|
||||
if ($forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD')) {
|
||||
// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
|
||||
$languageXml = new \SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
|
||||
$this->filterForm->setField($languageXml, 'filter', true);
|
||||
|
||||
// Also, unset the active language filter so the search tools is not open by default with this filter.
|
||||
unset($this->activeFilters['language']);
|
||||
}
|
||||
}
|
||||
|
||||
// If filter by category is active we need to know the extension name to filter the categories
|
||||
$extensionName = $this->escape($this->state->get('filter.extension'));
|
||||
$this->filterForm->setFieldAttribute('category_id', 'extension', $extensionName, 'filter');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$categoryId = $this->state->get('filter.category_id');
|
||||
$component = $this->state->get('filter.component');
|
||||
$section = $this->state->get('filter.section');
|
||||
$canDo = ContentHelper::getActions($component, 'category', $categoryId);
|
||||
$user = $this->getCurrentUser();
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
// Avoid nonsense situation.
|
||||
if ($component == 'com_categories') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Need to load the menu language file as mod_menu hasn't been loaded yet.
|
||||
$lang = $this->getLanguage();
|
||||
$lang->load($component, JPATH_BASE)
|
||||
|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component);
|
||||
|
||||
// If a component categories title string is present, let's use it.
|
||||
if ($lang->hasKey($component_title_key = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORIES_TITLE')) {
|
||||
$title = Text::_($component_title_key);
|
||||
} elseif ($lang->hasKey($component_section_key = strtoupper($component . ($section ? "_$section" : '')))) {
|
||||
// Else if the component section string exists, let's use it.
|
||||
$title = Text::sprintf('COM_CATEGORIES_CATEGORIES_TITLE', $this->escape(Text::_($component_section_key)));
|
||||
} else { // Else use the base title
|
||||
$title = Text::_('COM_CATEGORIES_CATEGORIES_BASE_TITLE');
|
||||
}
|
||||
|
||||
// Load specific css component
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->getRegistry()->addExtensionRegistryFile($component);
|
||||
|
||||
if ($wa->assetExists('style', $component . '.admin-categories')) {
|
||||
$wa->useStyle($component . '.admin-categories');
|
||||
} else {
|
||||
$wa->registerAndUseStyle($component . '.admin-categories', $component . '/administrator/categories.css');
|
||||
}
|
||||
|
||||
// Prepare the toolbar.
|
||||
ToolbarHelper::title($title, 'folder categories ' . substr($component, 4) . ($section ? "-$section" : '') . '-categories');
|
||||
|
||||
if ($canDo->get('core.create') || \count($user->getAuthorisedCategories($component, 'core.create')) > 0) {
|
||||
$toolbar->addNew('category.add');
|
||||
}
|
||||
|
||||
if (!$this->isEmptyState && ($canDo->get('core.edit.state') || $user->authorise('core.admin'))) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
$childBar->publish('categories.publish')->listCheck(true);
|
||||
|
||||
$childBar->unpublish('categories.unpublish')->listCheck(true);
|
||||
|
||||
$childBar->archive('categories.archive')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($user->authorise('core.admin')) {
|
||||
$childBar->checkin('categories.checkin');
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state') && $this->state->get('filter.published') != -2) {
|
||||
$childBar->trash('categories.trash')->listCheck(true);
|
||||
}
|
||||
|
||||
// Add a batch button
|
||||
if (
|
||||
$canDo->get('core.create')
|
||||
&& $canDo->get('core.edit')
|
||||
&& $canDo->get('core.edit.state')
|
||||
) {
|
||||
$childBar->popupButton('batch', 'JTOOLBAR_BATCH')
|
||||
->popupType('inline')
|
||||
->textHeader(Text::_('COM_CATEGORIES_BATCH_OPTIONS'))
|
||||
->url('#joomla-dialog-batch')
|
||||
->modalWidth('800px')
|
||||
->modalHeight('fit-content')
|
||||
->listCheck(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->isEmptyState && $canDo->get('core.admin')) {
|
||||
$toolbar->standardButton('refresh', 'JTOOLBAR_REBUILD')
|
||||
->task('categories.rebuild');
|
||||
}
|
||||
|
||||
if (!$this->isEmptyState && $this->state->get('filter.published') == -2 && $canDo->get('core.delete', $component)) {
|
||||
$toolbar->delete('categories.delete', 'JTOOLBAR_EMPTY_TRASH')
|
||||
->message('JGLOBAL_CONFIRM_DELETE')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences($component);
|
||||
}
|
||||
|
||||
// Get the component form if it exists for the help key/url
|
||||
$name = 'category' . ($section ? ('.' . $section) : '');
|
||||
|
||||
// Looking first in the component forms folder
|
||||
$path = Path::clean(JPATH_ADMINISTRATOR . "/components/$component/forms/$name.xml");
|
||||
|
||||
// Looking in the component models/forms folder (J! 3)
|
||||
if (!file_exists($path)) {
|
||||
$path = Path::clean(JPATH_ADMINISTRATOR . "/components/$component/models/forms/$name.xml");
|
||||
}
|
||||
|
||||
$ref_key = '';
|
||||
$url = '';
|
||||
|
||||
// Look first in form for help key and url
|
||||
if (file_exists($path)) {
|
||||
if (!$xml = simplexml_load_file($path)) {
|
||||
throw new \Exception(Text::_('JERROR_LOADFILE_FAILED'));
|
||||
}
|
||||
|
||||
$ref_key = (string) $xml->listhelp['key'];
|
||||
$url = (string) $xml->listhelp['url'];
|
||||
}
|
||||
|
||||
if (!$ref_key) {
|
||||
// Compute the ref_key if it does exist in the component
|
||||
$languageKey = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORIES_HELP_KEY';
|
||||
|
||||
if ($lang->hasKey($languageKey)) {
|
||||
$ref_key = $languageKey;
|
||||
} else {
|
||||
$languageKey = 'JHELP_COMPONENTS_' . strtoupper(substr($component, 4) . ($section ? "_$section" : '')) . '_CATEGORIES';
|
||||
|
||||
if ($lang->hasKey($languageKey)) {
|
||||
$ref_key = $languageKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get help for the categories view for the component by
|
||||
* -remotely searching in a URL defined in the category form
|
||||
* -remotely searching in a language defined dedicated URL: *component*_HELP_URL
|
||||
* -locally searching in a component help file if helpURL param exists in the component and is set to ''
|
||||
* -remotely searching in a component URL if helpURL param exists in the component and is NOT set to ''
|
||||
*/
|
||||
if (!$url) {
|
||||
if ($lang->hasKey($lang_help_url = strtoupper($component) . '_HELP_URL')) {
|
||||
$debug = $lang->setDebug(false);
|
||||
$url = Text::_($lang_help_url);
|
||||
$lang->setDebug($debug);
|
||||
}
|
||||
}
|
||||
|
||||
$toolbar->help($ref_key, ComponentHelper::getParams($component)->exists('helpURL'), $url);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Categories\Administrator\View\Category;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Helper\TagsHelper;
|
||||
use Joomla\CMS\Language\Associations;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
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
|
||||
|
||||
/**
|
||||
* HTML View class for the Categories component
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The active item
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Flag if an association exists
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $assoc;
|
||||
|
||||
/**
|
||||
* The actions the user is authorised to perform
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $canDo;
|
||||
|
||||
/**
|
||||
* Is there a content type associated with this category alias
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $checkTags = false;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string|null $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->form = $this->get('Form');
|
||||
$this->item = $this->get('Item');
|
||||
$this->state = $this->get('State');
|
||||
$section = $this->state->get('category.section') ? $this->state->get('category.section') . '.' : '';
|
||||
$this->canDo = ContentHelper::getActions($this->state->get('category.component'), $section . 'category', $this->item->id);
|
||||
$this->assoc = $this->get('Assoc');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check if we have a content type for this alias
|
||||
if (!empty(TagsHelper::getTypes('objectList', [$this->state->get('category.extension') . '.category'], true))) {
|
||||
$this->checkTags = true;
|
||||
}
|
||||
|
||||
Factory::getApplication()->getInput()->set('hidemainmenu', true);
|
||||
|
||||
// If we are forcing a language in modal (used for associations).
|
||||
if ($this->getLayout() === 'modal' && $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'cmd')) {
|
||||
// Set the language field to the forcedLanguage and disable changing it.
|
||||
$this->form->setValue('language', null, $forcedLanguage);
|
||||
$this->form->setFieldAttribute('language', 'readonly', 'true');
|
||||
|
||||
// Only allow to select categories with All language or with the forced language.
|
||||
$this->form->setFieldAttribute('parent_id', 'language', '*,' . $forcedLanguage);
|
||||
|
||||
// Only allow to select tags with All language or with the forced language.
|
||||
$this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage);
|
||||
}
|
||||
|
||||
if ($this->getLayout() !== 'modal') {
|
||||
$this->addToolbar();
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$extension = Factory::getApplication()->getInput()->get('extension');
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
$isNew = ($this->item->id == 0);
|
||||
$checkedOut = !(\is_null($this->item->checked_out) || $this->item->checked_out == $userId);
|
||||
|
||||
// Avoid nonsense situation.
|
||||
if ($extension == 'com_categories') {
|
||||
return;
|
||||
}
|
||||
|
||||
// The extension can be in the form com_foo.section
|
||||
$parts = explode('.', $extension);
|
||||
$component = $parts[0];
|
||||
$section = (\count($parts) > 1) ? $parts[1] : null;
|
||||
$componentParams = ComponentHelper::getParams($component);
|
||||
|
||||
// Need to load the menu language file as mod_menu hasn't been loaded yet.
|
||||
$lang = $this->getLanguage();
|
||||
$lang->load($component, JPATH_BASE)
|
||||
|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component);
|
||||
|
||||
// Get the results for each action.
|
||||
$canDo = $this->canDo;
|
||||
|
||||
// If a component categories title string is present, let's use it.
|
||||
if ($lang->hasKey($component_title_key = $component . ($section ? "_$section" : '') . '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE')) {
|
||||
$title = Text::_($component_title_key);
|
||||
} elseif ($lang->hasKey($component_section_key = $component . ($section ? "_$section" : ''))) {
|
||||
// Else if the component section string exists, let's use it.
|
||||
$title = Text::sprintf('COM_CATEGORIES_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT')
|
||||
. '_TITLE', $this->escape(Text::_($component_section_key)));
|
||||
} else {
|
||||
// Else use the base title
|
||||
$title = Text::_('COM_CATEGORIES_CATEGORY_BASE_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE');
|
||||
}
|
||||
|
||||
// Load specific css component
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->getRegistry()->addExtensionRegistryFile($component);
|
||||
|
||||
if ($wa->assetExists('style', $component . '.admin-categories')) {
|
||||
$wa->useStyle($component . '.admin-categories');
|
||||
} else {
|
||||
$wa->registerAndUseStyle($component . '.admin-categories', $component . '/administrator/categories.css');
|
||||
}
|
||||
|
||||
// Prepare the toolbar.
|
||||
ToolbarHelper::title(
|
||||
$title,
|
||||
'folder category-' . ($isNew ? 'add' : 'edit')
|
||||
. ' ' . substr($component, 4) . ($section ? "-$section" : '') . '-category-' . ($isNew ? 'add' : 'edit')
|
||||
);
|
||||
|
||||
if ($isNew) {
|
||||
$toolbar->apply('category.apply');
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) {
|
||||
$childBar->save('category.save');
|
||||
$childBar->save2new('category.save2new');
|
||||
}
|
||||
);
|
||||
|
||||
$toolbar->cancel('category.cancel', 'JTOOLBAR_CANCEL');
|
||||
} else {
|
||||
// If not checked out, can save the item.
|
||||
// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
|
||||
$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_user_id == $userId);
|
||||
|
||||
// Can't save the record if it's checked out and editable
|
||||
if (!$checkedOut && $itemEditable) {
|
||||
$toolbar->apply('category.apply');
|
||||
}
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($checkedOut, $canDo, $itemEditable) {
|
||||
// Can't save the record if it's checked out and editable
|
||||
if (!$checkedOut && $itemEditable) {
|
||||
$childBar->save('category.save');
|
||||
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2new('category.save2new');
|
||||
}
|
||||
}
|
||||
|
||||
// If an existing item, can save to a copy.
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2copy('category.save2copy');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$toolbar->cancel('category.cancel');
|
||||
|
||||
if (ComponentHelper::isEnabled('com_contenthistory') && $componentParams->get('save_history', 0) && $itemEditable) {
|
||||
$typeAlias = $extension . '.category';
|
||||
$toolbar->versions($typeAlias, $this->item->id);
|
||||
}
|
||||
|
||||
if (
|
||||
Associations::isEnabled() &&
|
||||
ComponentHelper::isEnabled('com_associations') &&
|
||||
AssociationsHelper::hasSupport($component)
|
||||
) {
|
||||
$toolbar->standardButton('contract', 'JTOOLBAR_ASSOCIATIONS', 'category.editAssociations')
|
||||
->icon('icon-contract')
|
||||
->listCheck(false);
|
||||
}
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
|
||||
// Look first in form for help key
|
||||
$ref_key = (string) $this->form->getXml()->help['key'];
|
||||
|
||||
// Try with a language string
|
||||
if (!$ref_key) {
|
||||
// Compute the ref_key if it does exist in the component
|
||||
$languageKey = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT') . '_HELP_KEY';
|
||||
|
||||
if ($lang->hasKey($languageKey)) {
|
||||
$ref_key = $languageKey;
|
||||
} else {
|
||||
$languageKey = 'JHELP_COMPONENTS_'
|
||||
. strtoupper(substr($component, 4) . ($section ? "_$section" : ''))
|
||||
. '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT');
|
||||
|
||||
if ($lang->hasKey($languageKey)) {
|
||||
$ref_key = $languageKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get help for the category/section view for the component by
|
||||
* -remotely searching in a URL defined in the category form
|
||||
* -remotely searching in a language defined dedicated URL: *component*_HELP_URL
|
||||
* -locally searching in a component help file if helpURL param exists in the component and is set to ''
|
||||
* -remotely searching in a component URL if helpURL param exists in the component and is NOT set to ''
|
||||
*/
|
||||
$url = (string) $this->form->getXml()->help['url'];
|
||||
|
||||
if (!$url) {
|
||||
if ($lang->hasKey($lang_help_url = strtoupper($component) . '_HELP_URL')) {
|
||||
$debug = $lang->setDebug(false);
|
||||
$url = Text::_($lang_help_url);
|
||||
$lang->setDebug($debug);
|
||||
}
|
||||
}
|
||||
|
||||
$toolbar->help($ref_key, $componentParams->exists('helpURL'), $url, $component);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,298 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2008 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\String\Inflector;
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->get('id');
|
||||
$extension = $this->escape($this->state->get('filter.extension'));
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
$saveOrder = ($listOrder == 'a.lft' && strtolower($listDirn) == 'asc');
|
||||
$parts = explode('.', $extension, 2);
|
||||
$component = $parts[0];
|
||||
$section = null;
|
||||
|
||||
if (count($parts) > 1) {
|
||||
$section = $parts[1];
|
||||
|
||||
$inflector = Inflector::getInstance();
|
||||
|
||||
if (!$inflector->isPlural($section)) {
|
||||
$section = $inflector->toPlural($section);
|
||||
}
|
||||
}
|
||||
|
||||
if ($saveOrder && !empty($this->items)) {
|
||||
$saveOrderingUrl = 'index.php?option=com_categories&task=categories.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1';
|
||||
HTMLHelper::_('draggablelist.draggable');
|
||||
}
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_categories&view=categories&extension=' . $this->state->get('filter.extension')); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php
|
||||
// Search tools bar
|
||||
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="categoryList">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_CATEGORIES_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>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', '', 'a.lft', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-sort'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) : ?>
|
||||
<th scope="col" class="w-3 text-center d-none d-md-table-cell">
|
||||
<span class="icon-check" aria-hidden="true" title="<?php echo Text::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?>"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) : ?>
|
||||
<th scope="col" class="w-3 text-center d-none d-md-table-cell">
|
||||
<span class="icon-times" aria-hidden="true" title="<?php echo Text::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?>"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) : ?>
|
||||
<th scope="col" class="w-3 text-center d-none d-md-table-cell">
|
||||
<span class="icon-folder icon-fw" aria-hidden="true" title="<?php echo Text::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?>"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) : ?>
|
||||
<th scope="col" class="w-3 text-center d-none d-md-table-cell">
|
||||
<span class="icon-trash" aria-hidden="true" title="<?php echo Text::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?>"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php if ($this->assoc) : ?>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_CATEGORY_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<th scope="col" class="w-5 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody <?php if ($saveOrder) :
|
||||
?> class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>" data-nested="false"<?php
|
||||
endif; ?>>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<?php
|
||||
$canEdit = $user->authorise('core.edit', $extension . '.category.' . $item->id);
|
||||
$canCheckin = $user->authorise('core.admin', 'com_checkin') || $item->checked_out == $userId || is_null($item->checked_out);
|
||||
$canEditOwn = $user->authorise('core.edit.own', $extension . '.category.' . $item->id) && $item->created_user_id == $userId;
|
||||
$canChange = $user->authorise('core.edit.state', $extension . '.category.' . $item->id) && $canCheckin;
|
||||
|
||||
// Get the parents of item for sorting
|
||||
if ($item->level > 1) {
|
||||
$parentsStr = '';
|
||||
$_currentParentId = $item->parent_id;
|
||||
$parentsStr = ' ' . $_currentParentId;
|
||||
for ($i2 = 0; $i2 < $item->level; $i2++) {
|
||||
foreach ($this->ordering as $k => $v) {
|
||||
$v = implode('-', $v);
|
||||
$v = '-' . $v . '-';
|
||||
if (strpos($v, '-' . $_currentParentId . '-') !== false) {
|
||||
$parentsStr .= ' ' . $k;
|
||||
$_currentParentId = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$parentsStr = '';
|
||||
}
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>" data-draggable-group="<?php echo $item->parent_id; ?>"
|
||||
data-item-id="<?php echo $item->id ?>" data-parents="<?php echo $parentsStr ?>"
|
||||
data-level="<?php echo $item->level ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->id, false, 'cid', 'cb', $item->title); ?>
|
||||
</td>
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php
|
||||
$iconClass = '';
|
||||
if (!$canChange) {
|
||||
$iconClass = ' inactive';
|
||||
} elseif (!$saveOrder) {
|
||||
$iconClass = ' inactive" title="' . Text::_('JORDERINGDISABLED');
|
||||
}
|
||||
?>
|
||||
<span class="sortable-handler<?php echo $iconClass ?>">
|
||||
<span class="icon-ellipsis-v"></span>
|
||||
</span>
|
||||
<?php if ($canChange && $saveOrder) : ?>
|
||||
<input type="text" class="hidden" name="order[]" size="5" value="<?php echo $item->lft; ?>">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'categories.', $canChange); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php $prefix = LayoutHelper::render('joomla.html.treeprefix', ['level' => $item->level]); ?>
|
||||
<?php echo $prefix; ?>
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'categories.', $canCheckin); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit || $canEditOwn) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_categories&task=category.edit&id=' . $item->id . '&extension=' . $extension); ?>" title="<?php echo Text::_('JACTION_EDIT'); ?> <?php echo $this->escape($item->title); ?>">
|
||||
<?php echo $this->escape($item->title); ?></a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<?php echo $prefix; ?>
|
||||
<span class="small">
|
||||
<?php if (empty($item->note)) : ?>
|
||||
<?php echo Text::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
|
||||
<?php else : ?>
|
||||
<?php echo Text::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) : ?>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_published > 0) ? 'btn-success' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=1&filter[level]=1'); ?>"
|
||||
aria-describedby="tip-publish<?php echo $i; ?>">
|
||||
<?php echo $item->count_published; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-publish<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) : ?>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_unpublished > 0) ? 'btn-danger' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=0&filter[level]=1'); ?>"
|
||||
aria-describedby="tip-unpublish<?php echo $i; ?>">
|
||||
<?php echo $item->count_unpublished; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-unpublish<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) : ?>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_archived > 0) ? 'btn-info' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=2&filter[level]=1'); ?>"
|
||||
aria-describedby="tip-archive<?php echo $i; ?>">
|
||||
<?php echo $item->count_archived; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-archive<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) : ?>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_trashed > 0) ? 'btn-dark' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=-2&filter[level]=1'); ?>"
|
||||
aria-describedby="tip-trash<?php echo $i; ?>">
|
||||
<?php echo $item->count_trashed; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-trash<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo $this->escape($item->access_level); ?>
|
||||
</td>
|
||||
<?php if ($this->assoc) : ?>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php if ($item->association) : ?>
|
||||
<?php echo HTMLHelper::_('categoriesadministrator.association', $item->id, $extension); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo LayoutHelper::render('joomla.content.language', $item); ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo (int) $item->id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php // Load the batch processing form. ?>
|
||||
<?php
|
||||
if (
|
||||
$user->authorise('core.create', $extension)
|
||||
&& $user->authorise('core.edit', $extension)
|
||||
&& $user->authorise('core.edit.state', $extension)
|
||||
) : ?>
|
||||
<template id="joomla-dialog-batch"><?php echo $this->loadTemplate('batch_body'); ?></template>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="extension" value="<?php echo $extension; ?>">
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_CATEGORIES_CATEGORIES_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_CATEGORIES_CATEGORIES_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fields name="request">
|
||||
<fieldset name="request">
|
||||
<field
|
||||
name="extension"
|
||||
type="ComponentsCategory"
|
||||
label="COM_CATEGORIES_CHOOSE_COMPONENT_LABEL"
|
||||
required="true"
|
||||
addfieldprefix="Joomla\Component\Categories\Administrator\Field"
|
||||
>
|
||||
<option value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2015 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$published = (int) $this->state->get('filter.published');
|
||||
$extension = $this->escape($this->state->get('filter.extension'));
|
||||
|
||||
?>
|
||||
|
||||
<div class="p-3">
|
||||
<div class="row">
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<div class="form-group col-md-6">
|
||||
<div class="controls">
|
||||
<?php echo LayoutHelper::render('joomla.html.batch.language', []); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="form-group col-md-6">
|
||||
<div class="controls">
|
||||
<?php echo LayoutHelper::render('joomla.html.batch.access', []); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<?php if ($published >= 0) : ?>
|
||||
<div class="form-group col-md-6">
|
||||
<div class="controls">
|
||||
<?php echo LayoutHelper::render('joomla.html.batch.item', ['extension' => $extension, 'addRoot' => true]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="form-group col-md-6">
|
||||
<div class="controls">
|
||||
<?php echo LayoutHelper::render('joomla.html.batch.tag', []); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($extension === 'com_content') : ?>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<div class="controls">
|
||||
<label id="flip-ordering-id-lbl" for="flip-ordering-id" class="control-label">
|
||||
<?php echo Text::_('JLIB_HTML_BATCH_FLIPORDERING_LABEL'); ?>
|
||||
</label>
|
||||
<fieldset id="flip-ordering-id">
|
||||
<?php echo HTMLHelper::_('select.booleanlist', 'batch[flip_ordering]', [], 0, 'JYES', 'JNO', 'flip-ordering-id'); ?>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="btn-toolbar p-3">
|
||||
<joomla-toolbar-button task="category.batch" class="ms-auto">
|
||||
<button type="button" class="btn btn-success"><?php echo Text::_('JGLOBAL_BATCH_PROCESS'); ?></button>
|
||||
</joomla-toolbar-button>
|
||||
</div>
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2021 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\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$extension = $this->state->get('filter.extension');
|
||||
$component = $this->state->get('filter.component');
|
||||
$section = $this->state->get('filter.section');
|
||||
|
||||
// Special handling for the title as com_categories is a service component for many other components. Copied from the categories view.
|
||||
$lang = Factory::getApplication()->getLanguage();
|
||||
$lang->load($component, JPATH_BASE)
|
||||
|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component);
|
||||
|
||||
// If a component categories title string is present, let's use it.
|
||||
if ($lang->hasKey($component_title_key = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORIES_TITLE')) {
|
||||
$title = Text::_($component_title_key);
|
||||
} elseif ($lang->hasKey($component_section_key = strtoupper($component . ($section ? "_$section" : '')))) {
|
||||
// Else if the component section string exists, let's use it
|
||||
$title = Text::sprintf('COM_CATEGORIES_CATEGORIES_TITLE', $this->escape(Text::_($component_section_key)));
|
||||
} else // Else use the base title
|
||||
{
|
||||
$title = Text::_('COM_CATEGORIES_CATEGORIES_BASE_TITLE');
|
||||
}
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_CATEGORIES',
|
||||
'formURL' => 'index.php?option=com_categories&extension=' . $extension,
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Category',
|
||||
'title' => $title,
|
||||
'icon' => 'icon-folder categories content-categories',
|
||||
];
|
||||
|
||||
if ($this->getCurrentUser()->authorise('core.create', $extension)) {
|
||||
$displayData['createURL'] = 'index.php?option=com_categories&extension=' . $extension . '&task=category.add';
|
||||
}
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2013 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\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Component\Content\Site\Helper\RouteHelper;
|
||||
|
||||
$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('core');
|
||||
|
||||
$extension = $this->escape($this->state->get('filter.extension'));
|
||||
$function = $app->getInput()->getCmd('function', 'jSelectCategory');
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div class="container-popup">
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_categories&view=categories&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="categoryList">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_CATEGORIES_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>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-15 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$iconStates = [
|
||||
-2 => 'icon-trash',
|
||||
0 => 'icon-times',
|
||||
1 => 'icon-check',
|
||||
2 => 'icon-folder',
|
||||
];
|
||||
?>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<?php if ($item->language && Multilanguage::isEnabled()) {
|
||||
$tag = strlen($item->language);
|
||||
if ($tag == 5) {
|
||||
$lang = substr($item->language, 0, 2);
|
||||
} elseif ($tag == 6) {
|
||||
$lang = substr($item->language, 0, 3);
|
||||
} else {
|
||||
$lang = '';
|
||||
}
|
||||
} elseif (!Multilanguage::isEnabled()) {
|
||||
$lang = '';
|
||||
}
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<span class="tbody-icon">
|
||||
<span class="<?php echo $iconStates[$this->escape($item->published)]; ?>" aria-hidden="true"></span>
|
||||
</span>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php echo LayoutHelper::render('joomla.html.treeprefix', ['level' => $item->level]); ?>
|
||||
<a href="javascript:void(0)" onclick="if (window.parent) window.parent.<?php echo $this->escape($function); ?>('<?php echo $item->id; ?>', '<?php echo $this->escape(addslashes($item->title)); ?>', null, '<?php echo $this->escape(RouteHelper::getCategoryRoute($item->id, $item->language)); ?>', '<?php echo $this->escape($lang); ?>', null);">
|
||||
<?php echo $this->escape($item->title); ?></a>
|
||||
<div class="small" title="<?php echo $this->escape($item->path); ?>">
|
||||
<?php if (empty($item->note)) : ?>
|
||||
<?php echo Text::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
|
||||
<?php else : ?>
|
||||
<?php echo Text::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</th>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo $this->escape($item->access_level); ?>
|
||||
</td>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo LayoutHelper::render('joomla.content.language', $item); ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo (int) $item->id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="extension" value="<?php echo $extension; ?>">
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<input type="hidden" name="forcedLanguage" value="<?php echo $app->getInput()->get('forcedLanguage', '', 'CMD'); ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
129
administrator/components/com_categories/tmpl/category/edit.php
Normal file
129
administrator/components/com_categories/tmpl/category/edit.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2009 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\Associations;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Workflow\WorkflowServiceInterface;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$input = $app->getInput();
|
||||
|
||||
$assoc = Associations::isEnabled();
|
||||
// Are associations implemented for this extension?
|
||||
$extensionassoc = array_key_exists('item_associations', $this->form->getFieldsets());
|
||||
|
||||
// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
|
||||
$this->ignore_fieldsets = ['jmetadata', 'item_associations'];
|
||||
|
||||
$c = Factory::getApplication()->bootComponent($this->state->get('category.extension'));
|
||||
|
||||
if ($c instanceof WorkflowServiceInterface) {
|
||||
$wcontext = $c->getCategoryWorkflowContext($this->state->get('category.section'));
|
||||
|
||||
if (!$c->isWorkflowActive($wcontext)) {
|
||||
$this->ignore_fieldsets[] = 'workflow';
|
||||
}
|
||||
}
|
||||
|
||||
$this->useCoreUI = true;
|
||||
|
||||
// In case of modal
|
||||
$isModal = $input->get('layout') === 'modal';
|
||||
$layout = $isModal ? 'modal' : 'edit';
|
||||
$tmpl = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_categories&extension=' . $input->getCmd('extension', 'com_content') . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" aria-label="<?php echo Text::_('COM_CATEGORIES_FORM_TITLE_' . ((int) $this->item->id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
|
||||
|
||||
<div class="main-card">
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'general', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'general', Text::_('JCATEGORY')); ?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<?php echo $this->form->getLabel('description'); ?>
|
||||
<?php echo $this->form->getInput('description'); ?>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<?php echo LayoutHelper::render('joomla.edit.global', $this); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.params', $this); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'publishing', Text::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6">
|
||||
<fieldset id="fieldset-publishingdata" class="options-form">
|
||||
<legend><?php echo Text::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></legend>
|
||||
<div>
|
||||
<?php echo LayoutHelper::render('joomla.edit.publishingdata', $this); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<fieldset id="fieldset-metadata" class="options-form">
|
||||
<legend><?php echo Text::_('JGLOBAL_FIELDSET_METADATA_OPTIONS'); ?></legend>
|
||||
<div>
|
||||
<?php echo LayoutHelper::render('joomla.edit.metadata', $this); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php if (!$isModal && $assoc && $extensionassoc) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'associations', Text::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
|
||||
<fieldset id="fieldset-associations" class="options-form">
|
||||
<legend><?php echo Text::_('JGLOBAL_FIELDSET_ASSOCIATIONS'); ?></legend>
|
||||
<div>
|
||||
<?php echo LayoutHelper::render('joomla.edit.associations', $this); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
<?php elseif ($isModal && $assoc && $extensionassoc) : ?>
|
||||
<div class="hidden"><?php echo LayoutHelper::render('joomla.edit.associations', $this); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($this->canDo->get('core.admin')) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'rules', Text::_('COM_CATEGORIES_FIELDSET_RULES')); ?>
|
||||
<fieldset id="fieldset-rules" class="options-form">
|
||||
<legend><?php echo Text::_('COM_CATEGORIES_FIELDSET_RULES'); ?></legend>
|
||||
<div>
|
||||
<?php echo $this->form->getInput('rules'); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
|
||||
<?php echo $this->form->getInput('extension'); ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="return" value="<?php echo $input->getBase64('return'); ?>">
|
||||
<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_CATEGORIES_CATEGORY_VIEW_EDIT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_CATEGORIES_CATEGORY_VIEW_EDIT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fieldset name="request">
|
||||
<fields name="request">
|
||||
<field
|
||||
name="extension"
|
||||
type="ComponentsCategory"
|
||||
label="COM_CATEGORIES_CHOOSE_COMPONENT_LABEL"
|
||||
required="true"
|
||||
addfieldprefix="Joomla\Component\Categories\Administrator\Field"
|
||||
>
|
||||
<option value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
|
||||
</field>
|
||||
<field
|
||||
name="id"
|
||||
type="hidden"
|
||||
default="0"
|
||||
/>
|
||||
</fields>
|
||||
</fieldset>
|
||||
</metadata>
|
||||
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_categories
|
||||
*
|
||||
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
?>
|
||||
<div class="container-popup">
|
||||
<?php $this->setLayout('edit'); ?>
|
||||
<?php echo $this->loadTemplate(); ?>
|
||||
</div>
|
||||
Reference in New Issue
Block a user