[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_finder 6 * 7 * @copyright (C) 2011 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\Finder\Administrator\Model; 12 13 use Joomla\CMS\Component\ComponentHelper; 14 use Joomla\CMS\Factory; 15 use Joomla\CMS\Language\Text; 16 use Joomla\CMS\MVC\Factory\MVCFactoryInterface; 17 use Joomla\CMS\MVC\Model\ListModel; 18 use Joomla\CMS\Plugin\PluginHelper; 19 20 // phpcs:disable PSR1.Files.SideEffects 21 \defined('_JEXEC') or die; 22 // phpcs:enable PSR1.Files.SideEffects 23 24 /** 25 * Index model class for Finder. 26 * 27 * @since 2.5 28 */ 29 class IndexModel extends ListModel 30 { 31 /** 32 * The event to trigger after deleting the data. 33 * 34 * @var string 35 * @since 2.5 36 */ 37 protected $event_after_delete = 'onContentAfterDelete'; 38 39 /** 40 * The event to trigger before deleting the data. 41 * 42 * @var string 43 * @since 2.5 44 */ 45 protected $event_before_delete = 'onContentBeforeDelete'; 46 47 /** 48 * The event to trigger after purging the data. 49 * 50 * @var string 51 * @since 4.0.0 52 */ 53 protected $event_after_purge = 'onFinderIndexAfterPurge'; 54 55 /** 56 * Constructor. 57 * 58 * @param array $config An optional associative array of configuration settings. 59 * @param MVCFactoryInterface $factory The factory. 60 * 61 * @see \Joomla\CMS\MVC\Model\BaseDatabaseModel 62 * @since 3.7 63 */ 64 public function __construct($config = array(), MVCFactoryInterface $factory = null) 65 { 66 if (empty($config['filter_fields'])) { 67 $config['filter_fields'] = array( 68 'state', 'published', 'l.published', 69 'title', 'l.title', 70 'type', 'type_id', 'l.type_id', 71 't.title', 't_title', 72 'url', 'l.url', 73 'language', 'l.language', 74 'indexdate', 'l.indexdate', 75 'content_map', 76 ); 77 } 78 79 parent::__construct($config, $factory); 80 } 81 82 /** 83 * Method to test whether a record can be deleted. 84 * 85 * @param object $record A record object. 86 * 87 * @return boolean True if allowed to delete the record. Defaults to the permission for the component. 88 * 89 * @since 2.5 90 */ 91 protected function canDelete($record) 92 { 93 return Factory::getUser()->authorise('core.delete', $this->option); 94 } 95 96 /** 97 * Method to test whether a record can have its state changed. 98 * 99 * @param object $record A record object. 100 * 101 * @return boolean True if allowed to change the state of the record. Defaults to the permission for the component. 102 * 103 * @since 2.5 104 */ 105 protected function canEditState($record) 106 { 107 return Factory::getUser()->authorise('core.edit.state', $this->option); 108 } 109 110 /** 111 * Method to delete one or more records. 112 * 113 * @param array $pks An array of record primary keys. 114 * 115 * @return boolean True if successful, false if an error occurs. 116 * 117 * @since 2.5 118 */ 119 public function delete(&$pks) 120 { 121 $pks = (array) $pks; 122 $table = $this->getTable(); 123 124 // Include the content plugins for the on delete events. 125 PluginHelper::importPlugin('content'); 126 127 // Iterate the items to delete each one. 128 foreach ($pks as $i => $pk) { 129 if ($table->load($pk)) { 130 if ($this->canDelete($table)) { 131 $context = $this->option . '.' . $this->name; 132 133 // Trigger the onContentBeforeDelete event. 134 $result = Factory::getApplication()->triggerEvent($this->event_before_delete, array($context, $table)); 135 136 if (in_array(false, $result, true)) { 137 $this->setError($table->getError()); 138 139 return false; 140 } 141 142 if (!$table->delete($pk)) { 143 $this->setError($table->getError()); 144 145 return false; 146 } 147 148 // Trigger the onContentAfterDelete event. 149 Factory::getApplication()->triggerEvent($this->event_after_delete, array($context, $table)); 150 } else { 151 // Prune items that you can't change. 152 unset($pks[$i]); 153 $error = $this->getError(); 154 155 if ($error) { 156 $this->setError($error); 157 } else { 158 $this->setError(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); 159 } 160 } 161 } else { 162 $this->setError($table->getError()); 163 164 return false; 165 } 166 } 167 168 // Clear the component's cache 169 $this->cleanCache(); 170 171 return true; 172 } 173 174 /** 175 * Build an SQL query to load the list data. 176 * 177 * @return \Joomla\Database\DatabaseQuery 178 * 179 * @since 2.5 180 */ 181 protected function getListQuery() 182 { 183 $db = $this->getDatabase(); 184 $query = $db->getQuery(true) 185 ->select('l.*') 186 ->select($db->quoteName('t.title', 't_title')) 187 ->from($db->quoteName('#__finder_links', 'l')) 188 ->join('INNER', $db->quoteName('#__finder_types', 't') . ' ON ' . $db->quoteName('t.id') . ' = ' . $db->quoteName('l.type_id')); 189 190 // Check the type filter. 191 $type = $this->getState('filter.type'); 192 193 // Join over the language 194 $query->select('la.title AS language_title, la.image AS language_image') 195 ->join('LEFT', $db->quoteName('#__languages') . ' AS la ON la.lang_code = l.language'); 196 197 if (is_numeric($type)) { 198 $query->where($db->quoteName('l.type_id') . ' = ' . (int) $type); 199 } 200 201 // Check the map filter. 202 $contentMapId = $this->getState('filter.content_map'); 203 204 if (is_numeric($contentMapId)) { 205 $query->join('INNER', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.link_id') . ' = ' . $db->quoteName('l.link_id')) 206 ->where($db->quoteName('m.node_id') . ' = ' . (int) $contentMapId); 207 } 208 209 // Check for state filter. 210 $state = $this->getState('filter.state'); 211 212 if (is_numeric($state)) { 213 $query->where($db->quoteName('l.published') . ' = ' . (int) $state); 214 } 215 216 // Filter on the language. 217 if ($language = $this->getState('filter.language')) { 218 $query->where($db->quoteName('l.language') . ' = ' . $db->quote($language)); 219 } 220 221 // Check the search phrase. 222 $search = $this->getState('filter.search'); 223 224 if (!empty($search)) { 225 $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); 226 $orSearchSql = $db->quoteName('l.title') . ' LIKE ' . $search . ' OR ' . $db->quoteName('l.url') . ' LIKE ' . $search; 227 228 // Filter by indexdate only if $search doesn't contains non-ascii characters 229 if (!preg_match('/[^\x00-\x7F]/', $search)) { 230 $orSearchSql .= ' OR ' . $query->castAsChar($db->quoteName('l.indexdate')) . ' LIKE ' . $search; 231 } 232 233 $query->where('(' . $orSearchSql . ')'); 234 } 235 236 // Handle the list ordering. 237 $listOrder = $this->getState('list.ordering', 'l.title'); 238 $listDir = $this->getState('list.direction', 'ASC'); 239 240 if ($listOrder === 't.title') { 241 $ordering = $db->quoteName('t.title') . ' ' . $db->escape($listDir) . ', ' . $db->quoteName('l.title') . ' ' . $db->escape($listDir); 242 } else { 243 $ordering = $db->escape($listOrder) . ' ' . $db->escape($listDir); 244 } 245 246 $query->order($ordering); 247 248 return $query; 249 } 250 251 /** 252 * Method to get the state of the Smart Search Plugins. 253 * 254 * @return array Array of relevant plugins and whether they are enabled or not. 255 * 256 * @since 2.5 257 */ 258 public function getPluginState() 259 { 260 $db = $this->getDatabase(); 261 $query = $db->getQuery(true) 262 ->select('name, enabled') 263 ->from($db->quoteName('#__extensions')) 264 ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) 265 ->where($db->quoteName('folder') . ' IN (' . $db->quote('system') . ',' . $db->quote('content') . ')') 266 ->where($db->quoteName('element') . ' = ' . $db->quote('finder')); 267 $db->setQuery($query); 268 269 return $db->loadObjectList('name'); 270 } 271 272 /** 273 * Method to get a store id based on model configuration state. 274 * 275 * This is necessary because the model is used by the component and 276 * different modules that might need different sets of data or different 277 * ordering requirements. 278 * 279 * @param string $id A prefix for the store id. [optional] 280 * 281 * @return string A store id. 282 * 283 * @since 2.5 284 */ 285 protected function getStoreId($id = '') 286 { 287 // Compile the store id. 288 $id .= ':' . $this->getState('filter.search'); 289 $id .= ':' . $this->getState('filter.state'); 290 $id .= ':' . $this->getState('filter.type'); 291 $id .= ':' . $this->getState('filter.content_map'); 292 293 return parent::getStoreId($id); 294 } 295 296 /** 297 * Gets the total of indexed items. 298 * 299 * @return integer The total of indexed items. 300 * 301 * @since 3.6.0 302 */ 303 public function getTotalIndexed() 304 { 305 $db = $this->getDatabase(); 306 $query = $db->getQuery(true) 307 ->select('COUNT(link_id)') 308 ->from($db->quoteName('#__finder_links')); 309 $db->setQuery($query); 310 311 return (int) $db->loadResult(); 312 } 313 314 /** 315 * Returns a Table object, always creating it. 316 * 317 * @param string $type The table type to instantiate. [optional] 318 * @param string $prefix A prefix for the table class name. [optional] 319 * @param array $config Configuration array for model. [optional] 320 * 321 * @return \Joomla\CMS\Table\Table A database object 322 * 323 * @since 2.5 324 */ 325 public function getTable($type = 'Link', $prefix = 'Administrator', $config = array()) 326 { 327 return parent::getTable($type, $prefix, $config); 328 } 329 330 /** 331 * Method to purge the index, deleting all links. 332 * 333 * @return boolean True on success, false on failure. 334 * 335 * @since 2.5 336 * @throws \Exception on database error 337 */ 338 public function purge() 339 { 340 $db = $this->getDatabase(); 341 342 // Truncate the links table. 343 $db->truncateTable('#__finder_links'); 344 345 // Truncate the links terms tables. 346 $db->truncateTable('#__finder_links_terms'); 347 348 // Truncate the terms table. 349 $db->truncateTable('#__finder_terms'); 350 351 // Truncate the taxonomy map table. 352 $db->truncateTable('#__finder_taxonomy_map'); 353 354 // Truncate the taxonomy table and insert the root node. 355 $db->truncateTable('#__finder_taxonomy'); 356 $root = (object) array( 357 'id' => 1, 358 'parent_id' => 0, 359 'lft' => 0, 360 'rgt' => 1, 361 'level' => 0, 362 'path' => '', 363 'title' => 'ROOT', 364 'alias' => 'root', 365 'state' => 1, 366 'access' => 1, 367 'language' => '*' 368 ); 369 $db->insertObject('#__finder_taxonomy', $root); 370 371 // Truncate the tokens tables. 372 $db->truncateTable('#__finder_tokens'); 373 374 // Truncate the tokens aggregate table. 375 $db->truncateTable('#__finder_tokens_aggregate'); 376 377 // Include the finder plugins for the on purge events. 378 PluginHelper::importPlugin('finder'); 379 Factory::getApplication()->triggerEvent($this->event_after_purge); 380 381 return true; 382 } 383 384 /** 385 * Method to auto-populate the model state. Calling getState in this method will result in recursion. 386 * 387 * @param string $ordering An optional ordering field. [optional] 388 * @param string $direction An optional direction. [optional] 389 * 390 * @return void 391 * 392 * @since 2.5 393 */ 394 protected function populateState($ordering = 'l.title', $direction = 'asc') 395 { 396 // Load the filter state. 397 $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); 398 $this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd')); 399 $this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'cmd')); 400 $this->setState('filter.content_map', $this->getUserStateFromRequest($this->context . '.filter.content_map', 'filter_content_map', '', 'cmd')); 401 $this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '')); 402 403 // Load the parameters. 404 $params = ComponentHelper::getParams('com_finder'); 405 $this->setState('params', $params); 406 407 // List state information. 408 parent::populateState($ordering, $direction); 409 } 410 411 /** 412 * Method to change the published state of one or more records. 413 * 414 * @param array $pks A list of the primary keys to change. 415 * @param integer $value The value of the published state. [optional] 416 * 417 * @return boolean True on success. 418 * 419 * @since 2.5 420 */ 421 public function publish(&$pks, $value = 1) 422 { 423 $user = Factory::getUser(); 424 $table = $this->getTable(); 425 $pks = (array) $pks; 426 427 // Include the content plugins for the change of state event. 428 PluginHelper::importPlugin('content'); 429 430 // Access checks. 431 foreach ($pks as $i => $pk) { 432 $table->reset(); 433 434 if ($table->load($pk) && !$this->canEditState($table)) { 435 // Prune items that you can't change. 436 unset($pks[$i]); 437 $this->setError(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); 438 439 return false; 440 } 441 } 442 443 // Attempt to change the state of the records. 444 if (!$table->publish($pks, $value, $user->get('id'))) { 445 $this->setError($table->getError()); 446 447 return false; 448 } 449 450 $context = $this->option . '.' . $this->name; 451 452 // Trigger the onContentChangeState event. 453 $result = Factory::getApplication()->triggerEvent('onContentChangeState', array($context, $pks, $value)); 454 455 if (in_array(false, $result, true)) { 456 $this->setError($table->getError()); 457 458 return false; 459 } 460 461 // Clear the component's cache 462 $this->cleanCache(); 463 464 return true; 465 } 466 }
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 |