Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
user.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Table
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  * Users table
14  *
15  * @package Joomla.Platform
16  * @subpackage Table
17  * @since 11.1
18  */
19 class JTableUser extends JTable
20 {
21  /**
22  * Associative array of group ids => group ids for the user
23  *
24  * @var array
25  * @since 11.1
26  */
27  public $groups;
28 
29  /**
30  * Constructor
31  *
32  * @param JDatabaseDriver $db Database driver object.
33  *
34  * @since 11.1
35  */
36  public function __construct(JDatabaseDriver $db)
37  {
38  parent::__construct('#__users', 'id', $db);
39 
40  // Initialise.
41  $this->id = 0;
42  $this->sendEmail = 0;
43  }
44 
45  /**
46  * Method to load a user, user groups, and any other necessary data
47  * from the database so that it can be bound to the user object.
48  *
49  * @param integer $userId An optional user id.
50  * @param boolean $reset False if row not found or on error
51  * (internal error state set in that case).
52  *
53  * @return boolean True on success, false on failure.
54  *
55  * @since 11.1
56  */
57  public function load($userId = null, $reset = true)
58  {
59  // Get the id to load.
60  if ($userId !== null)
61  {
62  $this->id = $userId;
63  }
64  else
65  {
66  $userId = $this->id;
67  }
68 
69  // Check for a valid id to load.
70  if ($userId === null)
71  {
72  return false;
73  }
74 
75  // Reset the table.
76  $this->reset();
77 
78  // Load the user data.
79  $query = $this->_db->getQuery(true)
80  ->select('*')
81  ->from($this->_db->quoteName('#__users'))
82  ->where($this->_db->quoteName('id') . ' = ' . (int) $userId);
83  $this->_db->setQuery($query);
84  $data = (array) $this->_db->loadAssoc();
85 
86  if (!count($data))
87  {
88  return false;
89  }
90 
91  // Convert e-mail from punycode
92  $data['email'] = JStringPunycode::emailToUTF8($data['email']);
93 
94  // Bind the data to the table.
95  $return = $this->bind($data);
96 
97  if ($return !== false)
98  {
99  // Load the user groups.
100  $query->clear()
101  ->select($this->_db->quoteName('g.id'))
102  ->select($this->_db->quoteName('g.title'))
103  ->from($this->_db->quoteName('#__usergroups') . ' AS g')
104  ->join('INNER', $this->_db->quoteName('#__user_usergroup_map') . ' AS m ON m.group_id = g.id')
105  ->where($this->_db->quoteName('m.user_id') . ' = ' . (int) $userId);
106  $this->_db->setQuery($query);
107 
108  // Add the groups to the user data.
109  $this->groups = $this->_db->loadAssocList('id', 'id');
110  }
111 
112  return $return;
113  }
114 
115  /**
116  * Method to bind the user, user groups, and any other necessary data.
117  *
118  * @param array $array The data to bind.
119  * @param mixed $ignore An array or space separated list of fields to ignore.
120  *
121  * @return boolean True on success, false on failure.
122  *
123  * @since 11.1
124  */
125  public function bind($array, $ignore = '')
126  {
127  if (array_key_exists('params', $array) && is_array($array['params']))
128  {
129  $registry = new JRegistry;
130  $registry->loadArray($array['params']);
131  $array['params'] = (string) $registry;
132  }
133 
134  // Attempt to bind the data.
135  $return = parent::bind($array, $ignore);
136 
137  // Load the real group data based on the bound ids.
138  if ($return && !empty($this->groups))
139  {
140  // Set the group ids.
141  JArrayHelper::toInteger($this->groups);
142 
143  // Get the titles for the user groups.
144  $query = $this->_db->getQuery(true)
145  ->select($this->_db->quoteName('id'))
146  ->select($this->_db->quoteName('title'))
147  ->from($this->_db->quoteName('#__usergroups'))
148  ->where($this->_db->quoteName('id') . ' = ' . implode(' OR ' . $this->_db->quoteName('id') . ' = ', $this->groups));
149  $this->_db->setQuery($query);
150 
151  // Set the titles for the user groups.
152  $this->groups = $this->_db->loadAssocList('id', 'id');
153 
154  }
155 
156  return $return;
157  }
158 
159  /**
160  * Validation and filtering
161  *
162  * @return boolean True if satisfactory
163  *
164  * @since 11.1
165  */
166  public function check()
167  {
168  // Set user id to null istead of 0, if needed
169  if ($this->id === 0)
170  {
171  $this->id = null;
172  }
173 
174  // Validate user information
175  if (trim($this->name) == '')
176  {
177  $this->setError(JText::_('JLIB_DATABASE_ERROR_PLEASE_ENTER_YOUR_NAME'));
178 
179  return false;
180  }
181 
182  if (trim($this->username) == '')
183  {
184  $this->setError(JText::_('JLIB_DATABASE_ERROR_PLEASE_ENTER_A_USER_NAME'));
185 
186  return false;
187  }
188 
189  if (preg_match('#[<>"\'%;()&\\s\\\\]|\\.\\./#', $this->username) || strlen(utf8_decode($this->username)) < 2)
190  {
191  $this->setError(JText::sprintf('JLIB_DATABASE_ERROR_VALID_AZ09', 2));
192 
193  return false;
194  }
195 
196  if ((trim($this->email) == "") || !JMailHelper::isEmailAddress($this->email))
197  {
198  $this->setError(JText::_('JLIB_DATABASE_ERROR_VALID_MAIL'));
199 
200  return false;
201  }
202 
203  // Convert e-mail to punycode for storage
204  $this->email = JStringPunycode::emailToPunycode($this->email);
205 
206  // Set the registration timestamp
207  if (empty($this->registerDate) || $this->registerDate == $this->_db->getNullDate())
208  {
209  $this->registerDate = JFactory::getDate()->toSql();
210  }
211 
212  // Set the lastvisitDate timestamp
213  if (empty($this->lastvisitDate))
214  {
215  $this->lastvisitDate = $this->_db->getNullDate();
216  }
217 
218  // Check for existing username
219  $query = $this->_db->getQuery(true)
220  ->select($this->_db->quoteName('id'))
221  ->from($this->_db->quoteName('#__users'))
222  ->where($this->_db->quoteName('username') . ' = ' . $this->_db->quote($this->username))
223  ->where($this->_db->quoteName('id') . ' != ' . (int) $this->id);
224  $this->_db->setQuery($query);
225 
226  $xid = (int) $this->_db->loadResult();
227 
228  if ($xid && $xid != (int) $this->id)
229  {
230  $this->setError(JText::_('JLIB_DATABASE_ERROR_USERNAME_INUSE'));
231 
232  return false;
233  }
234 
235  // Check for existing email
236  $query->clear()
237  ->select($this->_db->quoteName('id'))
238  ->from($this->_db->quoteName('#__users'))
239  ->where($this->_db->quoteName('email') . ' = ' . $this->_db->quote($this->email))
240  ->where($this->_db->quoteName('id') . ' != ' . (int) $this->id);
241  $this->_db->setQuery($query);
242  $xid = (int) $this->_db->loadResult();
243 
244  if ($xid && $xid != (int) $this->id)
245  {
246  $this->setError(JText::_('JLIB_DATABASE_ERROR_EMAIL_INUSE'));
247 
248  return false;
249  }
250 
251  // Check for root_user != username
252  $config = JFactory::getConfig();
253  $rootUser = $config->get('root_user');
254 
255  if (!is_numeric($rootUser))
256  {
257  $query->clear()
258  ->select($this->_db->quoteName('id'))
259  ->from($this->_db->quoteName('#__users'))
260  ->where($this->_db->quoteName('username') . ' = ' . $this->_db->quote($rootUser));
261  $this->_db->setQuery($query);
262  $xid = (int) $this->_db->loadResult();
263 
264  if ($rootUser == $this->username && (!$xid || $xid && $xid != (int) $this->id)
265  || $xid && $xid == (int) $this->id && $rootUser != $this->username)
266  {
267  $this->setError(JText::_('JLIB_DATABASE_ERROR_USERNAME_CANNOT_CHANGE'));
268 
269  return false;
270  }
271  }
272 
273  return true;
274  }
275 
276  /**
277  * Method to store a row in the database from the JTable instance properties.
278  * If a primary key value is set the row with that primary key value will be
279  * updated with the instance property values. If no primary key value is set
280  * a new row will be inserted into the database with the properties from the
281  * JTable instance.
282  *
283  * @param boolean $updateNulls True to update fields even if they are null.
284  *
285  * @return boolean True on success.
286  *
287  * @link http://docs.joomla.org/JTable/store
288  * @since 11.1
289  */
290  public function store($updateNulls = false)
291  {
292  // Get the table key and key value.
293  $k = $this->_tbl_key;
294  $key = $this->$k;
295 
296  // TODO: This is a dumb way to handle the groups.
297  // Store groups locally so as to not update directly.
298  $groups = $this->groups;
299  unset($this->groups);
300 
301  // Insert or update the object based on presence of a key value.
302  if ($key)
303  {
304  // Already have a table key, update the row.
305  $this->_db->updateObject($this->_tbl, $this, $this->_tbl_key, $updateNulls);
306  }
307  else
308  {
309  // Don't have a table key, insert the row.
310  $this->_db->insertObject($this->_tbl, $this, $this->_tbl_key);
311  }
312 
313  // Reset groups to the local object.
314  $this->groups = $groups;
315  unset($groups);
316 
317  // Store the group data if the user data was saved.
318  if (is_array($this->groups) && count($this->groups))
319  {
320  // Delete the old user group maps.
321  $query = $this->_db->getQuery(true)
322  ->delete($this->_db->quoteName('#__user_usergroup_map'))
323  ->where($this->_db->quoteName('user_id') . ' = ' . (int) $this->id);
324  $this->_db->setQuery($query);
325  $this->_db->execute();
326 
327  // Set the new user group maps.
328  $query->clear()
329  ->insert($this->_db->quoteName('#__user_usergroup_map'))
330  ->columns(array($this->_db->quoteName('user_id'), $this->_db->quoteName('group_id')));
331 
332  // Have to break this up into individual queries for cross-database support.
333  foreach ($this->groups as $group)
334  {
335  $query->clear('values')
336  ->values($this->id . ', ' . $group);
337  $this->_db->setQuery($query);
338  $this->_db->execute();
339  }
340  }
341 
342  // If a user is blocked, delete the cookie login rows
343  if ($this->block == (int) 1)
344  {
345  $query->clear()
346  ->delete($this->_db->quoteName('#__user_keys'))
347  ->where($this->_db->quoteName('user_id') . ' = ' . $this->_db->quote($this->username));
348  $this->_db->setQuery($query);
349  $this->_db->execute();
350  }
351 
352  return true;
353  }
354 
355  /**
356  * Method to delete a user, user groups, and any other necessary data from the database.
357  *
358  * @param integer $userId An optional user id.
359  *
360  * @return boolean True on success, false on failure.
361  *
362  * @since 11.1
363  */
364  public function delete($userId = null)
365  {
366  // Set the primary key to delete.
367  $k = $this->_tbl_key;
368 
369  if ($userId)
370  {
371  $this->$k = (int) $userId;
372  }
373 
374  // Delete the user.
375  $query = $this->_db->getQuery(true)
376  ->delete($this->_db->quoteName($this->_tbl))
377  ->where($this->_db->quoteName($this->_tbl_key) . ' = ' . (int) $this->$k);
378  $this->_db->setQuery($query);
379  $this->_db->execute();
380 
381  // Delete the user group maps.
382  $query->clear()
383  ->delete($this->_db->quoteName('#__user_usergroup_map'))
384  ->where($this->_db->quoteName('user_id') . ' = ' . (int) $this->$k);
385  $this->_db->setQuery($query);
386  $this->_db->execute();
387 
388  /*
389  * Clean Up Related Data.
390  */
391 
392  $query->clear()
393  ->delete($this->_db->quoteName('#__messages_cfg'))
394  ->where($this->_db->quoteName('user_id') . ' = ' . (int) $this->$k);
395  $this->_db->setQuery($query);
396  $this->_db->execute();
397 
398  $query->clear()
399  ->delete($this->_db->quoteName('#__messages'))
400  ->where($this->_db->quoteName('user_id_to') . ' = ' . (int) $this->$k);
401  $this->_db->setQuery($query);
402  $this->_db->execute();
403 
404  $query->clear()
405  ->delete($this->_db->quoteName('#__user_keys'))
406  ->where($this->_db->quoteName('user_id') . ' = ' . $this->_db->quote($this->username));
407  $this->_db->setQuery($query);
408  $this->_db->execute();
409 
410  return true;
411  }
412 
413  /**
414  * Updates last visit time of user
415  *
416  * @param integer $timeStamp The timestamp, defaults to 'now'.
417  * @param integer $userId The user id (optional).
418  *
419  * @return boolean False if an error occurs
420  *
421  * @since 11.1
422  */
423  public function setLastVisit($timeStamp = null, $userId = null)
424  {
425  // Check for User ID
426  if (is_null($userId))
427  {
428  if (isset($this))
429  {
430  $userId = $this->id;
431  }
432  else
433  {
434  jexit('No userid in setLastVisit');
435  }
436  }
437 
438  // If no timestamp value is passed to function, than current time is used.
439  $date = JFactory::getDate($timeStamp);
440 
441  // Update the database row for the user.
442  $db = $this->_db;
443  $query = $db->getQuery(true)
444  ->update($db->quoteName($this->_tbl))
445  ->set($db->quoteName('lastvisitDate') . '=' . $db->quote($date->toSql()))
446  ->where($db->quoteName('id') . '=' . (int) $userId);
447  $db->setQuery($query);
448  $db->execute();
449 
450  return true;
451  }
452 }