PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/home/administrator/components/com_categories/models/fields/categoryedit.php

https://bitbucket.org/rubbystar/carimod
PHP | 413 lines | 250 code | 51 blank | 112 comment | 82 complexity | b4b4c971a62fc8c849f21a873c8dd10f MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, GPL-3.0
  1. <?php
  2. /**
  3. * @package Joomla.Administrator
  4. * @subpackage com_categories
  5. *
  6. * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('JPATH_BASE') or die;
  10. use Joomla\Utilities\ArrayHelper;
  11. JFormHelper::loadFieldClass('list');
  12. /**
  13. * Form Field class for the Joomla Framework.
  14. *
  15. * @since 1.6
  16. */
  17. class JFormFieldCategoryEdit extends JFormFieldList
  18. {
  19. /**
  20. * To allow creation of new categories.
  21. *
  22. * @var integer
  23. * @since 3.6
  24. */
  25. protected $allowAdd;
  26. /**
  27. * A flexible category list that respects access controls
  28. *
  29. * @var string
  30. * @since 1.6
  31. */
  32. public $type = 'CategoryEdit';
  33. /**
  34. * Method to attach a JForm object to the field.
  35. *
  36. * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object.
  37. * @param mixed $value The form field value to validate.
  38. * @param string $group The field name group control value. This acts as as an array container for the field.
  39. * For example if the field has name="foo" and the group value is set to "bar" then the
  40. * full field name would end up being "bar[foo]".
  41. *
  42. * @return boolean True on success.
  43. *
  44. * @see JFormField::setup()
  45. * @since 3.2
  46. */
  47. public function setup(SimpleXMLElement $element, $value, $group = null)
  48. {
  49. $return = parent::setup($element, $value, $group);
  50. if ($return)
  51. {
  52. $this->allowAdd = isset($this->element['allowAdd']) ? $this->element['allowAdd'] : '';
  53. }
  54. return $return;
  55. }
  56. /**
  57. * Method to get certain otherwise inaccessible properties from the form field object.
  58. *
  59. * @param string $name The property name for which to the the value.
  60. *
  61. * @return mixed The property value or null.
  62. *
  63. * @since 3.6
  64. */
  65. public function __get($name)
  66. {
  67. switch ($name)
  68. {
  69. case 'allowAdd':
  70. return $this->$name;
  71. }
  72. return parent::__get($name);
  73. }
  74. /**
  75. * Method to set certain otherwise inaccessible properties of the form field object.
  76. *
  77. * @param string $name The property name for which to the the value.
  78. * @param mixed $value The value of the property.
  79. *
  80. * @return void
  81. *
  82. * @since 3.6
  83. */
  84. public function __set($name, $value)
  85. {
  86. $value = (string) $value;
  87. switch ($name)
  88. {
  89. case 'allowAdd':
  90. $value = (string) $value;
  91. $this->$name = ($value === 'true' || $value === $name || $value === '1');
  92. break;
  93. default:
  94. parent::__set($name, $value);
  95. }
  96. }
  97. /**
  98. * Method to get a list of categories that respects access controls and can be used for
  99. * either category assignment or parent category assignment in edit screens.
  100. * Use the parent element to indicate that the field will be used for assigning parent categories.
  101. *
  102. * @return array The field option objects.
  103. *
  104. * @since 1.6
  105. */
  106. protected function getOptions()
  107. {
  108. $options = array();
  109. $published = $this->element['published'] ? $this->element['published'] : array(0, 1);
  110. $name = (string) $this->element['name'];
  111. // Let's get the id for the current item, either category or content item.
  112. $jinput = JFactory::getApplication()->input;
  113. // Load the category options for a given extension.
  114. // For categories the old category is the category id or 0 for new category.
  115. if ($this->element['parent'] || $jinput->get('option') == 'com_categories')
  116. {
  117. $oldCat = $jinput->get('id', 0);
  118. $oldParent = $this->form->getValue($name, 0);
  119. $extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('extension', 'com_content');
  120. }
  121. else
  122. // For items the old category is the category they are in when opened or 0 if new.
  123. {
  124. $oldCat = $this->form->getValue($name, 0);
  125. $extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('option', 'com_content');
  126. }
  127. $db = JFactory::getDbo();
  128. $query = $db->getQuery(true)
  129. ->select('DISTINCT a.id AS value, a.title AS text, a.level, a.published, a.lft');
  130. $subQuery = $db->getQuery(true)
  131. ->select('id,title,level,published,parent_id,extension,lft,rgt')
  132. ->from('#__categories');
  133. // Filter by the extension type
  134. if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
  135. {
  136. $subQuery->where('(extension = ' . $db->quote($extension) . ' OR parent_id = 0)');
  137. }
  138. else
  139. {
  140. $subQuery->where('(extension = ' . $db->quote($extension) . ')');
  141. }
  142. // Filter language
  143. if (!empty($this->element['language']))
  144. {
  145. $subQuery->where('language = ' . $db->quote($this->element['language']));
  146. }
  147. // Filter on the published state
  148. if (is_numeric($published))
  149. {
  150. $subQuery->where('published = ' . (int) $published);
  151. }
  152. elseif (is_array($published))
  153. {
  154. $subQuery->where('published IN (' . implode(',', ArrayHelper::toInteger($published)) . ')');
  155. }
  156. $query->from('(' . (string) $subQuery . ') AS a')
  157. ->join('LEFT', $db->quoteName('#__categories') . ' AS b ON a.lft > b.lft AND a.rgt < b.rgt');
  158. $query->order('a.lft ASC');
  159. // If parent isn't explicitly stated but we are in com_categories assume we want parents
  160. if ($oldCat != 0 && ($this->element['parent'] == true || $jinput->get('option') == 'com_categories'))
  161. {
  162. // Prevent parenting to children of this item.
  163. // To rearrange parents and children move the children up, not the parents down.
  164. $query->join('LEFT', $db->quoteName('#__categories') . ' AS p ON p.id = ' . (int) $oldCat)
  165. ->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');
  166. $rowQuery = $db->getQuery(true);
  167. $rowQuery->select('a.id AS value, a.title AS text, a.level, a.parent_id')
  168. ->from('#__categories AS a')
  169. ->where('a.id = ' . (int) $oldCat);
  170. $db->setQuery($rowQuery);
  171. $row = $db->loadObject();
  172. }
  173. // Get the options.
  174. $db->setQuery($query);
  175. try
  176. {
  177. $options = $db->loadObjectList();
  178. }
  179. catch (RuntimeException $e)
  180. {
  181. JError::raiseWarning(500, $e->getMessage());
  182. }
  183. // Pad the option text with spaces using depth level as a multiplier.
  184. for ($i = 0, $n = count($options); $i < $n; $i++)
  185. {
  186. // Translate ROOT
  187. if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
  188. {
  189. if ($options[$i]->level == 0)
  190. {
  191. $options[$i]->text = JText::_('JGLOBAL_ROOT_PARENT');
  192. }
  193. }
  194. // Displays language code if not set to All
  195. $db = JFactory::getDbo();
  196. $query = $db->getQuery(true)
  197. ->select($db->quoteName('language'))
  198. ->where($db->quoteName('id') . '=' . (int) $options[$i]->value)
  199. ->from($db->quoteName('#__categories'));
  200. $db->setQuery($query);
  201. $language = $db->loadResult();
  202. if ($options[$i]->published == 1)
  203. {
  204. $options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->text;
  205. }
  206. else
  207. {
  208. $options[$i]->text = str_repeat('- ', $options[$i]->level) . '[' . $options[$i]->text . ']';
  209. }
  210. if ($language !== '*')
  211. {
  212. $options[$i]->text = $options[$i]->text . ' (' . $language . ')';
  213. }
  214. }
  215. // Get the current user object.
  216. $user = JFactory::getUser();
  217. // For new items we want a list of categories you are allowed to create in.
  218. if ($oldCat == 0)
  219. {
  220. foreach ($options as $i => $option)
  221. {
  222. /*
  223. * 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.
  224. * Unset the option if the user isn't authorised for it. In this field assets are always categories.
  225. */
  226. if ($user->authorise('core.create', $extension . '.category.' . $option->value) != true && $option->level != 0)
  227. {
  228. unset($options[$i]);
  229. }
  230. }
  231. }
  232. // If you have an existing category id things are more complex.
  233. else
  234. {
  235. /*
  236. * If you are only allowed to edit in this category but not edit.state, you should not get any
  237. * option to change the category parent for a category or the category for a content item,
  238. * but you should be able to save in that category.
  239. */
  240. foreach ($options as $i => $option)
  241. {
  242. if ($user->authorise('core.edit.state', $extension . '.category.' . $oldCat) != true && !isset($oldParent))
  243. {
  244. if ($option->value != $oldCat)
  245. {
  246. unset($options[$i]);
  247. }
  248. }
  249. if ($user->authorise('core.edit.state', $extension . '.category.' . $oldCat) != true
  250. && (isset($oldParent))
  251. && $option->value != $oldParent)
  252. {
  253. unset($options[$i]);
  254. }
  255. /*
  256. * However, if you can edit.state you can also move this to another category for which you have
  257. * create permission and you should also still be able to save in the current category.
  258. */
  259. if (($user->authorise('core.create', $extension . '.category.' . $option->value) != true)
  260. && ($option->value != $oldCat && !isset($oldParent)))
  261. {
  262. {
  263. unset($options[$i]);
  264. }
  265. }
  266. if (($user->authorise('core.create', $extension . '.category.' . $option->value) != true)
  267. && (isset($oldParent))
  268. && $option->value != $oldParent)
  269. {
  270. {
  271. unset($options[$i]);
  272. }
  273. }
  274. }
  275. }
  276. if (($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
  277. && (isset($row) && !isset($options[0]))
  278. && isset($this->element['show_root']))
  279. {
  280. if ($row->parent_id == '1')
  281. {
  282. $parent = new stdClass;
  283. $parent->text = JText::_('JGLOBAL_ROOT_PARENT');
  284. array_unshift($options, $parent);
  285. }
  286. array_unshift($options, JHtml::_('select.option', '0', JText::_('JGLOBAL_ROOT')));
  287. }
  288. // Merge any additional options in the XML definition.
  289. return array_merge(parent::getOptions(), $options);
  290. }
  291. /**
  292. * Method to get the field input markup for a generic list.
  293. * Use the multiple attribute to enable multiselect.
  294. *
  295. * @return string The field input markup.
  296. *
  297. * @since 3.6
  298. */
  299. protected function getInput()
  300. {
  301. $html = array();
  302. $class = array();
  303. $attr = '';
  304. // Initialize some field attributes.
  305. $class[] = !empty($this->class) ? $this->class : '';
  306. if ($this->allowAdd)
  307. {
  308. $customGroupText = JText::_('JGLOBAL_CUSTOM_CATEGORY');
  309. $class[] = 'chzn-custom-value';
  310. $attr .= ' data-custom_group_text="' . $customGroupText . '" '
  311. . 'data-no_results_text="' . JText::_('JGLOBAL_ADD_CUSTOM_CATEGORY') . '" '
  312. . 'data-placeholder="' . JText::_('JGLOBAL_TYPE_OR_SELECT_CATEGORY') . '" ';
  313. }
  314. if ($class)
  315. {
  316. $attr .= 'class="' . implode(' ', $class) . '"';
  317. }
  318. $attr .= !empty($this->size) ? ' size="' . $this->size . '"' : '';
  319. $attr .= $this->multiple ? ' multiple' : '';
  320. $attr .= $this->required ? ' required aria-required="true"' : '';
  321. $attr .= $this->autofocus ? ' autofocus' : '';
  322. // To avoid user's confusion, readonly="true" should imply disabled="true".
  323. if ((string) $this->readonly == '1'
  324. || (string) $this->readonly == 'true'
  325. || (string) $this->disabled == '1'
  326. || (string) $this->disabled == 'true')
  327. {
  328. $attr .= ' disabled="disabled"';
  329. }
  330. // Initialize JavaScript field attributes.
  331. $attr .= $this->onchange ? ' onchange="' . $this->onchange . '"' : '';
  332. // Get the field options.
  333. $options = (array) $this->getOptions();
  334. // Create a read-only list (no name) with hidden input(s) to store the value(s).
  335. if ((string) $this->readonly == '1' || (string) $this->readonly == 'true')
  336. {
  337. $html[] = JHtml::_('select.genericlist', $options, '', trim($attr), 'value', 'text', $this->value, $this->id);
  338. // E.g. form field type tag sends $this->value as array
  339. if ($this->multiple && is_array($this->value))
  340. {
  341. if (!count($this->value))
  342. {
  343. $this->value[] = '';
  344. }
  345. foreach ($this->value as $value)
  346. {
  347. $html[] = '<input type="hidden" name="' . $this->name . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"/>';
  348. }
  349. }
  350. else
  351. {
  352. $html[] = '<input type="hidden" name="' . $this->name . '" value="' . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"/>';
  353. }
  354. }
  355. else
  356. // Create a regular list.
  357. {
  358. $html[] = JHtml::_('select.genericlist', $options, $this->name, trim($attr), 'value', 'text', $this->value, $this->id);
  359. }
  360. return implode($html);
  361. }
  362. }