Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
legacy.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Legacy
4  * @subpackage Model
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 /**
13  * Base class for a Joomla Model
14  *
15  * Acts as a Factory class for application specific objects and
16  * provides many supporting API functions.
17  *
18  * @package Joomla.Legacy
19  * @subpackage Model
20  * @since 12.2
21  */
22 abstract class JModelLegacy extends JObject
23 {
24  /**
25  * Indicates if the internal state has been set
26  *
27  * @var boolean
28  * @since 12.2
29  */
30  protected $__state_set = null;
31 
32  /**
33  * Database Connector
34  *
35  * @var object
36  * @since 12.2
37  */
38  protected $_db;
39 
40  /**
41  * The model (base) name
42  *
43  * @var string
44  * @since 12.2
45  */
46  protected $name;
47 
48  /**
49  * The URL option for the component.
50  *
51  * @var string
52  * @since 12.2
53  */
54  protected $option = null;
55 
56  /**
57  * A state object
58  *
59  * @var string
60  * @since 12.2
61  */
62  protected $state;
63 
64  /**
65  * The event to trigger when cleaning cache.
66  *
67  * @var string
68  * @since 12.2
69  */
70  protected $event_clean_cache = null;
71 
72  /**
73  * Add a directory where JModelLegacy should search for models. You may
74  * either pass a string or an array of directories.
75  *
76  * @param mixed $path A path or array[sting] of paths to search.
77  * @param string $prefix A prefix for models.
78  *
79  * @return array An array with directory elements. If prefix is equal to '', all directories are returned.
80  *
81  * @since 12.2
82  */
83  public static function addIncludePath($path = '', $prefix = '')
84  {
85  static $paths;
86 
87  if (!isset($paths))
88  {
89  $paths = array();
90  }
91 
92  if (!isset($paths[$prefix]))
93  {
94  $paths[$prefix] = array();
95  }
96 
97  if (!isset($paths['']))
98  {
99  $paths[''] = array();
100  }
101 
102  if (!empty($path))
103  {
104  jimport('joomla.filesystem.path');
105 
106  if (!in_array($path, $paths[$prefix]))
107  {
108  array_unshift($paths[$prefix], JPath::clean($path));
109  }
110 
111  if (!in_array($path, $paths['']))
112  {
113  array_unshift($paths[''], JPath::clean($path));
114  }
115  }
116 
117  return $paths[$prefix];
118  }
119 
120  /**
121  * Adds to the stack of model table paths in LIFO order.
122  *
123  * @param mixed $path The directory as a string or directories as an array to add.
124  *
125  * @return void
126  *
127  * @since 12.2
128  */
129  public static function addTablePath($path)
130  {
131  JTable::addIncludePath($path);
132  }
133 
134  /**
135  * Create the filename for a resource
136  *
137  * @param string $type The resource type to create the filename for.
138  * @param array $parts An associative array of filename information.
139  *
140  * @return string The filename
141  *
142  * @since 12.2
143  */
144  protected static function _createFileName($type, $parts = array())
145  {
146  $filename = '';
147 
148  switch ($type)
149  {
150  case 'model':
151  $filename = strtolower($parts['name']) . '.php';
152  break;
153 
154  }
155  return $filename;
156  }
157 
158  /**
159  * Returns a Model object, always creating it
160  *
161  * @param string $type The model type to instantiate
162  * @param string $prefix Prefix for the model class name. Optional.
163  * @param array $config Configuration array for model. Optional.
164  *
165  * @return mixed A model object or false on failure
166  *
167  * @since 12.2
168  */
169  public static function getInstance($type, $prefix = '', $config = array())
170  {
171  $type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
172  $modelClass = $prefix . ucfirst($type);
173 
174  if (!class_exists($modelClass))
175  {
176  jimport('joomla.filesystem.path');
177  $path = JPath::find(self::addIncludePath(null, $prefix), self::_createFileName('model', array('name' => $type)));
178  if (!$path)
179  {
180  $path = JPath::find(self::addIncludePath(null, ''), self::_createFileName('model', array('name' => $type)));
181  }
182  if ($path)
183  {
184  require_once $path;
185 
186  if (!class_exists($modelClass))
187  {
188  JLog::add(JText::sprintf('JLIB_APPLICATION_ERROR_MODELCLASS_NOT_FOUND', $modelClass), JLog::WARNING, 'jerror');
189  return false;
190  }
191  }
192  else
193  {
194  return false;
195  }
196  }
197 
198  return new $modelClass($config);
199  }
200 
201  /**
202  * Constructor
203  *
204  * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request).
205  *
206  * @since 12.2
207  * @throws Exception
208  */
209  public function __construct($config = array())
210  {
211  // Guess the option from the class name (Option)Model(View).
212  if (empty($this->option))
213  {
214  $r = null;
215 
216  if (!preg_match('/(.*)Model/i', get_class($this), $r))
217  {
218  throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
219  }
220 
221  $this->option = 'com_' . strtolower($r[1]);
222  }
223 
224  // Set the view name
225  if (empty($this->name))
226  {
227  if (array_key_exists('name', $config))
228  {
229  $this->name = $config['name'];
230  }
231  else
232  {
233  $this->name = $this->getName();
234  }
235  }
236 
237  // Set the model state
238  if (array_key_exists('state', $config))
239  {
240  $this->state = $config['state'];
241  }
242  else
243  {
244  $this->state = new JObject;
245  }
246 
247  // Set the model dbo
248  if (array_key_exists('dbo', $config))
249  {
250  $this->_db = $config['dbo'];
251  }
252  else
253  {
254  $this->_db = JFactory::getDbo();
255  }
256 
257  // Set the default view search path
258  if (array_key_exists('table_path', $config))
259  {
260  $this->addTablePath($config['table_path']);
261  }
262  elseif (defined('JPATH_COMPONENT_ADMINISTRATOR'))
263  {
264  $this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');
265  $this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR . '/table');
266  }
267 
268  // Set the internal state marker - used to ignore setting state from the request
269  if (!empty($config['ignore_request']))
270  {
271  $this->__state_set = true;
272  }
273 
274  // Set the clean cache event
275  if (isset($config['event_clean_cache']))
276  {
277  $this->event_clean_cache = $config['event_clean_cache'];
278  }
279  elseif (empty($this->event_clean_cache))
280  {
281  $this->event_clean_cache = 'onContentCleanCache';
282  }
283 
284  }
285 
286  /**
287  * Gets an array of objects from the results of database query.
288  *
289  * @param string $query The query.
290  * @param integer $limitstart Offset.
291  * @param integer $limit The number of records.
292  *
293  * @return array An array of results.
294  *
295  * @since 12.2
296  * @throws RuntimeException
297  */
298  protected function _getList($query, $limitstart = 0, $limit = 0)
299  {
300  $this->_db->setQuery($query, $limitstart, $limit);
301  $result = $this->_db->loadObjectList();
302 
303  return $result;
304  }
305 
306  /**
307  * Returns a record count for the query.
308  *
309  * @param JDatabaseQuery|string $query The query.
310  *
311  * @return integer Number of rows for query.
312  *
313  * @since 12.2
314  */
315  protected function _getListCount($query)
316  {
317  // Use fast COUNT(*) on JDatabaseQuery objects if there no GROUP BY or HAVING clause:
318  if ($query instanceof JDatabaseQuery
319  && $query->type == 'select'
320  && $query->group === null
321  && $query->having === null)
322  {
323  $query = clone $query;
324  $query->clear('select')->clear('order')->select('COUNT(*)');
325 
326  $this->_db->setQuery($query);
327  return (int) $this->_db->loadResult();
328  }
329 
330  // Otherwise fall back to inefficient way of counting all results.
331  $this->_db->setQuery($query);
332  $this->_db->execute();
333 
334  return (int) $this->_db->getNumRows();
335  }
336 
337  /**
338  * Method to load and return a model object.
339  *
340  * @param string $name The name of the view
341  * @param string $prefix The class prefix. Optional.
342  * @param array $config Configuration settings to pass to JTable::getInstance
343  *
344  * @return mixed Model object or boolean false if failed
345  *
346  * @since 12.2
347  * @see JTable::getInstance()
348  */
349  protected function _createTable($name, $prefix = 'Table', $config = array())
350  {
351  // Clean the model name
352  $name = preg_replace('/[^A-Z0-9_]/i', '', $name);
353  $prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
354 
355  // Make sure we are returning a DBO object
356  if (!array_key_exists('dbo', $config))
357  {
358  $config['dbo'] = $this->getDbo();
359  }
360 
361  return JTable::getInstance($name, $prefix, $config);
362  }
363 
364  /**
365  * Method to get the database driver object
366  *
367  * @return JDatabaseDriver
368  */
369  public function getDbo()
370  {
371  return $this->_db;
372  }
373 
374  /**
375  * Method to get the model name
376  *
377  * The model name. By default parsed using the classname or it can be set
378  * by passing a $config['name'] in the class constructor
379  *
380  * @return string The name of the model
381  *
382  * @since 12.2
383  * @throws Exception
384  */
385  public function getName()
386  {
387  if (empty($this->name))
388  {
389  $r = null;
390  if (!preg_match('/Model(.*)/i', get_class($this), $r))
391  {
392  throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
393  }
394  $this->name = strtolower($r[1]);
395  }
396 
397  return $this->name;
398  }
399 
400  /**
401  * Method to get model state variables
402  *
403  * @param string $property Optional parameter name
404  * @param mixed $default Optional default value
405  *
406  * @return object The property where specified, the state object where omitted
407  *
408  * @since 12.2
409  */
410  public function getState($property = null, $default = null)
411  {
412  if (!$this->__state_set)
413  {
414  // Protected method to auto-populate the model state.
415  $this->populateState();
416 
417  // Set the model state set flag to true.
418  $this->__state_set = true;
419  }
420 
421  return $property === null ? $this->state : $this->state->get($property, $default);
422  }
423 
424  /**
425  * Method to get a table object, load it if necessary.
426  *
427  * @param string $name The table name. Optional.
428  * @param string $prefix The class prefix. Optional.
429  * @param array $options Configuration array for model. Optional.
430  *
431  * @return JTable A JTable object
432  *
433  * @since 12.2
434  * @throws Exception
435  */
436  public function getTable($name = '', $prefix = 'Table', $options = array())
437  {
438  if (empty($name))
439  {
440  $name = $this->getName();
441  }
442 
443  if ($table = $this->_createTable($name, $prefix, $options))
444  {
445  return $table;
446  }
447 
448  throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name), 0);
449  }
450 
451  /**
452  * Method to load a row for editing from the version history table.
453  *
454  * @param integer $version_id Key to the version history table.
455  * @param JTable &$table Content table object being loaded.
456  *
457  * @return boolean False on failure or error, true otherwise.
458  *
459  * @since 12.2
460  */
461  public function loadHistory($version_id, JTable &$table)
462  {
463  // Only attempt to check the row in if it exists.
464  if ($version_id)
465  {
466  $user = JFactory::getUser();
467 
468  // Get an instance of the row to checkout.
469  $historyTable = JTable::getInstance('Contenthistory');
470 
471  if (!$historyTable->load($version_id))
472  {
473  $this->setError($historyTable->getError());
474 
475  return false;
476  }
477 
478  $rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data));
479 
480  $typeId = JTable::getInstance('Contenttype')->getTypeId($this->typeAlias);
481 
482  if ($historyTable->ucm_type_id != $typeId)
483  {
484  $this->setError(JText::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH'));
485  $key = $table->getKeyName();
486 
487  if (isset($rowArray[$key]))
488  {
489  $table->checkIn($rowArray[$key]);
490  }
491 
492  return false;
493  }
494  }
495 
496  $this->setState('save_date', $historyTable->save_date);
497  $this->setState('version_note', $historyTable->version_note);
498 
499  return $table->bind($rowArray);
500  }
501 
502  /**
503  * Method to auto-populate the model state.
504  *
505  * This method should only be called once per instantiation and is designed
506  * to be called on the first call to the getState() method unless the model
507  * configuration flag to ignore the request is set.
508  *
509  * @return void
510  *
511  * @note Calling getState in this method will result in recursion.
512  * @since 12.2
513  */
514  protected function populateState()
515  {
516  }
517 
518  /**
519  * Method to set the database driver object
520  *
521  * @param JDatabaseDriver $db A JDatabaseDriver based object
522  *
523  * @return void
524  *
525  * @since 12.2
526  */
527  public function setDbo($db)
528  {
529  $this->_db = $db;
530  }
531 
532  /**
533  * Method to set model state variables
534  *
535  * @param string $property The name of the property.
536  * @param mixed $value The value of the property to set or null.
537  *
538  * @return mixed The previous value of the property or null if not set.
539  *
540  * @since 12.2
541  */
542  public function setState($property, $value = null)
543  {
544  return $this->state->set($property, $value);
545  }
546 
547  /**
548  * Clean the cache
549  *
550  * @param string $group The cache group
551  * @param integer $client_id The ID of the client
552  *
553  * @return void
554  *
555  * @since 12.2
556  */
557  protected function cleanCache($group = null, $client_id = 0)
558  {
559  $conf = JFactory::getConfig();
560  $dispatcher = JEventDispatcher::getInstance();
561 
562  $options = array(
563  'defaultgroup' => ($group) ? $group : (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')),
564  'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache'));
565 
566  $cache = JCache::getInstance('callback', $options);
567  $cache->clean();
568 
569  // Trigger the onContentCleanCache event.
570  $dispatcher->trigger($this->event_clean_cache, $options);
571  }
572 }