[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Site 5 * @subpackage com_content 6 * 7 * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Content\Site\Model; 12 13 use Joomla\CMS\Categories\Categories; 14 use Joomla\CMS\Categories\CategoryNode; 15 use Joomla\CMS\Factory; 16 use Joomla\CMS\Language\Multilanguage; 17 use Joomla\CMS\MVC\Model\ListModel; 18 use Joomla\CMS\Table\Table; 19 use Joomla\Component\Content\Site\Helper\QueryHelper; 20 use Joomla\Registry\Registry; 21 use Joomla\Utilities\ArrayHelper; 22 23 // phpcs:disable PSR1.Files.SideEffects 24 \defined('_JEXEC') or die; 25 // phpcs:enable PSR1.Files.SideEffects 26 27 /** 28 * This models supports retrieving a category, the articles associated with the category, 29 * sibling, child and parent categories. 30 * 31 * @since 1.5 32 */ 33 class CategoryModel extends ListModel 34 { 35 /** 36 * Category items data 37 * 38 * @var array 39 */ 40 protected $_item = null; 41 42 /** 43 * Array of articles in the category 44 * 45 * @var \stdClass[] 46 */ 47 protected $_articles = null; 48 49 /** 50 * Category left and right of this one 51 * 52 * @var CategoryNode[]|null 53 */ 54 protected $_siblings = null; 55 56 /** 57 * Array of child-categories 58 * 59 * @var CategoryNode[]|null 60 */ 61 protected $_children = null; 62 63 /** 64 * Parent category of the current one 65 * 66 * @var CategoryNode|null 67 */ 68 protected $_parent = null; 69 70 /** 71 * Model context string. 72 * 73 * @var string 74 */ 75 protected $_context = 'com_content.category'; 76 77 /** 78 * The category that applies. 79 * 80 * @var object 81 */ 82 protected $_category = null; 83 84 /** 85 * The list of categories. 86 * 87 * @var array 88 */ 89 protected $_categories = null; 90 91 /** 92 * @param array $config An optional associative array of configuration settings. 93 * 94 * @since 1.6 95 */ 96 public function __construct($config = array()) 97 { 98 if (empty($config['filter_fields'])) { 99 $config['filter_fields'] = array( 100 'id', 'a.id', 101 'title', 'a.title', 102 'alias', 'a.alias', 103 'checked_out', 'a.checked_out', 104 'checked_out_time', 'a.checked_out_time', 105 'catid', 'a.catid', 'category_title', 106 'state', 'a.state', 107 'access', 'a.access', 'access_level', 108 'created', 'a.created', 109 'created_by', 'a.created_by', 110 'modified', 'a.modified', 111 'ordering', 'a.ordering', 112 'featured', 'a.featured', 113 'language', 'a.language', 114 'hits', 'a.hits', 115 'publish_up', 'a.publish_up', 116 'publish_down', 'a.publish_down', 117 'author', 'a.author', 118 'filter_tag' 119 ); 120 } 121 122 parent::__construct($config); 123 } 124 125 /** 126 * Method to auto-populate the model state. 127 * 128 * Note. Calling getState in this method will result in recursion. 129 * 130 * @param string $ordering The field to order on. 131 * @param string $direction The direction to order on. 132 * 133 * @return void 134 * 135 * @since 1.6 136 */ 137 protected function populateState($ordering = null, $direction = null) 138 { 139 $app = Factory::getApplication(); 140 $pk = $app->input->getInt('id'); 141 142 $this->setState('category.id', $pk); 143 144 // Load the parameters. Merge Global and Menu Item params into new object 145 $params = $app->getParams(); 146 147 if ($menu = $app->getMenu()->getActive()) { 148 $menuParams = $menu->getParams(); 149 } else { 150 $menuParams = new Registry(); 151 } 152 153 $mergedParams = clone $menuParams; 154 $mergedParams->merge($params); 155 156 $this->setState('params', $mergedParams); 157 $user = Factory::getUser(); 158 159 $asset = 'com_content'; 160 161 if ($pk) { 162 $asset .= '.category.' . $pk; 163 } 164 165 if ((!$user->authorise('core.edit.state', $asset)) && (!$user->authorise('core.edit', $asset))) { 166 // Limit to published for people who can't edit or edit.state. 167 $this->setState('filter.published', 1); 168 } else { 169 $this->setState('filter.published', [0, 1]); 170 } 171 172 // Process show_noauth parameter 173 if (!$params->get('show_noauth')) { 174 $this->setState('filter.access', true); 175 } else { 176 $this->setState('filter.access', false); 177 } 178 179 $itemid = $app->input->get('id', 0, 'int') . ':' . $app->input->get('Itemid', 0, 'int'); 180 181 $value = $this->getUserStateFromRequest('com_content.category.filter.' . $itemid . '.tag', 'filter_tag', 0, 'int', false); 182 $this->setState('filter.tag', $value); 183 184 // Optional filter text 185 $search = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter-search', 'filter-search', '', 'string'); 186 $this->setState('list.filter', $search); 187 188 // Filter.order 189 $orderCol = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order', 'filter_order', '', 'string'); 190 191 if (!in_array($orderCol, $this->filter_fields)) { 192 $orderCol = 'a.ordering'; 193 } 194 195 $this->setState('list.ordering', $orderCol); 196 197 $listOrder = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order_Dir', 'filter_order_Dir', '', 'cmd'); 198 199 if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', ''))) { 200 $listOrder = 'ASC'; 201 } 202 203 $this->setState('list.direction', $listOrder); 204 205 $this->setState('list.start', $app->input->get('limitstart', 0, 'uint')); 206 207 // Set limit for query. If list, use parameter. If blog, add blog parameters for limit. 208 if (($app->input->get('layout') === 'blog') || $params->get('layout_type') === 'blog') { 209 $limit = $params->get('num_leading_articles') + $params->get('num_intro_articles') + $params->get('num_links'); 210 $this->setState('list.links', $params->get('num_links')); 211 } else { 212 $limit = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.limit', 'limit', $params->get('display_num'), 'uint'); 213 } 214 215 $this->setState('list.limit', $limit); 216 217 // Set the depth of the category query based on parameter 218 $showSubcategories = $params->get('show_subcategory_content', '0'); 219 220 if ($showSubcategories) { 221 $this->setState('filter.max_category_levels', $params->get('show_subcategory_content', '1')); 222 $this->setState('filter.subcategories', true); 223 } 224 225 $this->setState('filter.language', Multilanguage::isEnabled()); 226 227 $this->setState('layout', $app->input->getString('layout')); 228 229 // Set the featured articles state 230 $this->setState('filter.featured', $params->get('show_featured')); 231 } 232 233 /** 234 * Get the articles in the category 235 * 236 * @return array|bool An array of articles or false if an error occurs. 237 * 238 * @since 1.5 239 */ 240 public function getItems() 241 { 242 $limit = $this->getState('list.limit'); 243 244 if ($this->_articles === null && $category = $this->getCategory()) { 245 $model = $this->bootComponent('com_content')->getMVCFactory() 246 ->createModel('Articles', 'Site', ['ignore_request' => true]); 247 $model->setState('params', Factory::getApplication()->getParams()); 248 $model->setState('filter.category_id', $category->id); 249 $model->setState('filter.published', $this->getState('filter.published')); 250 $model->setState('filter.access', $this->getState('filter.access')); 251 $model->setState('filter.language', $this->getState('filter.language')); 252 $model->setState('filter.featured', $this->getState('filter.featured')); 253 $model->setState('list.ordering', $this->_buildContentOrderBy()); 254 $model->setState('list.start', $this->getState('list.start')); 255 $model->setState('list.limit', $limit); 256 $model->setState('list.direction', $this->getState('list.direction')); 257 $model->setState('list.filter', $this->getState('list.filter')); 258 $model->setState('filter.tag', $this->getState('filter.tag')); 259 260 // Filter.subcategories indicates whether to include articles from subcategories in the list or blog 261 $model->setState('filter.subcategories', $this->getState('filter.subcategories')); 262 $model->setState('filter.max_category_levels', $this->getState('filter.max_category_levels')); 263 $model->setState('list.links', $this->getState('list.links')); 264 265 if ($limit >= 0) { 266 $this->_articles = $model->getItems(); 267 268 if ($this->_articles === false) { 269 $this->setError($model->getError()); 270 } 271 } else { 272 $this->_articles = array(); 273 } 274 275 $this->_pagination = $model->getPagination(); 276 } 277 278 return $this->_articles; 279 } 280 281 /** 282 * Build the orderby for the query 283 * 284 * @return string $orderby portion of query 285 * 286 * @since 1.5 287 */ 288 protected function _buildContentOrderBy() 289 { 290 $app = Factory::getApplication(); 291 $db = $this->getDatabase(); 292 $params = $this->state->params; 293 $itemid = $app->input->get('id', 0, 'int') . ':' . $app->input->get('Itemid', 0, 'int'); 294 $orderCol = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order', 'filter_order', '', 'string'); 295 $orderDirn = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order_Dir', 'filter_order_Dir', '', 'cmd'); 296 $orderby = ' '; 297 298 if (!in_array($orderCol, $this->filter_fields)) { 299 $orderCol = null; 300 } 301 302 if (!in_array(strtoupper($orderDirn), array('ASC', 'DESC', ''))) { 303 $orderDirn = 'ASC'; 304 } 305 306 if ($orderCol && $orderDirn) { 307 $orderby .= $db->escape($orderCol) . ' ' . $db->escape($orderDirn) . ', '; 308 } 309 310 $articleOrderby = $params->get('orderby_sec', 'rdate'); 311 $articleOrderDate = $params->get('order_date'); 312 $categoryOrderby = $params->def('orderby_pri', ''); 313 $secondary = QueryHelper::orderbySecondary($articleOrderby, $articleOrderDate, $this->getDatabase()) . ', '; 314 $primary = QueryHelper::orderbyPrimary($categoryOrderby); 315 316 $orderby .= $primary . ' ' . $secondary . ' a.created '; 317 318 return $orderby; 319 } 320 321 /** 322 * Method to get a JPagination object for the data set. 323 * 324 * @return \Joomla\CMS\Pagination\Pagination A JPagination object for the data set. 325 * 326 * @since 3.0.1 327 */ 328 public function getPagination() 329 { 330 if (empty($this->_pagination)) { 331 return null; 332 } 333 334 return $this->_pagination; 335 } 336 337 /** 338 * Method to get category data for the current category 339 * 340 * @return object 341 * 342 * @since 1.5 343 */ 344 public function getCategory() 345 { 346 if (!is_object($this->_item)) { 347 if (isset($this->state->params)) { 348 $params = $this->state->params; 349 $options = array(); 350 $options['countItems'] = $params->get('show_cat_num_articles', 1) || !$params->get('show_empty_categories_cat', 0); 351 $options['access'] = $params->get('check_access_rights', 1); 352 } else { 353 $options['countItems'] = 0; 354 } 355 356 $categories = Categories::getInstance('Content', $options); 357 $this->_item = $categories->get($this->getState('category.id', 'root')); 358 359 // Compute selected asset permissions. 360 if (is_object($this->_item)) { 361 $user = Factory::getUser(); 362 $asset = 'com_content.category.' . $this->_item->id; 363 364 // Check general create permission. 365 if ($user->authorise('core.create', $asset)) { 366 $this->_item->getParams()->set('access-create', true); 367 } 368 369 // @todo: Why aren't we lazy loading the children and siblings? 370 $this->_children = $this->_item->getChildren(); 371 $this->_parent = false; 372 373 if ($this->_item->getParent()) { 374 $this->_parent = $this->_item->getParent(); 375 } 376 377 $this->_rightsibling = $this->_item->getSibling(); 378 $this->_leftsibling = $this->_item->getSibling(false); 379 } else { 380 $this->_children = false; 381 $this->_parent = false; 382 } 383 } 384 385 return $this->_item; 386 } 387 388 /** 389 * Get the parent category. 390 * 391 * @return mixed An array of categories or false if an error occurs. 392 * 393 * @since 1.6 394 */ 395 public function getParent() 396 { 397 if (!is_object($this->_item)) { 398 $this->getCategory(); 399 } 400 401 return $this->_parent; 402 } 403 404 /** 405 * Get the left sibling (adjacent) categories. 406 * 407 * @return mixed An array of categories or false if an error occurs. 408 * 409 * @since 1.6 410 */ 411 public function &getLeftSibling() 412 { 413 if (!is_object($this->_item)) { 414 $this->getCategory(); 415 } 416 417 return $this->_leftsibling; 418 } 419 420 /** 421 * Get the right sibling (adjacent) categories. 422 * 423 * @return mixed An array of categories or false if an error occurs. 424 * 425 * @since 1.6 426 */ 427 public function &getRightSibling() 428 { 429 if (!is_object($this->_item)) { 430 $this->getCategory(); 431 } 432 433 return $this->_rightsibling; 434 } 435 436 /** 437 * Get the child categories. 438 * 439 * @return mixed An array of categories or false if an error occurs. 440 * 441 * @since 1.6 442 */ 443 public function &getChildren() 444 { 445 if (!is_object($this->_item)) { 446 $this->getCategory(); 447 } 448 449 // Order subcategories 450 if ($this->_children) { 451 $params = $this->getState()->get('params'); 452 453 $orderByPri = $params->get('orderby_pri'); 454 455 if ($orderByPri === 'alpha' || $orderByPri === 'ralpha') { 456 $this->_children = ArrayHelper::sortObjects($this->_children, 'title', ($orderByPri === 'alpha') ? 1 : (-1)); 457 } 458 } 459 460 return $this->_children; 461 } 462 463 /** 464 * Increment the hit counter for the category. 465 * 466 * @param int $pk Optional primary key of the category to increment. 467 * 468 * @return boolean True if successful; false otherwise and internal error set. 469 */ 470 public function hit($pk = 0) 471 { 472 $input = Factory::getApplication()->input; 473 $hitcount = $input->getInt('hitcount', 1); 474 475 if ($hitcount) { 476 $pk = (!empty($pk)) ? $pk : (int) $this->getState('category.id'); 477 478 $table = Table::getInstance('Category', 'JTable'); 479 $table->hit($pk); 480 } 481 482 return true; 483 } 484 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |