[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\MVC\Model; 11 12 use Joomla\CMS\Cache\CacheControllerFactoryAwareInterface; 13 use Joomla\CMS\Cache\CacheControllerFactoryAwareTrait; 14 use Joomla\CMS\Cache\Controller\CallbackController; 15 use Joomla\CMS\Cache\Exception\CacheExceptionInterface; 16 use Joomla\CMS\Component\ComponentHelper; 17 use Joomla\CMS\Extension\ComponentInterface; 18 use Joomla\CMS\Factory; 19 use Joomla\CMS\Language\Text; 20 use Joomla\CMS\MVC\Factory\LegacyFactory; 21 use Joomla\CMS\MVC\Factory\MVCFactoryAwareTrait; 22 use Joomla\CMS\MVC\Factory\MVCFactoryInterface; 23 use Joomla\CMS\MVC\Factory\MVCFactoryServiceInterface; 24 use Joomla\CMS\Table\Table; 25 use Joomla\CMS\User\CurrentUserInterface; 26 use Joomla\CMS\User\CurrentUserTrait; 27 use Joomla\Database\DatabaseAwareInterface; 28 use Joomla\Database\DatabaseAwareTrait; 29 use Joomla\Database\DatabaseInterface; 30 use Joomla\Database\DatabaseQuery; 31 use Joomla\Database\Exception\DatabaseNotFoundException; 32 use Joomla\Event\DispatcherAwareInterface; 33 use Joomla\Event\DispatcherAwareTrait; 34 use Joomla\Event\DispatcherInterface; 35 use Joomla\Event\Event; 36 use Joomla\Event\EventInterface; 37 38 // phpcs:disable PSR1.Files.SideEffects 39 \defined('JPATH_PLATFORM') or die; 40 // phpcs:enable PSR1.Files.SideEffects 41 42 /** 43 * Base class for a database aware Joomla Model 44 * 45 * Acts as a Factory class for application specific objects and provides many supporting API functions. 46 * 47 * @since 2.5.5 48 */ 49 abstract class BaseDatabaseModel extends BaseModel implements 50 DatabaseModelInterface, 51 DispatcherAwareInterface, 52 CurrentUserInterface, 53 CacheControllerFactoryAwareInterface, 54 DatabaseAwareInterface 55 { 56 use DatabaseAwareTrait; 57 use MVCFactoryAwareTrait; 58 use DispatcherAwareTrait; 59 use CurrentUserTrait; 60 use CacheControllerFactoryAwareTrait; 61 62 /** 63 * The URL option for the component. 64 * 65 * @var string 66 * @since 3.0 67 */ 68 protected $option = null; 69 70 /** 71 * The event to trigger when cleaning cache. 72 * 73 * @var string 74 * @since 3.0 75 */ 76 protected $event_clean_cache = null; 77 78 /** 79 * Constructor 80 * 81 * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). 82 * @param MVCFactoryInterface $factory The factory. 83 * 84 * @since 3.0 85 * @throws \Exception 86 */ 87 public function __construct($config = array(), MVCFactoryInterface $factory = null) 88 { 89 parent::__construct($config); 90 91 // Guess the option from the class name (Option)Model(View). 92 if (empty($this->option)) { 93 $r = null; 94 95 if (!preg_match('/(.*)Model/i', \get_class($this), $r)) { 96 throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_GET_NAME', __METHOD__), 500); 97 } 98 99 $this->option = ComponentHelper::getComponentName($this, $r[1]); 100 } 101 102 /** 103 * @deprecated 5.0 Database instance is injected through the setter function, 104 * subclasses should not use the db instance in constructor anymore 105 */ 106 $db = \array_key_exists('dbo', $config) ? $config['dbo'] : Factory::getDbo(); 107 108 if ($db) { 109 @trigger_error(sprintf('Database is not available in constructor in 5.0.'), E_USER_DEPRECATED); 110 $this->setDatabase($db); 111 112 // Is needed, when models use the deprecated MVC DatabaseAwareTrait, as the trait is overriding the local functions 113 $this->setDbo($db); 114 } 115 116 // Set the default view search path 117 if (\array_key_exists('table_path', $config)) { 118 $this->addTablePath($config['table_path']); 119 } elseif (\defined('JPATH_COMPONENT_ADMINISTRATOR')) { 120 $this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables'); 121 $this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR . '/table'); 122 } 123 124 // Set the clean cache event 125 if (isset($config['event_clean_cache'])) { 126 $this->event_clean_cache = $config['event_clean_cache']; 127 } elseif (empty($this->event_clean_cache)) { 128 $this->event_clean_cache = 'onContentCleanCache'; 129 } 130 131 if ($factory) { 132 $this->setMVCFactory($factory); 133 134 return; 135 } 136 137 $component = Factory::getApplication()->bootComponent($this->option); 138 139 if ($component instanceof MVCFactoryServiceInterface) { 140 $this->setMVCFactory($component->getMVCFactory()); 141 } 142 } 143 144 /** 145 * Gets an array of objects from the results of database query. 146 * 147 * @param string $query The query. 148 * @param integer $limitstart Offset. 149 * @param integer $limit The number of records. 150 * 151 * @return object[] An array of results. 152 * 153 * @since 3.0 154 * @throws \RuntimeException 155 */ 156 protected function _getList($query, $limitstart = 0, $limit = 0) 157 { 158 if (\is_string($query)) { 159 $query = $this->getDbo()->getQuery(true)->setQuery($query); 160 } 161 162 $query->setLimit($limit, $limitstart); 163 $this->getDbo()->setQuery($query); 164 165 return $this->getDbo()->loadObjectList(); 166 } 167 168 /** 169 * Returns a record count for the query. 170 * 171 * Note: Current implementation of this method assumes that getListQuery() returns a set of unique rows, 172 * thus it uses SELECT COUNT(*) to count the rows. In cases that getListQuery() uses DISTINCT 173 * then either this method must be overridden by a custom implementation at the derived Model Class 174 * or a GROUP BY clause should be used to make the set unique. 175 * 176 * @param DatabaseQuery|string $query The query. 177 * 178 * @return integer Number of rows for query. 179 * 180 * @since 3.0 181 */ 182 protected function _getListCount($query) 183 { 184 // Use fast COUNT(*) on DatabaseQuery objects if there is no GROUP BY or HAVING clause: 185 if ( 186 $query instanceof DatabaseQuery 187 && $query->type === 'select' 188 && $query->group === null 189 && $query->merge === null 190 && $query->querySet === null 191 && $query->having === null 192 ) { 193 $query = clone $query; 194 $query->clear('select')->clear('order')->clear('limit')->clear('offset')->select('COUNT(*)'); 195 196 $this->getDbo()->setQuery($query); 197 198 return (int) $this->getDbo()->loadResult(); 199 } 200 201 // Otherwise fall back to inefficient way of counting all results. 202 203 // Remove the limit, offset and order parts if it's a DatabaseQuery object 204 if ($query instanceof DatabaseQuery) { 205 $query = clone $query; 206 $query->clear('limit')->clear('offset')->clear('order'); 207 } 208 209 $this->getDbo()->setQuery($query); 210 $this->getDbo()->execute(); 211 212 return (int) $this->getDbo()->getNumRows(); 213 } 214 215 /** 216 * Method to load and return a table object. 217 * 218 * @param string $name The name of the view 219 * @param string $prefix The class prefix. Optional. 220 * @param array $config Configuration settings to pass to Table::getInstance 221 * 222 * @return Table|boolean Table object or boolean false if failed 223 * 224 * @since 3.0 225 * @see \JTable::getInstance() 226 */ 227 protected function _createTable($name, $prefix = 'Table', $config = array()) 228 { 229 // Make sure we are returning a DBO object 230 if (!\array_key_exists('dbo', $config)) { 231 $config['dbo'] = $this->getDbo(); 232 } 233 234 return $this->getMVCFactory()->createTable($name, $prefix, $config); 235 } 236 237 /** 238 * Method to get a table object, load it if necessary. 239 * 240 * @param string $name The table name. Optional. 241 * @param string $prefix The class prefix. Optional. 242 * @param array $options Configuration array for model. Optional. 243 * 244 * @return Table A Table object 245 * 246 * @since 3.0 247 * @throws \Exception 248 */ 249 public function getTable($name = '', $prefix = '', $options = array()) 250 { 251 if (empty($name)) { 252 $name = $this->getName(); 253 } 254 255 // We need this ugly code to deal with non-namespaced MVC code 256 if (empty($prefix) && $this->getMVCFactory() instanceof LegacyFactory) { 257 $prefix = 'Table'; 258 } 259 260 if ($table = $this->_createTable($name, $prefix, $options)) { 261 return $table; 262 } 263 264 throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name), 0); 265 } 266 267 /** 268 * Method to check if the given record is checked out by the current user 269 * 270 * @param \stdClass $item The record to check 271 * 272 * @return bool 273 */ 274 public function isCheckedOut($item) 275 { 276 $table = $this->getTable(); 277 $checkedOutField = $table->getColumnAlias('checked_out'); 278 279 if (property_exists($item, $checkedOutField) && $item->{$checkedOutField} != $this->getCurrentUser()->id) { 280 return true; 281 } 282 283 return false; 284 } 285 286 /** 287 * Clean the cache 288 * 289 * @param string $group The cache group 290 * 291 * @return void 292 * 293 * @since 3.0 294 */ 295 protected function cleanCache($group = null) 296 { 297 $app = Factory::getApplication(); 298 299 $options = [ 300 'defaultgroup' => $group ?: ($this->option ?? $app->input->get('option')), 301 'cachebase' => $app->get('cache_path', JPATH_CACHE), 302 'result' => true, 303 ]; 304 305 try { 306 /** @var CallbackController $cache */ 307 $cache = $this->getCacheControllerFactory()->createCacheController('callback', $options); 308 $cache->clean(); 309 } catch (CacheExceptionInterface $exception) { 310 $options['result'] = false; 311 } 312 313 // Trigger the onContentCleanCache event. 314 $this->dispatchEvent(new Event($this->event_clean_cache, $options)); 315 } 316 317 /** 318 * Boots the component with the given name. 319 * 320 * @param string $component The component name, eg. com_content. 321 * 322 * @return ComponentInterface The service container 323 * 324 * @since 4.0.0 325 */ 326 protected function bootComponent($component): ComponentInterface 327 { 328 return Factory::getApplication()->bootComponent($component); 329 } 330 331 /** 332 * Dispatches the given event on the internal dispatcher, does a fallback to the global one. 333 * 334 * @param EventInterface $event The event 335 * 336 * @return void 337 * 338 * @since 4.1.0 339 */ 340 protected function dispatchEvent(EventInterface $event) 341 { 342 try { 343 $this->getDispatcher()->dispatch($event->getName(), $event); 344 } catch (\UnexpectedValueException $e) { 345 Factory::getContainer()->get(DispatcherInterface::class)->dispatch($event->getName(), $event); 346 } 347 } 348 349 /** 350 * Get the database driver. 351 * 352 * @return DatabaseInterface The database driver. 353 * 354 * @since 4.2.0 355 * @throws \UnexpectedValueException 356 * 357 * @deprecated 5.0 Use getDatabase() instead 358 */ 359 public function getDbo() 360 { 361 try { 362 return $this->getDatabase(); 363 } catch (DatabaseNotFoundException $e) { 364 throw new \UnexpectedValueException('Database driver not set in ' . __CLASS__); 365 } 366 } 367 368 /** 369 * Set the database driver. 370 * 371 * @param DatabaseInterface $db The database driver. 372 * 373 * @return void 374 * 375 * @since 4.2.0 376 * 377 * @deprecated 5.0 Use setDatabase() instead 378 */ 379 public function setDbo(DatabaseInterface $db = null) 380 { 381 if ($db === null) { 382 return; 383 } 384 385 $this->setDatabase($db); 386 } 387 388 /** 389 * Proxy for _db variable. 390 * 391 * @param string $name The name of the element 392 * 393 * @return mixed The value of the element if set, null otherwise 394 * 395 * @since 4.2.0 396 * 397 * @deprecated 5.0 Use getDatabase() instead of directly accessing _db 398 */ 399 public function __get($name) 400 { 401 if ($name === '_db') { 402 return $this->getDbo(); 403 } 404 405 // Default the variable 406 if (!isset($this->$name)) { 407 $this->$name = null; 408 } 409 410 return $this->$name; 411 } 412 }
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 |