Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/com_categories.tar

categories.php000064400000001664151164267220007417 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

$input = JFactory::getApplication()->input;

// If you have a URL like this:
com_categories&view=categories&extension=com_example.example_cat
$parts = explode('.', $input->get('extension'));
$component = $parts[0];

if (!JFactory::getUser()->authorise('core.manage',
$component))
{
	throw new
JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'),
403);
}

JLoader::register('JHtmlCategoriesAdministrator',
JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/html/categoriesadministrator.php');

$controller = JControllerLegacy::getInstance('Categories');
$controller->execute($input->get('task'));
$controller->redirect();
categories.xml000064400000002020151164267220007413 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1"
method="upgrade">
	<name>com_categories</name>
	<author>Joomla! Project</author>
	<creationDate>December 2007</creationDate>
	<copyright>(C) 2005 - 2020 Open Source Matters. All rights
reserved.</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>3.0.0</version>
	<description>COM_CATEGORIES_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>categories.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</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>
controller.php000064400000005470151164267220007454 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories view class for the Category package.
 *
 * @since  1.6
 */
class CategoriesController extends JControllerLegacy
{
	/**
	 * 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.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Guess the JText 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, for valid values see {@link JFilterInput::clean()}.
	 *
	 * @return  CategoriesController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Get the document object.
		$document = JFactory::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.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID',
$id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('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, 'CategoriesModel',
array('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;

			// Load the submenu.
			JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/categories.php');

			CategoriesHelper::addSubmenu($model->getState('filter.extension'));
			$view->display();
		}

		return $this;
	}
}
controllers/ajax.json.php000064400000004632151164267220011531
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Language\LanguageHelper;

/**
 * The categories controller for ajax requests
 *
 * @since  3.9.0
 */
class CategoriesControllerAjax extends JControllerLegacy
{
	/**
	 * 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  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'),
true);
		}
		else
		{
			$input     = JFactory::getApplication()->input;
			$extension = $input->get('extension');

			$assocId   = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null,
JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID',
'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '',
'STRING');

			$associations = JLanguageAssociations::getAssociations($extension,
'#__categories', 'com_categories.item', (int) $assocId,
'id', 'alias', '');

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/tables');
			$categoryTable = JTable::getInstance('Category',
'JTable');

			foreach ($associations as $lang => $association)
			{
				$categoryTable->load($association->id);
				$associations[$lang]->title = $categoryTable->title;
			}

			$countContentLanguages =
count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message =
JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message =
JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME',
$tags);
			}
			else
			{
				$message =
JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
controllers/categories.php000064400000007721151164267220011765
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * The Categories List Controller
 *
 * @since  1.6
 */
class CategoriesControllerCategories extends JControllerAdmin
{
	/**
	 * 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  JModelLegacy  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Category', $prefix =
'CategoriesModel', $config = array('ignore_request'
=> true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * 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(JRoute::_('index.php?option=com_categories&view=categories&extension='
. $extension, false));

		/** @var CategoriesModelCategory $model */
		$model = $this->getModel();

		if ($model->rebuild())
		{
			// Rebuild succeeded.
			$this->setMessage(JText::_('COM_CATEGORIES_REBUILD_SUCCESS'));

			return true;
		}

		// Rebuild failed.
		$this->setMessage(JText::_('COM_CATEGORIES_REBUILD_FAILURE'));

		return false;
	}

	/**
	 * Save the manual order inputs from the categories list page.
	 *
	 * @return      boolean  True on success
	 *
	 * @since       1.6
	 * @see         JControllerAdmin::saveorder()
	 * @deprecated  4.0
	 */
	public function saveorder()
	{
		$this->checkToken();

		try
		{
			JLog::add(sprintf('%s() is deprecated. Function will be removed in
4.0.', __METHOD__), JLog::WARNING, 'deprecated');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get the arrays from the Request
		$order = $this->input->post->get('order', null,
'array');
		$originalOrder = explode(',',
$this->input->getString('original_order_values'));

		// Make sure something has changed
		if (!($order === $originalOrder))
		{
			parent::saveorder();
		}
		else
		{
			// Nothing to reorder
			$this->setRedirect(JRoute::_('index.php?option=' .
$this->option . '&view=' . $this->view_list, false));

			return true;
		}
	}

	/**
	 * Deletes and returns correctly.
	 *
	 * @return  void
	 *
	 * @since   3.1.2
	 */
	public function delete()
	{
		$this->checkToken();

		// Get items to remove from the request.
		$cid = $this->input->get('cid', array(),
'array');
		$extension = $this->input->getCmd('extension', null);

		if (!is_array($cid) || count($cid) < 1)
		{
			JError::raiseWarning(500, JText::_($this->text_prefix .
'_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var CategoriesModelCategory $model */
			$model = $this->getModel();

			// Make sure the item ids are integers
			$cid = ArrayHelper::toInteger($cid);

			// Remove the items.
			if ($model->delete($cid))
			{
				$this->setMessage(JText::plural($this->text_prefix .
'_N_ITEMS_DELETED', count($cid)));
			}
			else
			{
				$this->setMessage($model->getError());
			}
		}

		$this->setRedirect(JRoute::_('index.php?option=' .
$this->option . '&extension=' . $extension, false));
	}

	/**
	 * Check in of one or more records.
	 *
	 * Overrides JControllerAdmin::checkin to redirect to URL with extension.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.6.0
	 */
	public function checkin()
	{
		// Process parent checkin method.
		$result = parent::checkin();

		// Override the redirect Uri.
		$redirectUri = 'index.php?option=' . $this->option .
'&view=' . $this->view_list . '&extension='
. $this->input->get('extension', '',
'CMD');
		$this->setRedirect(JRoute::_($redirectUri, false), $this->message,
$this->messageType);

		return $result;
	}
}
controllers/category.php000064400000010570151164267220011451
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

/**
 * The Category Controller
 *
 * @since  1.6
 */
class CategoriesControllerCategory extends JControllerForm
{
	/**
	 * 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.
	 *
	 * @since  1.6
	 * @see    JControllerLegacy
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Guess the JText message prefix. Defaults to the option.
		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 = array())
	{
		$user = JFactory::getUser();

		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 = array(), $key =
'parent_id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// 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;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $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();

		// Set the model
		/** @var CategoriesModelCategory $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  $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);
		$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   JModelLegacy  $model      The data model object.
	 * @param   array         $validData  The validated data.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		$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;
		}
	}
}
helpers/association.php000064400000003223151164267220011241
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/categories.php');

/**
 * Category Component Association Helper
 *
 * @since  3.0
 */
abstract class CategoryHelperAssociation
{
	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   $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 = array();

		if ($id)
		{
			// Load route helper
			jimport('helper.route', JPATH_COMPONENT_SITE);
			$helperClassname = ucfirst(substr($extension, 4)) .
'HelperRoute';

			$associations = CategoriesHelper::getAssociations($id, $extension);

			foreach ($associations as $tag => $item)
			{
				if (class_exists($helperClassname) &&
is_callable(array($helperClassname, 'getCategoryRoute')))
				{
					$return[$tag] = $helperClassname::getCategoryRoute($item, $tag,
$layout);
				}
				else
				{
					$viewLayout = $layout ? '&layout=' . $layout :
'';

					$return[$tag] = 'index.php?option=' . $extension .
'&view=category&id=' . $item . $viewLayout;
				}
			}
		}

		return $return;
	}
}
helpers/categories.php000064400000011440151164267220011052 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories helper.
 *
 * @since  1.6
 */
class CategoriesHelper
{
	/**
	 * Configure the Submenu links.
	 *
	 * @param   string  $extension  The extension being used for the
categories.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($extension)
	{
		// Avoid nonsense situation.
		if ($extension == 'com_categories')
		{
			return;
		}

		$parts = explode('.', $extension);
		$component = $parts[0];

		if (count($parts) > 1)
		{
			$section = $parts[1];
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' .
$component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst(str_replace('com_', '',
$component));
			$cName = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName))
			{
				if (is_callable(array($cName, 'addSubmenu')))
				{
					$lang = JFactory::getLanguage();

					// Loading language file from the administrator/language directory
then
					// loading language file from the
administrator/components/*extension*/language directory
					$lang->load($component, JPATH_BASE, null, false, true)
					|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR .
'/components/' . $component), null, false, true);

					call_user_func(array($cName, 'addSubmenu'),
'categories' . (isset($section) ? '.' . $section :
''));
				}
			}
		}
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @param   string   $extension   The extension.
	 * @param   integer  $categoryId  The category ID.
	 *
	 * @return  JObject
	 *
	 * @since   1.6
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions($extension, $categoryId = 0)
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated, use JHelperContent::getActions() with
new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions($extension, 'category',
$categoryId);
	}

	/**
	 * 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 = JLanguageAssociations::getAssociations($extension,
'#__categories', 'com_categories.item', $pk,
'id', 'alias', '');
		$associations     = array();
		$user             = JFactory::getUser();
		$groups           = implode(',',
$user->getAuthorisedViewLevels());

		foreach ($langAssociations as $langAssociation)
		{
			// Include only published categories with user access
			$arrId    = explode(':', $langAssociation->id);
			$assocId  = $arrId[0];

			$db    = \JFactory::getDbo();

			$query = $db->getQuery(true)
				->select($db->qn('published'))
				->from($db->qn('#__categories'))
				->where('access IN (' . $groups . ')')
				->where($db->qn('id') . ' = ' . (int)
$assocId);

			$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)
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/tables');

		$categoryTable = JTable::getInstance('Category');

		$data = array();
		$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)
	{
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/models');
		JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/tables');

		$categoryModel = JModelLegacy::getInstance('Category',
'CategoriesModel', array('ignore_request' => true));
		$categoryModel->save($data);

		$catid = $categoryModel->getState('category.id');

		return $catid;
	}
}
helpers/html/categoriesadministrator.php000064400000004610151164267220014620
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/categories.php');

/**
 * Administrator category HTML
 *
 * @since  3.2
 */
abstract class JHtmlCategoriesAdministrator
{
	/**
	 * 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 static 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 = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('c.id, c.title')
				->select('l.sef as lang_sef')
				->select('l.lang_code')
				->from('#__categories as c')
				->where('c.id IN (' . implode(',',
array_values($associations)) . ')')
				->where('c.id != ' . $catid)
				->join('LEFT', '#__languages as l ON
c.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				throw new Exception($e->getMessage(), 500, $e);
			}

			if ($items)
			{
				foreach ($items as &$item)
				{
					$text    = $item->lang_sef ? strtoupper($item->lang_sef) :
'XX';
					$url     =
JRoute::_('index.php?option=com_categories&task=category.edit&id='
. (int) $item->id . '&extension=' . $extension);
					$classes = 'hasPopover label label-association label-' .
$item->lang_sef;

					$item->link = '<a href="' . $url . '"
title="' . $item->language_title . '"
class="' . $classes
						. '" data-content="' .
htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') .
'" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations',
$items);
		}

		return $html;
	}
}
models/categories.php000064400000024654151164267220010706 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories Component Categories Model
 *
 * @since  1.6
 */
class CategoriesModelCategories extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'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',
			);
		}

		if (JLanguageAssociations::isEnabled())
		{
			$config['filter_fields'][] = 'association';
		}

		parent::__construct($config);
	}

	/**
	 * 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 = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage',
'', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->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);

		$this->setState('filter.search',
$this->getUserStateFromRequest($this->context . '.search',
'filter_search', '', 'string'));
		$this->setState('filter.published',
$this->getUserStateFromRequest($this->context .
'.filter.published', 'filter_published', '',
'string'));
		$this->setState('filter.access',
$this->getUserStateFromRequest($this->context .
'.filter.access', 'filter_access', '',
'cmd'));
		$this->setState('filter.language',
$this->getUserStateFromRequest($this->context .
'.filter.language', 'filter_language', '',
'string'));
		$this->setState('filter.tag',
$this->getUserStateFromRequest($this->context .
'.filter.tag', 'filter_tag', '',
'string'));
		$this->setState('filter.level',
$this->getUserStateFromRequest($this->context .
'.filter.level', 'filter_level', '',
'string'));

		// 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 .= ':' . $this->getState('filter.tag');

		return parent::getStoreId($id);
	}

	/**
	 * Method to get a database query to list categories.
	 *
	 * @return  JDatabaseQuery object.
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// 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'
			)
		);
		$query->from('#__categories AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS
language_image')
			->join('LEFT', $db->quoteName('#__languages')
. ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON
uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id =
a.access');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')
			->join('LEFT', '#__users AS ua ON ua.id =
a.created_user_id');

		// Join over the associations.
		$assoc = $this->getAssoc();

		if ($assoc)
		{
			$query->select('COUNT(asso2.id)>1 as association')
				->join('LEFT', '#__associations AS asso ON asso.id =
a.id AND asso.context=' .
$db->quote('com_categories.item'))
				->join('LEFT', '#__associations AS asso2 ON asso2.key
= asso.key')
				->group('a.id, l.title, uc.name, ag.title, ua.name');
		}

		// Filter by extension
		if ($extension = $this->getState('filter.extension'))
		{
			$query->where('a.extension = ' .
$db->quote($extension));
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where('a.level <= ' . (int) $level);
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.published = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.published IN (0, 1))');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ',
'%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR
a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search .
')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		// Filter by a single tag.
		$tagId = $this->getState('filter.tag');

		if (is_numeric($tagId))
		{
			$query->where($db->quoteName('tagmap.tag_id') . ' =
' . (int) $tagId)
				->join(
					'LEFT',
$db->quoteName('#__contentitem_tag_map', 'tagmap')
					. ' ON ' .
$db->quoteName('tagmap.content_item_id') . ' = ' .
$db->quoteName('a.id')
					. ' AND ' . $db->quoteName('tagmap.type_alias')
. ' = ' . $db->quote($extension . '.category')
				);
		}

		// 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()
	{
		static $assoc = null;

		if (!is_null($assoc))
		{
			return $assoc;
		}

		$extension = $this->getState('filter.extension');

		$assoc = JLanguageAssociations::isEnabled();
		$extension = explode('.', $extension);
		$component = array_shift($extension);
		$cname = str_replace('com_', '', $component);

		if (!$assoc || !$component || !$cname)
		{
			$assoc = false;
		}
		else
		{
			$hname = $cname . 'HelperAssociation';
			JLoader::register($hname, JPATH_SITE . '/components/' .
$component . '/helpers/association.php');

			$assoc = class_exists($hname) &&
!empty($hname::$category_association);
		}

		return $assoc;
	}

	/**
	 * 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);
		$component = $parts[0];
		$section = null;

		if (count($parts) > 1)
		{
			$section = $parts[1];
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' .
$component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst($eName);
			$cName = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName) && is_callable(array($cName,
'countItems')))
			{
				$cName::countItems($items, $section);
			}
		}
	}
}
models/category.php000064400000104276151164267220010375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Categories Component Category Model
 *
 * @since  1.6
 */
class CategoriesModelCategory extends JModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_CATEGORIES';

	/**
	 * The type alias for this content type. Used for content version history.
	 *
	 * @var      string
	 * @since    3.2
	 */
	public $typeAlias = null;

	/**
	 * The context used for the associations table
	 *
	 * @var      string
	 * @since    3.4.4
	 */
	protected $associationsContext = 'com_categories.item';

	/**
	 * Override parent constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see     JModelLegacy
	 * @since   3.2
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
		$extension =
JFactory::getApplication()->input->get('extension',
'com_content');
		$this->typeAlias = $extension . '.category';

		// Add a new batch command
		$this->batch_commands['flip_ordering'] =
'batchFlipordering';
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the
permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete',
$record->extension . '.category.' . (int) $record->id);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record.
Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		// Check for existing category.
		if (!empty($record->id))
		{
			return $user->authorise('core.edit.state',
$record->extension . '.category.' . (int) $record->id);
		}

		// New category, so check against the parent.
		if (!empty($record->parent_id))
		{
			return $user->authorise('core.edit.state',
$record->extension . '.category.' . (int)
$record->parent_id);
		}

		// Default to component settings if neither category nor parent known.
		return $user->authorise('core.edit.state',
$record->extension);
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Category', $prefix =
'CategoriesTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		$parentId = $app->input->getInt('parent_id');
		$this->setState('category.parent_id', $parentId);

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState($this->getName() . '.id', $pk);

		$extension = $app->input->get('extension',
'com_content');
		$this->setState('category.extension', $extension);
		$parts = explode('.', $extension);

		// Extract the component name
		$this->setState('category.component', $parts[0]);

		// Extract the optional section name
		$this->setState('category.section', (count($parts) > 1) ?
$parts[1] : null);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_categories');
		$this->setState('params', $params);
	}

	/**
	 * Method to get a category.
	 *
	 * @param   integer  $pk  An optional id of the object to get, otherwise
the id from the model state is used.
	 *
	 * @return  mixed    Category data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		if ($result = parent::getItem($pk))
		{
			// Prime required properties.
			if (empty($result->id))
			{
				$result->parent_id =
$this->getState('category.parent_id');
				$result->extension =
$this->getState('category.extension');
			}

			// Convert the metadata field to an array.
			$registry = new Registry($result->metadata);
			$result->metadata = $registry->toArray();

			// Convert the created and modified dates to local user time for display
in the form.
			$tz = new
DateTimeZone(JFactory::getApplication()->get('offset'));

			if ((int) $result->created_time)
			{
				$date = new JDate($result->created_time);
				$date->setTimezone($tz);
				$result->created_time = $date->toSql(true);
			}
			else
			{
				$result->created_time = null;
			}

			if ((int) $result->modified_time)
			{
				$date = new JDate($result->modified_time);
				$date->setTimezone($tz);
				$result->modified_time = $date->toSql(true);
			}
			else
			{
				$result->modified_time = null;
			}

			if (!empty($result->id))
			{
				$result->tags = new JHelperTags;
				$result->tags->getTagIds($result->id, $result->extension .
'.category');
			}
		}

		$assoc = $this->getAssoc();

		if ($assoc)
		{
			if ($result->id != null)
			{
				$result->associations =
ArrayHelper::toInteger(CategoriesHelper::getAssociations($result->id,
$result->extension));
			}
			else
			{
				$result->associations = array();
			}
		}

		return $result;
	}

	/**
	 * Method to get the row form.
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$extension = $this->getState('category.extension');
		$jinput = JFactory::getApplication()->input;

		// A workaround to get the extension into the model for save requests.
		if (empty($extension) && isset($data['extension']))
		{
			$extension = $data['extension'];
			$parts = explode('.', $extension);

			$this->setState('category.extension', $extension);
			$this->setState('category.component', $parts[0]);
			$this->setState('category.section', @$parts[1]);
		}

		// Get the form.
		$form = $this->loadForm('com_categories.category' .
$extension, 'category', array('control' =>
'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on Edit State access controls.
		if (empty($data['extension']))
		{
			$data['extension'] = $extension;
		}

		$categoryId = $jinput->get('id');
		$parts      = explode('.', $extension);
		$assetKey   = $categoryId ? $extension . '.category.' .
$categoryId : $parts[0];

		if (!JFactory::getUser()->authorise('core.edit.state',
$assetKey))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled',
'true');
			$form->setFieldAttribute('published', 'disabled',
'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter',
'unset');
			$form->setFieldAttribute('published', 'filter',
'unset');
		}

		return $form;
	}

	/**
	 * A protected method to get the where clause for the reorder
	 * This ensures that the row will be moved relative to a row with the same
extension
	 *
	 * @param   JTableCategory  $table  Current table instance
	 *
	 * @return  array           An array of conditions to add to add to
ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return 'extension = ' .
$this->_db->quote($table->extension);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app = JFactory::getApplication();
		$data = $app->getUserState('com_categories.edit.' .
$this->getName() . '.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Language, Access) in edit form if
those have been selected in Category Manager
			if (!$data->id)
			{
				// Check for which extension the Category Manager is used and get
selected fields
				$extension =
substr($app->getUserState('com_categories.categories.filter.extension'),
4);
				$filters = (array)
$app->getUserState('com_categories.categories.' . $extension .
'.filter');

				$data->set(
					'published',
					$app->input->getInt(
						'published',
						((isset($filters['published']) &&
$filters['published'] !== '') ?
$filters['published'] : null)
					)
				);
				$data->set('language',
$app->input->getString('language',
(!empty($filters['language']) ? $filters['language'] :
null)));
				$data->set(
					'access',
					$app->input->getInt('access',
(!empty($filters['access']) ? $filters['access'] :
JFactory::getConfig()->get('access')))
				);
			}
		}

		$this->preprocessData('com_categories.category', $data);

		return $data;
	}

	/**
	 * Method to validate the form data.
	 *
	 * @param   JForm   $form   The form to validate against.
	 * @param   array   $data   The data to validate.
	 * @param   string  $group  The name of the field group to validate.
	 *
	 * @return  array|boolean  Array of filtered data if valid, false
otherwise.
	 *
	 * @see     JFormRule
	 * @see     JFilterInput
	 * @since   3.9.23
	 */
	public function validate($form, $data, $group = null)
	{
		if (!JFactory::getUser()->authorise('core.admin',
$data['extension']))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import.
	 *
	 * @return  mixed
	 *
	 * @see     JFormField
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group =
'content')
	{
		jimport('joomla.filesystem.path');

		$lang = JFactory::getLanguage();
		$component = $this->getState('category.component');
		$section = $this->getState('category.section');
		$extension =
JFactory::getApplication()->input->get('extension', null);

		// Get the component form if it exists
		$name = 'category' . ($section ? ('.' . $section) :
'');

		// Looking first in the component models/forms folder
		$path = JPath::clean(JPATH_ADMINISTRATOR .
"/components/$component/models/forms/$name.xml");

		// Old way: looking in the component folder
		if (!file_exists($path))
		{
			$path = JPath::clean(JPATH_ADMINISTRATOR .
"/components/$component/$name.xml");
		}

		if (file_exists($path))
		{
			$lang->load($component, JPATH_BASE, null, false, true);
			$lang->load($component, JPATH_BASE . '/components/' .
$component, null, false, true);

			if (!$form->loadFile($path, false))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$path = JPath::clean(JPATH_ADMINISTRATOR .
"/components/$component/helpers/category.php");

		if (file_exists($path))
		{
			$cName = ucfirst($eName) . ucfirst($section) .
'HelperCategory';

			JLoader::register($cName, $path);

			if (class_exists($cName) && is_callable(array($cName,
'onPrepareForm')))
			{
				$lang->load($component, JPATH_BASE, null, false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' .
$component, null, false, false)
					|| $lang->load($component, JPATH_BASE, $lang->getDefault(),
false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' .
$component, $lang->getDefault(), false, false);
				call_user_func_array(array($cName, 'onPrepareForm'),
array(&$form));

				// Check for an error.
				if ($form instanceof Exception)
				{
					$this->setError($form->getMessage());

					return false;
				}
			}
		}

		// Set the access control rules field component value.
		$form->setFieldAttribute('rules', 'component',
$component);
		$form->setFieldAttribute('rules', 'section',
$name);

		// Association category items
		if ($this->getAssoc())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null,
'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name',
'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_category');
					$field->addAttribute('language',
$language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label',
'false');
					$field->addAttribute('extension', $extension);
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
				}

				$form->load($addform, false);
			}
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$table      = $this->getTable();
		$input      = JFactory::getApplication()->input;
		$pk         = (!empty($data['id'])) ? $data['id'] :
(int) $this->getState($this->getName() . '.id');
		$isNew      = true;
		$context    = $this->option . '.' . $this->name;

		if (!empty($data['tags']) && $data['tags'][0]
!= '')
		{
			$table->newTags = $data['tags'];
		}

		// Include the plugins for the save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing category.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		// Set the new parent id if parent id not matched OR while New/Save as
Copy .
		if ($table->parent_id != $data['parent_id'] ||
$data['id'] == 0)
		{
			$table->setLocation($data['parent_id'],
'last-child');
		}

		// Alter the title for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $alias) =
$this->generateNewTitle($data['parent_id'],
$data['alias'], $data['title']);
				$data['title'] = $title;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['published'] = 0;
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Bind the rules.
		if (isset($data['rules']))
		{
			$rules = new JAccessRules($data['rules']);
			$table->setRules($rules);
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save,
array($context, &$table, $isNew, $data));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		$assoc = $this->getAssoc();

		if ($assoc)
		{
			// Adding self to the association
			$associations = isset($data['associations']) ?
$data['associations'] : array();

			// Unset any invalid associations
			$associations = Joomla\Utilities\ArrayHelper::toInteger($associations);

			foreach ($associations as $tag => $id)
			{
				if (!$id)
				{
					unset($associations[$tag]);
				}
			}

			// Detecting all item menus
			$allLanguage = $table->language == '*';

			if ($allLanguage && !empty($associations))
			{
				JError::raiseNotice(403,
JText::_('COM_CATEGORIES_ERROR_ALL_LANGUAGE_ASSOCIATED'));
			}

			// Get associationskey for edited item
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('key'))
				->from($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' .
$db->quote($this->associationsContext))
				->where($db->quoteName('id') . ' = ' . (int)
$table->id);
			$db->setQuery($query);
			$oldKey = $db->loadResult();

			// Deleting old associations for the associated items
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' .
$db->quote($this->associationsContext));

			if ($associations)
			{
				$query->where('(' . $db->quoteName('id') .
' IN (' . implode(',', $associations) . ') OR
'
					. $db->quoteName('key') . ' = ' .
$db->quote($oldKey) . ')');
			}
			else
			{
				$query->where($db->quoteName('key') . ' = ' .
$db->quote($oldKey));
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			// Adding self to the association
			if (!$allLanguage)
			{
				$associations[$table->language] = (int) $table->id;
			}

			if (count($associations) > 1)
			{
				// Adding new association for these items
				$key = md5(json_encode($associations));
				$query->clear()
					->insert('#__associations');

				foreach ($associations as $id)
				{
					$query->values(((int) $id) . ',' .
$db->quote($this->associationsContext) . ',' .
$db->quote($key));
				}

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context,
&$table, $isNew, $data));

		// Rebuild the path for the category:
		if (!$table->rebuildPath($table->id))
		{
			$this->setError($table->getError());

			return false;
		}

		// Rebuild the paths of the category's children:
		if (!$table->rebuild($table->id, $table->lft, $table->level,
$table->path))
		{
			$this->setError($table->getError());

			return false;
		}

		$this->setState($this->getName() . '.id', $table->id);

		if (Factory::getApplication()->input->get('task') ==
'editAssociations')
		{
			return $this->redirectToAssociations($data);
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish(&$pks, $value = 1)
	{
		if (parent::publish($pks, $value))
		{
			$dispatcher = JEventDispatcher::getInstance();
			$extension =
JFactory::getApplication()->input->get('extension');

			// Include the content plugins for the change of category state event.
			JPluginHelper::importPlugin('content');

			// Trigger the onCategoryChangeState event.
			$dispatcher->trigger('onCategoryChangeState',
array($extension, $pks, $value));

			return true;
		}
	}

	/**
	 * Method rebuild the entire nested set tree.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->rebuild())
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to save the reordered nested set tree.
	 * First we save the new order values in the lft values of the changed
ids.
	 * Then we invoke the table rebuild to implement the new ordering.
	 *
	 * @param   array    $idArray   An array of primary key ids.
	 * @param   integer  $lftArray  The lft value
	 *
	 * @return  boolean  False on failure or error, True otherwise
	 *
	 * @since   1.6
	 */
	public function saveorder($idArray = null, $lftArray = null)
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->saveorder($idArray, $lftArray))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Batch tag a list of categories.
	 *
	 * @param   integer  $value     The value of the new tag.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean true if successful; false otherwise.
	 */
	protected function batchTag($value, $pks, $contexts)
	{
		// Set the variables
		$user = JFactory::getUser();
		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.edit', $contexts[$pk]))
			{
				$table->reset();
				$table->load($pk);
				$tags = array($value);

				/** @var  JTableObserverTags  $tagsObserver */
				$tagsObserver =
$table->getObserverOfClass('JTableObserverTags');
				$result = $tagsObserver->setNewTags($tags, false);

				if (!$result)
				{
					$this->setError($table->getError());

					return false;
				}
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Batch flip category ordering.
	 *
	 * @param   integer  $value     The new category.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  mixed    An array of new IDs on success, boolean false on
failure.
	 *
	 * @since   3.6.3
	 */
	protected function batchFlipordering($value, $pks, $contexts)
	{
		$successful = array();

		$db = $this->getDbo();
		$query = $db->getQuery(true);

		/**
		 * For each category get the max ordering value
		 * Re-order with max - ordering
		 */
		foreach ($pks as $id)
		{
			$query->select('MAX(ordering)')
				->from('#__content')
				->where($db->qn('catid') . ' = ' .
$db->q($id));

			$db->setQuery($query);

			$max = (int) $db->loadresult();
			$max++;

			$query->clear();

			$query->update('#__content')
				->set($db->qn('ordering') . ' = ' . $max .
' - ' . $db->qn('ordering'))
				->where($db->qn('catid') . ' = ' .
$db->q($id));

			$db->setQuery($query);

			if ($db->execute())
			{
				$successful[] = $id;
			}
		}

		return empty($successful) ? false : $successful;
	}

	/**
	 * Batch copy categories to a new category.
	 *
	 * @param   integer  $value     The new category.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  mixed    An array of new IDs on success, boolean false on
failure.
	 *
	 * @since   1.6
	 */
	protected function batchCopy($value, $pks, $contexts)
	{
		$type = new JUcmType;
		$this->type = $type->getTypeByAlias($this->typeAlias);

		// $value comes as {parent_id}.{extension}
		$parts = explode('.', $value);
		$parentId = (int) ArrayHelper::getValue($parts, 0, 1);

		$db = $this->getDbo();
		$extension =
JFactory::getApplication()->input->get('extension',
'', 'word');
		$newIds = array();

		// Check that the parent exists
		if ($parentId)
		{
			if (!$this->table->load($parentId))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}

			// Check that user has create permission for parent category
			if ($parentId == $this->table->getRootId())
			{
				$canCreate = $this->user->authorise('core.create',
$extension);
			}
			else
			{
				$canCreate = $this->user->authorise('core.create',
$extension . '.category.' . $parentId);
			}

			if (!$canCreate)
			{
				// Error since user cannot create in parent category
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// If the parent is 0, set it to the ID of the root item in the tree
		if (empty($parentId))
		{
			if (!$parentId = $this->table->getRootId())
			{
				$this->setError($db->getErrorMsg());

				return false;
			}
			// Make sure we can create in root
			elseif (!$this->user->authorise('core.create',
$extension))
			{
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// We need to log the parent ID
		$parents = array();

		// Calculate the emergency stop count as a precaution against a runaway
loop bug
		$query = $db->getQuery(true)
			->select('COUNT(id)')
			->from($db->quoteName('#__categories'));
		$db->setQuery($query);

		try
		{
			$count = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Parent exists so let's proceed
		while (!empty($pks) && $count > 0)
		{
			// Pop the first id off the stack
			$pk = array_shift($pks);

			$this->table->reset();

			// Check that the row actually exists
			if (!$this->table->load($pk))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND',
$pk));
					continue;
				}
			}

			// Copy is a bit tricky, because we also need to copy the children
			$query->clear()
				->select('id')
				->from($db->quoteName('#__categories'))
				->where('lft > ' . (int) $this->table->lft)
				->where('rgt < ' . (int) $this->table->rgt);
			$db->setQuery($query);
			$childIds = $db->loadColumn();

			// Add child ID's to the array only if they aren't already
there.
			foreach ($childIds as $childId)
			{
				if (!in_array($childId, $pks))
				{
					$pks[] = $childId;
				}
			}

			// Make a copy of the old ID, Parent ID and Asset ID
			$oldId       = $this->table->id;
			$oldParentId = $this->table->parent_id;
			$oldAssetId  = $this->table->asset_id;

			// Reset the id because we are making a copy.
			$this->table->id = 0;

			// If we a copying children, the Old ID will turn up in the parents list
			// otherwise it's a new top level item
			$this->table->parent_id = isset($parents[$oldParentId]) ?
$parents[$oldParentId] : $parentId;

			// Set the new location in the tree for the node.
			$this->table->setLocation($this->table->parent_id,
'last-child');

			// @TODO: Deal with ordering?
			// $this->table->ordering = 1;
			$this->table->level = null;
			$this->table->asset_id = null;
			$this->table->lft = null;
			$this->table->rgt = null;

			// Alter the title & alias
			list($title, $alias) =
$this->generateNewTitle($this->table->parent_id,
$this->table->alias, $this->table->title);
			$this->table->title  = $title;
			$this->table->alias  = $alias;

			// Unpublish because we are making a copy
			$this->table->published = 0;

			$this->createTagsHelper($this->tagsObserver, $this->type, $pk,
$this->typeAlias, $this->table);

			// Store the row.
			if (!$this->table->store())
			{
				$this->setError($this->table->getError());

				return false;
			}

			// Get the new item ID
			$newId = $this->table->get('id');

			// Add the new ID to the array
			$newIds[$pk] = $newId;

			// Copy rules
			$query->clear()
				->update($db->quoteName('#__assets', 't'))
				->join('INNER', $db->quoteName('#__assets',
's') .
					' ON ' . $db->quoteName('s.id') . ' =
' . $oldAssetId
				)
				->set($db->quoteName('t.rules') . ' = ' .
$db->quoteName('s.rules'))
				->where($db->quoteName('t.id') . ' = ' .
$this->table->asset_id);
			$db->setQuery($query)->execute();

			// Now we log the old 'parent' to the new 'parent'
			$parents[$oldId] = $this->table->id;
			$count--;
		}

		// Rebuild the hierarchy.
		if (!$this->table->rebuild())
		{
			$this->setError($this->table->getError());

			return false;
		}

		// Rebuild the tree path.
		if (!$this->table->rebuildPath($this->table->id))
		{
			$this->setError($this->table->getError());

			return false;
		}

		return $newIds;
	}

	/**
	 * Batch move categories to a new category.
	 *
	 * @param   integer  $value     The new category ID.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		$parentId = (int) $value;
		$type = new JUcmType;
		$this->type = $type->getTypeByAlias($this->typeAlias);

		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$extension =
JFactory::getApplication()->input->get('extension',
'', 'word');

		// Check that the parent exists.
		if ($parentId)
		{
			if (!$this->table->load($parentId))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error.
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error.
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}

			// Check that user has create permission for parent category.
			if ($parentId == $this->table->getRootId())
			{
				$canCreate = $this->user->authorise('core.create',
$extension);
			}
			else
			{
				$canCreate = $this->user->authorise('core.create',
$extension . '.category.' . $parentId);
			}

			if (!$canCreate)
			{
				// Error since user cannot create in parent category
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}

			// Check that user has edit permission for every category being moved
			// Note that the entire batch operation fails if any category lacks edit
permission
			foreach ($pks as $pk)
			{
				if (!$this->user->authorise('core.edit', $extension .
'.category.' . $pk))
				{
					// Error since user cannot edit this category
					$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_EDIT'));

					return false;
				}
			}
		}

		// We are going to store all the children and just move the category
		$children = array();

		// Parent exists so let's proceed
		foreach ($pks as $pk)
		{
			// Check that the row actually exists
			if (!$this->table->load($pk))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND',
$pk));
					continue;
				}
			}

			// Set the new location in the tree for the node.
			$this->table->setLocation($parentId, 'last-child');

			// Check if we are moving to a different parent
			if ($parentId != $this->table->parent_id)
			{
				// Add the child node ids to the children array.
				$query->clear()
					->select('id')
					->from($db->quoteName('#__categories'))
					->where($db->quoteName('lft') . ' BETWEEN '
. (int) $this->table->lft . ' AND ' . (int)
$this->table->rgt);
				$db->setQuery($query);

				try
				{
					$children = array_merge($children, (array) $db->loadColumn());
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}

			$this->createTagsHelper($this->tagsObserver, $this->type, $pk,
$this->typeAlias, $this->table);

			// Store the row.
			if (!$this->table->store())
			{
				$this->setError($this->table->getError());

				return false;
			}

			// Rebuild the tree path.
			if (!$this->table->rebuildPath())
			{
				$this->setError($this->table->getError());

				return false;
			}
		}

		// Process the child rows
		if (!empty($children))
		{
			// Remove any duplicates and sanitize ids.
			$children = array_unique($children);
			$children = ArrayHelper::toInteger($children);
		}

		return true;
	}

	/**
	 * Custom clean the cache of com_content and content modules
	 *
	 * @param   string   $group     Cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$extension =
JFactory::getApplication()->input->get('extension');

		switch ($extension)
		{
			case 'com_content':
				parent::cleanCache('com_content');
				parent::cleanCache('mod_articles_archive');
				parent::cleanCache('mod_articles_categories');
				parent::cleanCache('mod_articles_category');
				parent::cleanCache('mod_articles_latest');
				parent::cleanCache('mod_articles_news');
				parent::cleanCache('mod_articles_popular');
				break;
			default:
				parent::cleanCache($extension);
				break;
		}
	}

	/**
	 * Method to change the title & alias.
	 *
	 * @param   integer  $parentId  The id of the parent.
	 * @param   string   $alias     The alias.
	 * @param   string   $title     The title.
	 *
	 * @return  array    Contains the modified title and alias.
	 *
	 * @since   1.7
	 */
	protected function generateNewTitle($parentId, $alias, $title)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('alias' => $alias,
'parent_id' => $parentId)))
		{
			$title = StringHelper::increment($title);
			$alias = StringHelper::increment($alias, 'dash');
		}

		return array($title, $alias);
	}

	/**
	 * Method to determine if a category association is available.
	 *
	 * @return  boolean True if a category association is available; false
otherwise.
	 */
	public function getAssoc()
	{
		static $assoc = null;

		if (!is_null($assoc))
		{
			return $assoc;
		}

		$extension = $this->getState('category.extension');

		$assoc = JLanguageAssociations::isEnabled();
		$extension = explode('.', $extension);
		$component = array_shift($extension);
		$cname = str_replace('com_', '', $component);

		if (!$assoc || !$component || !$cname)
		{
			$assoc = false;
		}
		else
		{
			$hname = $cname . 'HelperAssociation';
			JLoader::register($hname, JPATH_SITE . '/components/' .
$component . '/helpers/association.php');

			$assoc = class_exists($hname) &&
!empty($hname::$category_association);
		}

		return $assoc;
	}
}
models/fields/categoryedit.php000064400000031541151164267220012503
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

JFormHelper::loadFieldClass('list');

/**
 * Category Edit field..
 *
 * @since  1.6
 */
class JFormFieldCategoryEdit extends JFormFieldList
{
	/**
	 * 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';

	/**
	 * 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            $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     JFormField::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']) ?
$this->element['allowAdd'] : '';
			$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':
			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 = array();
		$published = $this->element['published'] ?
explode(',', (string) $this->element['published']) :
array(0, 1);
		$name = (string) $this->element['name'];

		// Let's get the id for the current item, either category or content
item.
		$jinput = JFactory::getApplication()->input;

		// 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 = JFactory::getDbo();
		$user = JFactory::getUser();

		$query = $db->getQuery(true)
			->select('a.id AS value, a.title AS text, a.level, a.published,
a.lft, a.language')
			->from('#__categories AS a');

		// Filter by the extension type
		if ($this->element['parent'] == true ||
$jinput->get('option') == 'com_categories')
		{
			$query->where('(a.extension = ' . $db->quote($extension)
. ' OR a.parent_id = 0)');
		}
		else
		{
			$query->where('(a.extension = ' . $db->quote($extension)
. ')');
		}

		// Filter language
		if (!empty($this->element['language']))
		{
			if (strpos($this->element['language'], ',') !==
false)
			{
				$language = implode(',', $db->quote(explode(',',
$this->element['language'])));
			}
			else
			{
				$language = $db->quote($this->element['language']);
			}

			$query->where($db->quoteName('a.language') . ' IN
(' . $language . ')');
		}

		// Filter on the published state
		$query->where('a.published IN (' . implode(',',
ArrayHelper::toInteger($published)) . ')');

		// Filter categories on User Access Level
		// Filter by access level on categories.
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		$query->order('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') . ' AS p ON p.id = '
. (int) $oldCat)
				->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');

			$rowQuery = $db->getQuery(true);
			$rowQuery->select('a.id AS value, a.title AS text, a.level,
a.parent_id')
				->from('#__categories AS a')
				->where('a.id = ' . (int) $oldCat);
			$db->setQuery($rowQuery);
			$row = $db->loadObject();
		}

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// 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 = JText::_('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]->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]);
				}
			}
		}
		// If you have an existing category id things are more complex.
		else
		{
			/*
			 * 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]);
					continue;
				}
			}
		}

		if (($this->element['parent'] == true ||
$jinput->get('option') == 'com_categories')
			&& (isset($row) && !isset($options[0]))
			&& isset($this->element['show_root']))
		{
			if ($row->parent_id == '1')
			{
				$parent = new stdClass;
				$parent->text = JText::_('JGLOBAL_ROOT_PARENT');
				array_unshift($options, $parent);
			}

			array_unshift($options, JHtml::_('select.option',
'0', JText::_('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()
	{
		$html = array();
		$class = array();
		$attr = '';

		// Initialize some field attributes.
		$class[] = !empty($this->class) ? $this->class : '';

		if ($this->allowAdd)
		{
			$customGroupText = JText::_('JGLOBAL_CUSTOM_CATEGORY');

			$class[] = 'chzn-custom-value';
			$attr .= ' data-custom_group_text="' . $customGroupText .
'" '
					. 'data-no_results_text="' .
JText::_('JGLOBAL_ADD_CUSTOM_CATEGORY') . '" '
					. 'data-placeholder="' .
JText::_('JGLOBAL_TYPE_OR_SELECT_CATEGORY') . '"
';

			if ($this->customPrefix !== '')
			{
				$attr .= 'data-custom_value_prefix="' .
$this->customPrefix . '" ';
			}
		}

		if ($class)
		{
			$attr .= 'class="' . implode(' ', $class) .
'"';
		}

		$attr .= !empty($this->size) ? ' size="' .
$this->size . '"' : '';
		$attr .= $this->multiple ? ' multiple' : '';
		$attr .= $this->required ? ' required
aria-required="true"' : '';
		$attr .= $this->autofocus ? ' autofocus' : '';

		// To avoid user's confusion, readonly="true" should imply
disabled="true".
		if ((string) $this->readonly == '1'
			|| (string) $this->readonly == 'true'
			|| (string) $this->disabled == '1'
			|| (string) $this->disabled == 'true')
		{
			$attr .= ' disabled="disabled"';
		}

		// Initialize JavaScript field attributes.
		$attr .= $this->onchange ? ' onchange="' .
$this->onchange . '"' : '';

		// Get the field options.
		$options = (array) $this->getOptions();

		// Create a read-only list (no name) with hidden input(s) to store the
value(s).
		if ((string) $this->readonly == '1' || (string)
$this->readonly == 'true')
		{
			$html[] = JHtml::_('select.genericlist', $options,
'', trim($attr), 'value', 'text',
$this->value, $this->id);

			// E.g. form field type tag sends $this->value as array
			if ($this->multiple && is_array($this->value))
			{
				if (!count($this->value))
				{
					$this->value[] = '';
				}

				foreach ($this->value as $value)
				{
					$html[] = '<input type="hidden" name="' .
$this->name . '" value="' . htmlspecialchars($value,
ENT_COMPAT, 'UTF-8') . '"/>';
				}
			}
			else
			{
				$html[] = '<input type="hidden" name="' .
$this->name . '" value="' .
htmlspecialchars($this->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[] = JHtml::_('select.genericlist', $options,
$this->name, trim($attr), 'value', 'text',
$this->value, $this->id);
		}

		return implode($html);
	}
}
models/fields/categoryparent.php000064400000012172151164267220013046
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JFormHelper::loadFieldClass('list');

/**
 * Category Parent field.
 *
 * @since       1.6
 * @deprecated  4.0  Use categoryedit instead.
 */
class JFormFieldCategoryParent extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'CategoryParent';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		// Initialise variables.
		$options = array();
		$name = (string) $this->element['name'];

		// Let's get the id for the current item, either category or content
item.
		$jinput = JFactory::getApplication()->input;

		// For categories the old category is the category id 0 for new category.
		if ($this->element['parent'])
		{
			$oldCat = $jinput->get('id', 0);
		}
		else
			// For items the old category is the category they are in when opened or
0 if new.
		{
			$oldCat = $this->form->getValue($name);
		}

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.id AS value, a.title AS text, a.level')
			->from('#__categories AS a')
			->join('LEFT', $db->quoteName('#__categories')
. ' AS b ON a.lft > b.lft AND a.rgt < b.rgt');

		// Filter by the type
		if ($extension = $this->form->getValue('extension'))
		{
			$query->where('(a.extension = ' . $db->quote($extension)
. ' OR a.parent_id = 0)');
		}

		if ($this->element['parent'])
		{
			// Prevent parenting to children of this item.
			if ($id = $this->form->getValue('id'))
			{
				$query->join('LEFT',
$db->quoteName('#__categories') . ' AS p ON p.id = '
. (int) $id)
					->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');

				$rowQuery = $db->getQuery(true);
				$rowQuery->select('a.id AS value, a.title AS text, a.level,
a.parent_id')
					->from('#__categories AS a')
					->where('a.id = ' . (int) $id);
				$db->setQuery($rowQuery);
				$row = $db->loadObject();
			}
		}

		$query->where('a.published IN (0,1)')
			->group('a.id, a.title, a.level, a.lft, a.rgt, a.extension,
a.parent_id')
			->order('a.lft ASC');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Pad the option text with spaces using depth level as a multiplier.
		for ($i = 0, $n = count($options); $i < $n; $i++)
		{
			// Translate ROOT
			if ($options[$i]->level == 0)
			{
				$options[$i]->text = JText::_('JGLOBAL_ROOT_PARENT');
			}

			// Displays language code if not set to All
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('language'))
				->where($db->quoteName('id') . '=' . (int)
$options[$i]->value)
				->from($db->quoteName('#__categories'));

			$db->setQuery($query);
			$language = $db->loadResult();

			$options[$i]->text = str_repeat('- ',
$options[$i]->level) . $options[$i]->text;

			if ($language !== '*')
			{
				$options[$i]->text = $options[$i]->text . ' (' .
$language . ')';
			}
		}

		// Get the current user object.
		$user = JFactory::getUser();

		// 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 ($user->authorise('core.create', $extension .
'.category.' . $option->value) != true)
				{
					unset($options[$i]);
				}
			}
		}
		// If you have an existing category id things are more complex.
		else
		{
			foreach ($options as $i => $option)
			{
				/*
				 * 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.
				 */
				if ($user->authorise('core.edit.state', $extension .
'.category.' . $oldCat) != true)
				{
					if ($option->value != $oldCat)
					{
						echo 'y';
						unset($options[$i]);
					}
				}
				/*
				 * 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.
				 */
				elseif (($user->authorise('core.create', $extension .
'.category.' . $option->value) != true)
					&& $option->value != $oldCat
				)
				{
					echo 'x';
					unset($options[$i]);
				}
			}
		}

		if (isset($row) && !isset($options[0]))
		{
			if ($row->parent_id == '1')
			{
				$parent = new stdClass;
				$parent->text = JText::_('JGLOBAL_ROOT_PARENT');
				array_unshift($options, $parent);
			}
		}

		// Merge any additional options in the XML definition.
		return array_merge(parent::getOptions(), $options);
	}
}
models/fields/modal/category.php000064400000023601151164267220012727
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Language\LanguageHelper;

/**
 * Supports a modal category picker.
 *
 * @since  3.1
 */
class JFormFieldModal_Category extends JFormField
{
	/**
	 * 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)
JFactory::getApplication()->input->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(array(0, 1));

		// Load language.
		JFactory::getLanguage()->load('com_categories',
JPATH_ADMINISTRATOR);

		// The active category id field.
		$value = (int) $this->value > 0 ? (int) $this->value :
'';

		// Create the modal id.
		$modalId = 'Category_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js',
array('version' => 'auto', 'relative'
=> true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectCategory_" . $this->id . "(id, title,
object) {
					window.processModalSelect('Category', '" .
$this->id . "', id, title, '', object);
				}
				");

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkCategories =
'index.php?option=com_categories&amp;view=categories&amp;layout=modal&amp;tmpl=component&amp;'
. JSession::getFormToken() . '=1'
			. '&amp;extension=' . $extension;
		$linkCategory  =
'index.php?option=com_categories&amp;view=category&amp;layout=modal&amp;tmpl=component&amp;'
. JSession::getFormToken() . '=1'
			. '&amp;extension=' . $extension;
		$modalTitle    = JText::_('COM_CATEGORIES_CHANGE_CATEGORY');

		if (isset($this->element['language']))
		{
			$linkCategories .= '&amp;forcedLanguage=' .
$this->element['language'];
			$linkCategory   .= '&amp;forcedLanguage=' .
$this->element['language'];
			$modalTitle     .= ' &#8212; ' .
$this->element['label'];
		}

		$urlSelect = $linkCategories .
'&amp;function=jSelectCategory_' . $this->id;
		$urlEdit   = $linkCategory .
'&amp;task=category.edit&amp;id=\' +
document.getElementById("' . $this->id .
'_id").value + \'';
		$urlNew    = $linkCategory . '&amp;task=category.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__categories'))
				->where($db->quoteName('id') . ' = ' . (int)
$value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		$title = empty($title) ?
JText::_('COM_CATEGORIES_SELECT_A_CATEGORY') :
htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current category display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' .
$this->id . '_name" type="text" value="' .
$title . '" disabled="disabled" size="35"
/>';

		// Select category button.
		if ($allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '
hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId .
'"'
				. ' title="' .
JHtml::tooltipText('COM_CATEGORIES_CHANGE_CATEGORY') .
'">'
				. '<span class="icon-file"
aria-hidden="true"></span> ' .
JText::_('JSELECT')
				. '</button>';
		}

		// New category button.
		if ($allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '
hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId .
'"'
				. ' title="' .
JHtml::tooltipText('COM_CATEGORIES_NEW_CATEGORY') .
'">'
				. '<span class="icon-new"
aria-hidden="true"></span> ' .
JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit category button.
		if ($allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' :
' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId .
'"'
				. ' title="' .
JHtml::tooltipText('COM_CATEGORIES_EDIT_CATEGORY') .
'">'
				. '<span class="icon-edit"
aria-hidden="true"></span> ' .
JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear category button.
		if ($allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : '
hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' .
$this->id . '\'); return false;">'
				. '<span class="icon-remove"
aria-hidden="true"></span>' .
JText::_('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 .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' :
' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' .
JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') .
'"'
			. ' onclick="Joomla.propagateAssociation(\'' .
$this->id . '\', \'' . $callbackFunctionStem .
'\');">'
			. '<span class="icon-refresh"
aria-hidden="true"></span>' .
JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';

		// Select category modal.
		if ($allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button"
class="btn" data-dismiss="modal">' .
JText::_('JLIB_HTML_BEHAVIOR_CLOSE') .
'</button>',
				)
			);
		}

		// New category modal.
		if ($allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       =>
JText::_('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"'
							. ' onclick="window.processModalEdit(this, \'' .
$this->id . '\', \'add\', \'category\',
\'cancel\', \'item-form\'); return
false;">'
							. JText::_('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;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn
btn-success"'
							. ' onclick="window.processModalEdit(this, \'' .
$this->id . '\', \'add\', \'category\',
\'apply\', \'item-form\'); return
false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit category modal.
		if ($allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       =>
JText::_('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"'
							. ' onclick="window.processModalEdit(this, \'' .
$this->id . '\', \'edit\', \'category\',
\'cancel\', \'item-form\'); return
false;">'
							. JText::_('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;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn
btn-success"'
							. ' onclick="window.processModalEdit(this, \'' .
$this->id . '\', \'edit\', \'category\',
\'apply\', \'item-form\'); return
false;">'
							. JText::_('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(JText::_('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 . '_id',
parent::getLabel());
	}
}
models/forms/category.xml000064400000012522151164267220011524
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<field
		name="id"
		type="number"
		label="JGLOBAL_FIELD_ID_LABEL"
		description="JGLOBAL_FIELD_ID_DESC"
		default="0"
		class="readonly"
		readonly="true"
	/>

	<field
		name="hits"
		type="number"
		label="JGLOBAL_HITS"
		description="COM_CATEGORIES_FIELD_HITS_DESC"
		default="0"
		class="readonly"
		readonly="true"
		filter="unset"
	/>

	<field
		name="asset_id"
		type="hidden"
		filter="unset"
		label="JFIELD_ASSET_ID_LABEL"
		description="JFIELD_ASSET_ID_DESC"
	/>

	<field
		name="parent_id"
		type="categoryedit"
		label="COM_CATEGORIES_FIELD_PARENT_LABEL"
		description="COM_CATEGORIES_FIELD_PARENT_DESC"
	/>

	<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"
		description="COM_CATEGORIES_PATH_DESC"
		class="readonly"
		size="40"
		readonly="true"
	/>

	<field
		name="extension"
		type="hidden"
	/>

	<field
		name="title"
		type="text"
		label="JGLOBAL_TITLE"
		description="JFIELD_TITLE_DESC"
		class="input-xxlarge input-large-text"
		size="40"
		required="true"
	/>

	<field
		name="alias"
		type="text"
		label="JFIELD_ALIAS_LABEL"
		description="JFIELD_ALIAS_DESC"
		size="45"
		hint="JFIELD_ALIAS_PLACEHOLDER"
	/>

	<field
		name="version_note"
		type="text"
		label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
		description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
		class="span12"
		size="45"
		maxlength="255"
	/>

	<field
		name="note"
		type="text"
		label="COM_CATEGORIES_FIELD_NOTE_LABEL"
		description="COM_CATEGORIES_FIELD_NOTE_DESC"
		class="span12"
		size="40"
		maxlength="255"
	/>

	<field
		name="description"
		type="editor"
		label="JGLOBAL_DESCRIPTION"
		description="COM_CATEGORIES_DESCRIPTION_DESC"
		filter="JComponentHelper::filterText"
		buttons="true"
		hide="readmore,pagebreak"
	/>

	<field
		name="published"
		type="list"
		label="JSTATUS"
		description="JFIELD_PUBLISHED_DESC"
		default="1"
		class="chzn-color-state"
		size="1"
		>
		<option value="1">JPUBLISHED</option>
		<option value="0">JUNPUBLISHED</option>
		<option value="2">JARCHIVED</option>
		<option value="-2">JTRASHED</option>
	</field>

	<field
		name="buttonspacer"
		type="spacer"
		label="JGLOBAL_ACTION_PERMISSIONS_LABEL"
		description="JGLOBAL_ACTION_PERMISSIONS_DESCRIPTION"
	/>

	<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"
		description="JFIELD_ACCESS_DESC"
	/>

	<field
		name="metadesc"
		type="textarea"
		label="JFIELD_META_DESCRIPTION_LABEL"
		description="JFIELD_META_DESCRIPTION_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="metakey"
		type="textarea"
		label="JFIELD_META_KEYWORDS_LABEL"
		description="JFIELD_META_KEYWORDS_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="created_user_id"
		type="user"
		label="JGLOBAL_FIELD_CREATED_BY_LABEL"
		desc="JGLOBAL_FIELD_CREATED_BY_DESC"
	/>

	<field
		name="created_time"
		type="calendar"
		label="JGLOBAL_CREATED_DATE"
		translateformat="true"
		showtime="true"
		size="22"
		filter="user_utc"
	/>

	<field
		name="modified_user_id"
		type="user"
		label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
		class="readonly"
		readonly="true"
		filter="unset"
	/>

	<field
		name="modified_time"
		type="calendar"
		label="JGLOBAL_FIELD_MODIFIED_LABEL"
		class="readonly"
		translateformat="true"
		showtime="true"
		size="22"
		readonly="true"
		filter="user_utc"
	/>

	<field
		name="language"
		type="contentlanguage"
		label="JFIELD_LANGUAGE_LABEL"
		description="COM_CATEGORIES_FIELD_LANGUAGE_DESC"
		>
		<option value="*">JALL</option>
	</field>

	<field
		name="tags"
		type="tag"
		label="JTAG"
		description="JTAG_DESC"
		class="span12"
		multiple="true"
	/>

	<field
		name="rules"
		type="rules"
		label="JFIELD_RULES_LABEL"
		id="rules"
		translate_label="false"
		filter="rules"
		validate="rules"
		component="com_content"
		section="category"
	/>

	<fields name="params"
label="COM_CATEGORIES_FIELD_BASIC_LABEL">

		<fieldset name="basic">

			<field
				name="category_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				view="category"
				useglobal="true"
			/>

			<field
				name="image"
				type="media"
				label="COM_CATEGORIES_FIELD_IMAGE_LABEL"
				description="COM_CATEGORIES_FIELD_IMAGE_DESC"
			/>

			<field
				name="image_alt"
				type="text"
				label="COM_CATEGORIES_FIELD_IMAGE_ALT_LABEL"
				description="COM_CATEGORIES_FIELD_IMAGE_ALT_DESC"
				size="20"
			/>
		</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"
				description="JFIELD_METADATA_AUTHOR_DESC"
				size="30"
			/>

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<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>
models/forms/filter_categories.xml000064400000005663151164267220013411
0ustar00<?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="COM_CATEGORIES_FILTER_PUBLISHED"
			description="COM_CATEGORIES_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			mode="nested"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_TAG</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option
value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">

		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			default="a.lft ASC"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			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">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language_title
DESC">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="COM_CATEGORIES_LIST_LIMIT"
			description="COM_CATEGORIES_LIST_LIMIT_DESC"
			default="25"
			class="input-mini"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
tables/category.php000064400000001443151164267220010354 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Category table
 *
 * @since  1.6
 */
class CategoriesTableCategory extends JTableCategory
{
	/**
	 * Method to delete a node and, optionally, its child nodes from the
table.
	 *
	 * @param   integer  $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);
	}
}
views/categories/tmpl/default.php000064400000032110151164267220013142
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\String\Inflector;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$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;
$columns   = 7;

if (count($parts) > 1)
{
	$section = $parts[1];

	$inflector = Inflector::getInstance();

	if (!$inflector->isPlural($section))
	{
		$section = $inflector->toPlural($section);
	}
}

if ($saveOrder)
{
	$saveOrderingUrl =
'index.php?option=com_categories&task=categories.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'categoryList',
'adminForm', strtolower($listDirn), $saveOrderingUrl, false,
true);
}
?>
<form action="<?php echo
JRoute::_('index.php?option=com_categories&view=categories');
?>" method="post" name="adminForm"
id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<?php
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped"
id="categoryList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center
hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '',
'a.lft', $listDirn, $listOrder, null, 'asc',
'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort',
'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort',
'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder);
?>
						</th>
						<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_published')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone
hidden-tablet">
								<span class="icon-publish hasTooltip"
aria-hidden="true" title="<?php echo
JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS');
?>"><span class="element-invisible"><?php
echo JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS');
?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_unpublished')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone
hidden-tablet">
								<span class="icon-unpublish hasTooltip"
aria-hidden="true" title="<?php echo
JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS');
?>"><span class="element-invisible"><?php
echo JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS');
?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_archived')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone
hidden-tablet">
								<span class="icon-archive hasTooltip"
aria-hidden="true" title="<?php echo
JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS');
?>"><span class="element-invisible"><?php
echo JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS');
?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_trashed')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone
hidden-tablet">
								<span class="icon-trash hasTooltip"
aria-hidden="true" title="<?php echo
JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS');
?>"><span class="element-invisible"><?php
echo JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS');
?></span></span>
							</th>
						<?php endif; ?>
						<th width="10%" class="nowrap
hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ACCESS', 'access_level', $listDirn,
$listOrder); ?>
						</th>
						<?php if ($this->assoc) :
							$columns++; ?>
							<th width="5%" class="nowrap hidden-phone
hidden-tablet">
								<?php echo JHtml::_('searchtools.sort',
'COM_CATEGORY_HEADING_ASSOCIATION', 'association',
$listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<th width="10%" class="nowrap
hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_LANGUAGE', 'language_title', $listDirn,
$listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder);
?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="<?php echo $columns; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?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 ||
$item->checked_out == 0;
						$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; ?>"
sortable-group-id="<?php echo $item->parent_id; ?>"
item-id="<?php echo $item->id ?>" parents="<?php
echo $parentsStr ?>" level="<?php echo $item->level
?>">
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';
								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip"
title="' . JHtml::_('tooltipText',
'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler<?php echo $iconClass
?>">
									<span class="icon-menu"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none"
name="order[]" size="5" value="<?php echo
$item->lft; ?>" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id);
?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published',
$item->published, $i, 'categories.', $canChange); ?>
									<?php
									if ($canChange)
									{
										// Create dropdown items
										JHtml::_('actionsdropdown.' . ((int)
$item->published === 2 ? 'un' : '') .
'archive', 'cb' . $i, 'categories');
										JHtml::_('actionsdropdown.' . ((int)
$item->published === -2 ? 'un' : '') .
'trash', 'cb' . $i, 'categories');

										// Render dropdown list
										echo JHtml::_('actionsdropdown.render',
$this->escape($item->title));
									}
									?>
								</div>
							</td>
							<td>
								<?php echo
JLayoutHelper::render('joomla.html.treeprefix',
array('level' => $item->level)); ?>
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i,
$item->editor, $item->checked_out_time, 'categories.',
$canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit || $canEditOwn) : ?>
									<a class="hasTooltip" href="<?php echo
JRoute::_('index.php?option=com_categories&task=category.edit&id='
. $item->id . '&extension=' . $extension); ?>"
title="<?php echo JText::_('JACTION_EDIT');
?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->title); ?>
								<?php endif; ?>
								<span class="small" title="<?php echo
$this->escape($item->path); ?>">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS',
$this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE',
$this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
							</td>
							<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_published')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_published
> 0) echo 'badge-success'; ?>" title="<?php
echo JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?>"
href="<?php echo JRoute::_('index.php?option=' .
$component . ($section ? '&view=' . $section : '')
. '&filter[category_id]=' . (int) $item->id .
'&filter[published]=1' . '&filter[level]=1');
?>">
										<?php echo $item->count_published; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_unpublished')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_unpublished
> 0) echo 'badge-important'; ?>" title="<?php
echo JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS');
?>" href="<?php echo
JRoute::_('index.php?option=' . $component . ($section ?
'&view=' . $section : '') .
'&filter[category_id]=' . (int) $item->id .
'&filter[published]=0' . '&filter[level]=1');
?>">
										<?php echo $item->count_unpublished; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_archived')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_archived >
0) echo 'badge-info'; ?>" title="<?php echo
JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?>"
href="<?php echo JRoute::_('index.php?option=' .
$component . ($section ? '&view=' . $section : '')
. '&filter[category_id]=' . (int) $item->id .
'&filter[published]=2' . '&filter[level]=1');
?>">
										<?php echo $item->count_archived; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) &&
property_exists($this->items[0], 'count_trashed')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_trashed >
0) echo 'badge-inverse'; ?>" title="<?php echo
JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?>"
href="<?php echo JRoute::_('index.php?option=' .
$component . ($section ? '&view=' . $section : '')
. '&filter[category_id]=' . (int) $item->id .
'&filter[published]=-2' . '&filter[level]=1');
?>">
										<?php echo $item->count_trashed; ?></a>
								</td>
							<?php endif; ?>

							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<?php if ($this->assoc) : ?>
								<td class="hidden-phone hidden-tablet">
									<?php if ($item->association) : ?>
										<?php echo
JHtml::_('CategoriesAdministrator.association', $item->id,
$extension); ?>
									<?php endif; ?>
								</td>
							<?php endif; ?>
							<td class="small nowrap hidden-phone">
								<?php echo
JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="hidden-phone">
								<span title="<?php echo sprintf('%d-%d',
$item->lft, $item->rgt); ?>">
									<?php echo (int) $item->id; ?></span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', $extension)
				&& $user->authorise('core.edit', $extension)
				&& $user->authorise('core.edit.state',
$extension)) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  =>
JText::_('COM_CATEGORIES_BATCH_OPTIONS'),
						'footer' =>
$this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?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 JHtml::_('form.token'); ?>
	</div>
</form>
views/categories/tmpl/default.xml000064400000001065151164267220013160
0ustar00<?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>
	<fieldset name="request">
		<fields name="request">
			<field
				name="extension"
				type="componentscategory"
				label="COM_CATEGORIES_CHOOSE_COMPONENT_LABEL"
				description="COM_CATEGORIES_CHOOSE_COMPONENT_DESC"
				required="true"
			>
				<option
value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
			</field>
		</fields>
	</fieldset>
</metadata>
views/categories/tmpl/default_batch_body.php000064400000004432151164267220015326
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */
defined('_JEXEC') or die;

$options = array(
	JHtml::_('select.option', 'c',
JText::_('JLIB_HTML_BATCH_COPY')),
	JHtml::_('select.option', 'm',
JText::_('JLIB_HTML_BATCH_MOVE'))
);
$published = (int) $this->state->get('filter.published');
$extension =
$this->escape($this->state->get('filter.extension'));
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="span6">
				<div class="control-group">
					<label id="batch-choose-action-lbl"
for="batch-category-id" class="control-label">
						<?php echo JText::_('JLIB_HTML_BATCH_MENU_LABEL'); ?>
					</label>
					<div id="batch-choose-action" class="combo
controls">
						<select name="batch[category_id]"
id="batch-category-id">
							<option value=""><?php echo
JText::_('JLIB_HTML_BATCH_NO_CATEGORY') ?></option>
							<?php echo JHtml::_('select.options',
JHtml::_('category.categories', $extension,
array('filter.published' => $published))); ?>
						</select>
					</div>
				</div>
				<div id="batch-copy-move" class="control-group
radio">
					<?php echo JText::_('JLIB_HTML_BATCH_MOVE_QUESTION');
?>
					<?php echo JHtml::_('select.radiolist', $options,
'batch[move_copy]', '', 'value',
'text', 'm'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<div class="span6">
			<div class="control-group">
				<label id="flip-ordering-id-lbl"
for="flip-ordering-id" class="control-label">
					<?php echo
JText::_('JLIB_HTML_BATCH_FLIPORDERING_LABEL'); ?>
				</label>
				<?php echo JHtml::_('select.booleanlist',
'batch[flip_ordering]', array(), 0, 'JYES',
'JNO', 'flip-ordering-id'); ?>
			</div>
		</div>
	</div>
</div>

views/categories/tmpl/default_batch_footer.php000064400000001321151164267220015661
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn"
onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''"
data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success"
onclick="Joomla.submitbutton('category.batch');return
false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
views/categories/tmpl/modal.php000064400000012660151164267220012622
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or
die(JText::_('JINVALID_TOKEN'));
}

JLoader::register('ContentHelperRoute', JPATH_ROOT .
'/components/com_content/helpers/route.php');

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip',
array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover',
array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');

// Special case for the search field tooltip.
$searchFilterDesc =
$this->filterForm->getFieldAttribute('search',
'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search',
array('title' => JText::_($searchFilterDesc),
'placement' => 'bottom'));

$extension =
$this->escape($this->state->get('filter.extension'));
$function  = $app->input->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
JRoute::_('index.php?option=com_categories&view=categories&layout=modal&tmpl=component&function='
. $function . '&' . JSession::getFormToken() .
'=1'); ?>" method="post"
name="adminForm" id="adminForm">

		<?php echo
JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this)); ?>

		<div class="clearfix"></div>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped"
id="categoryList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort',
'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort',
'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder);
?>
						</th>
						<th width="10%" class="nowrap
hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ACCESS', 'access_level', $listDirn,
$listOrder); ?>
						</th>
						<th width="15%" class="nowrap
hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_LANGUAGE', 'language_title', $listDirn,
$listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder);
?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php
					$iconStates = array(
						-2 => 'icon-trash',
						0  => 'icon-unpublish',
						1  => 'icon-publish',
						2  => 'icon-archive',
					);
					?>
					<?php foreach ($this->items as $i => $item) : ?>
						<?php if ($item->language &&
JLanguageMultilang::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 (!JLanguageMultilang::isEnabled())
						{
							$lang = '';
						}
						?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="center">
								<span class="<?php echo
$iconStates[$this->escape($item->published)]; ?>"
aria-hidden="true"></span>
							</td>
							<td>
								<?php echo
JLayoutHelper::render('joomla.html.treeprefix',
array('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(ContentHelperRoute::getCategoryRoute($item->id,
$item->language)); ?>', '<?php echo
$this->escape($lang); ?>', null);">
									<?php echo $this->escape($item->title); ?></a>
								<span class="small" title="<?php echo
$this->escape($item->path); ?>">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS',
$this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE',
$this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
							</td>
							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<td class="small hidden-phone">
								<?php echo
JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="hidden-phone">
								<?php echo (int) $item->id; ?>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?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->input->get('forcedLanguage', '',
'CMD'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
views/categories/view.html.php000064400000020326151164267220012465
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories view class for the Category package.
 *
 * @since  1.6
 */
class CategoriesViewCategories extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Flag if an association exists
	 *
	 * @var  boolean
	 */
	protected $assoc;

	/**
	 * Form object for search filters
	 *
	 * @var  JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $string;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse;
automatically searches through the template paths.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 */
	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');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(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;
		}

		// Levels filter - Used in Hathor.
		$this->f_levels = array(
			JHtml::_('select.option', '1',
JText::_('J1')),
			JHtml::_('select.option', '2',
JText::_('J2')),
			JHtml::_('select.option', '3',
JText::_('J3')),
			JHtml::_('select.option', '4',
JText::_('J4')),
			JHtml::_('select.option', '5',
JText::_('J5')),
			JHtml::_('select.option', '6',
JText::_('J6')),
			JHtml::_('select.option', '7',
JText::_('J7')),
			JHtml::_('select.option', '8',
JText::_('J8')),
			JHtml::_('select.option', '9',
JText::_('J9')),
			JHtml::_('select.option', '10',
JText::_('J10')),
		);

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In article associations modal we need to remove language filter if
forcing a language.
			if ($forcedLanguage =
JFactory::getApplication()->input->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']);
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @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      = JHelperContent::getActions($component,
'category', $categoryId);
		$user       = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		// Avoid nonsense situation.
		if ($component == 'com_categories')
		{
			return;
		}

		// Need to load the menu language file as mod_menu hasn't been
loaded yet.
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_BASE, null, false, true)
		|| $lang->load($component, JPATH_ADMINISTRATOR .
'/components/' . $component, null, false, true);

		// Load the category helper.
		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/categories.php');

		// 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 = JText::_($component_title_key);
		}
		elseif ($lang->hasKey($component_section_key = strtoupper($component .
($section ? "_$section" : ''))))
		// Else if the component section string exits, let's use it
		{
			$title = JText::sprintf('COM_CATEGORIES_CATEGORIES_TITLE',
$this->escape(JText::_($component_section_key)));
		}
		else
		// Else use the base title
		{
			$title = JText::_('COM_CATEGORIES_CATEGORIES_BASE_TITLE');
		}

		// Load specific css component
		JHtml::_('stylesheet', $component .
'/administrator/categories.css', array('version' =>
'auto', 'relative' => true));

		// Prepare the toolbar.
		JToolbarHelper::title($title, 'folder categories ' .
substr($component, 4) . ($section ? "-$section" : '') .
'-categories');

		if ($canDo->get('core.create') ||
count($user->getAuthorisedCategories($component,
'core.create')) > 0)
		{
			JToolbarHelper::addNew('category.add');
		}

		if ($canDo->get('core.edit') ||
$canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('category.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('categories.publish',
'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('categories.unpublish',
'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('categories.archive');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::checkin('categories.checkin');
		}

		// Add a batch button
		if ($canDo->get('core.create')
			&& $canDo->get('core.edit')
			&& $canDo->get('core.edit.state'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::custom('categories.rebuild',
'refresh.png', 'refresh_f2.png',
'JTOOLBAR_REBUILD', false);
		}

		if ($canDo->get('core.admin') ||
$canDo->get('core.options'))
		{
			JToolbarHelper::preferences($component);
		}

		if ($this->state->get('filter.published') == -2
&& $canDo->get('core.delete', $component))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE',
'categories.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('categories.trash');
		}

		// Compute the ref_key if it does exist in the component
		if (!$lang->hasKey($ref_key = strtoupper($component . ($section ?
"_$section" : '')) . '_CATEGORIES_HELP_KEY'))
		{
			$ref_key = 'JHELP_COMPONENTS_' . strtoupper(substr($component,
4) . ($section ? "_$section" : '')) .
'_CATEGORIES';
		}

		/*
		 * Get help for the categories view for the component by
		 * -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 ($lang->hasKey($lang_help_url = strtoupper($component) .
'_HELP_URL'))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($lang_help_url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($ref_key,
JComponentHelper::getParams($component)->exists('helpURL'),
$url);
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key
and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.lft'       =>
JText::_('JGRID_HEADING_ORDERING'),
			'a.published' => JText::_('JSTATUS'),
			'a.title'     => JText::_('JGLOBAL_TITLE'),
			'a.access'    =>
JText::_('JGRID_HEADING_ACCESS'),
			'language'    =>
JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'        => JText::_('JGRID_HEADING_ID'),
		);
	}
}
views/category/tmpl/edit.php000064400000010227151164267220012140
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_tags', null,
array('placeholder_text_multiple' =>
JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');

$app = JFactory::getApplication();
$input = $app->input;

$assoc = JLanguageAssociations::isEnabled();
// Are associations implemented for this extension?
$extensionassoc = array_key_exists('item_associations',
$this->form->getFieldsets());

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "category.cancel" ||
document.formvalidator.isValid(document.getElementById("item-form")))
		{
			jQuery("#permissions-sliders
select").attr("disabled", "disabled");
			' . $this->form->getField('description')->save()
. '
			Joomla.submitform(task, document.getElementById("item-form"));

			// @deprecated 4.0  The following js is not needed since 3.7.0.
			if (task !== "category.apply")
			{
				window.parent.jQuery("#categoryEdit' . $this->item->id
. 'Modal").modal("hide");
			}
		}
	};
');

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('jmetadata',
'item_associations');

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true :
false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '',
'cmd') === 'component' ?
'&tmpl=component' : '';
?>

<form action="<?php echo
JRoute::_('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"
class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias',
$this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet',
'myTab', array('active' => 'general'));
?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab',
'general', JText::_('JCATEGORY')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php echo $this->form->getLabel('description');
?>
				<?php echo $this->form->getInput('description');
?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global',
$this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params',
$this); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab',
'publishing',
JText::_('COM_CATEGORIES_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo
JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.metadata',
$this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if ( ! $isModal && $assoc && $extensionassoc) :
?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab',
'associations',
JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
			<?php echo $this->loadTemplate('associations'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php elseif ($isModal && $assoc && $extensionassoc) :
?>
			<div class="hidden"><?php echo
$this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab',
'rules', JText::_('COM_CATEGORIES_FIELDSET_RULES'));
?>
			<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<?php echo $this->form->getInput('extension'); ?>
		<input type="hidden" name="task"
value="" />
		<input type="hidden" name="forcedLanguage"
value="<?php echo $input->get('forcedLanguage',
'', 'cmd'); ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
views/category/tmpl/edit.xml000064400000001154151164267220012150
0ustar00<?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"
				description="COM_CATEGORIES_CHOOSE_COMPONENT_DESC"
				required="true"
				>
				<option
value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
			</field>
			<field
				name="id"
				type="hidden"
				default="0"
			/>
		</fields>
	</fieldset>
</metadata>
views/category/tmpl/edit_associations.php000064400000000530151164267220014713
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
views/category/tmpl/edit_metadata.php000064400000000524151164267220013777
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
views/category/tmpl/modal.php000064400000002566151164267220012316
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip',
array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons
are not needed since 3.7.0.
$function  =
JFactory::getApplication()->input->getCmd('function',
'jEditCategory_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditCategoryModal() {
		if (window.parent &&
document.formvalidator.isValid(document.getElementById("item-form")))
{
			return window.parent.' . $this->escape($function) .
'(document.getElementById("jform_title").value);
		}
	}
');
?>
<button id="applyBtn" type="button"
class="hidden"
onclick="Joomla.submitbutton('category.apply');
jEditCategoryModal();"></button>
<button id="saveBtn" type="button"
class="hidden"
onclick="Joomla.submitbutton('category.save');
jEditCategoryModal();"></button>
<button id="closeBtn" type="button"
class="hidden"
onclick="Joomla.submitbutton('category.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
views/category/tmpl/modal_associations.php000064400000000530151164267220015062
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
views/category/tmpl/modal_extrafields.php000064400000000430151164267220014674
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;
views/category/tmpl/modal_metadata.php000064400000000524151164267220014146
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
views/category/tmpl/modal_options.php000064400000002747151164267220014072
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

echo JHtml::_('bootstrap.startAccordion',
'categoryOptions', array('active' =>
'collapse0'));
$fieldSets = $this->form->getFieldsets('params');
$i = 0;
?>
<?php foreach ($fieldSets as $name => $fieldSet) : ?>
	<?php
	$label = !empty($fieldSet->label) ? $fieldSet->label :
'COM_CATEGORIES_' . $name . '_FIELDSET_LABEL';
	echo JHtml::_('bootstrap.addSlide', 'categoryOptions',
JText::_($label), 'collapse' . ($i++));
	if (isset($fieldSet->description) &&
trim($fieldSet->description))
	{
		echo '<p class="tip">' .
$this->escape(JText::_($fieldSet->description)) .
'</p>';
	}
	?>
	<?php foreach ($this->form->getFieldset($name) as $field) : ?>
		<div class="control-group">
			<div class="control-label">
				<?php echo $field->label; ?>
			</div>
			<div class="controls">
				<?php echo $field->input; ?>
			</div>
		</div>
	<?php endforeach; ?>

	<?php if ($name == 'basic') : ?>
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('note'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('note'); ?>
			</div>
		</div>
	<?php endif; ?>
	<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php endforeach; ?>
<?php echo JHtml::_('bootstrap.endAccordion'); ?>
views/category/view.html.php000064400000017043151164267220012157
0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Categories component
 *
 * @since  1.6
 */
class CategoriesViewCategory extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Flag if an association exists
	 *
	 * @var  boolean
	 */
	protected $assoc;

	/**
	 * The actions the user is authorised to perform
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse;
automatically searches through the template paths.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 */
	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 =
JHelperContent::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 Exception(implode("\n", $errors), 500);
		}

		// Check for tag type
		$this->checkTags = JHelperTags::getTypes('objectList',
array($this->state->get('category.extension') .
'.category'), true);

		JFactory::getApplication()->input->set('hidemainmenu',
true);

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' &&
$forcedLanguage =
JFactory::getApplication()->input->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);
		}

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$extension =
JFactory::getApplication()->input->get('extension');
		$user = JFactory::getUser();
		$userId = $user->id;

		$isNew = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 ||
$this->item->checked_out == $userId);

		// Check to see if the type exists
		$ucmType = new JUcmType;
		$this->typeId = $ucmType->getTypeId($extension .
'.category');

		// 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 = JComponentHelper::getParams($component);

		// Need to load the menu language file as mod_menu hasn't been
loaded yet.
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_BASE, null, false, true)
		|| $lang->load($component, JPATH_ADMINISTRATOR .
'/components/' . $component, null, false, true);

		// Load the category helper.
		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR .
'/components/com_categories/helpers/categories.php');

		// 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 = JText::_($component_title_key);
		}
		// Else if the component section string exits, let's use it
		elseif ($lang->hasKey($component_section_key = $component . ($section
? "_$section" : '')))
		{
			$title = JText::sprintf('COM_CATEGORIES_CATEGORY_' . ($isNew ?
'ADD' : 'EDIT')
					. '_TITLE',
$this->escape(JText::_($component_section_key))
					);
		}
		// Else use the base title
		else
		{
			$title = JText::_('COM_CATEGORIES_CATEGORY_BASE_' . ($isNew ?
'ADD' : 'EDIT') . '_TITLE');
		}

		// Load specific css component
		JHtml::_('stylesheet', $component .
'/administrator/categories.css', array('version' =>
'auto', 'relative' => true));

		// Prepare the toolbar.
		JToolbarHelper::title(
			$title,
			'folder category-' . ($isNew ? 'add' :
'edit')
				. ' ' . substr($component, 4) . ($section ?
"-$section" : '') . '-category-' . ($isNew ?
'add' : 'edit')
		);

		// For new records, check the create permission.
		if ($isNew &&
(count($user->getAuthorisedCategories($component,
'core.create')) > 0))
		{
			JToolbarHelper::apply('category.apply');
			JToolbarHelper::save('category.save');
			JToolbarHelper::save2new('category.save2new');
			JToolbarHelper::cancel('category.cancel');
		}

		// If not checked out, can save the item.
		else
		{
			// 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)
			{
				JToolbarHelper::apply('category.apply');
				JToolbarHelper::save('category.save');

				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('category.save2new');
				}
			}

			// If an existing item, can save to a copy.
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('category.save2copy');
			}

			if (JComponentHelper::isEnabled('com_contenthistory')
&& $componentParams->get('save_history', 0) &&
$itemEditable)
			{
				$typeAlias = $extension . '.category';
				JToolbarHelper::versions($typeAlias, $this->item->id);
			}

			if (JLanguageAssociations::isEnabled() &&
JComponentHelper::isEnabled('com_associations'))
			{
				JToolbarHelper::custom('category.editAssociations',
'contract', 'contract',
'JTOOLBAR_ASSOCIATIONS', false, false);
			}

			JToolbarHelper::cancel('category.cancel',
'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();

		// Compute the ref_key
		$ref_key = strtoupper($component . ($section ? "_$section" :
'')) . '_CATEGORY_' . ($isNew ? 'ADD' :
'EDIT') . '_HELP_KEY';

		// Check if thr computed ref_key does exist in the component
		if (!$lang->hasKey($ref_key))
		{
			$ref_key = 'JHELP_COMPONENTS_'
						. strtoupper(substr($component, 4) . ($section ?
"_$section" : ''))
						. '_CATEGORY_' . ($isNew ? 'ADD' :
'EDIT');
		}

		/*
		 * Get help for the category/section view for the component by
		 * -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 ($lang->hasKey($lang_help_url = strtoupper($component) .
'_HELP_URL'))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($lang_help_url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($ref_key,
$componentParams->exists('helpURL'), $url, $component);
	}
}