5 * @version $Id: user.php 9205 2008-12-18 18:08:57Z acydburn $
6 * @copyright (c) 2005, 2008 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
14 if (!defined('IN_PHPBB'))
22 * This is the overarching class which contains (through session extend)
23 * all methods utilised for user functionality during a session.
27 class phpbb_user
extends phpbb_session
30 * @var array required phpBB objects
32 public $phpbb_required = array('config', 'acl', 'db', 'template', 'security', 'server-vars', 'acm', 'api:user');
35 * @var array Optional phpBB objects
37 public $phpbb_optional = array();
40 * @var array language entries
42 public $lang = array();
45 * @var array help entries
47 public $help = array();
50 * @var array theme entries
52 public $theme = array();
55 * @var string users date format
60 * @var double users time zone
65 * @var int users summer time setting. 0 if not in DST, else DST offset.
70 * @var string language name, for example 'en'
72 public $lang_name = false;
75 * @var int the language id for the specified language name
77 public $lang_id = false;
80 * @var string the language path phpBB can find installed languages
85 * @var string Imageset language name. If no fallback happens it is the same as {@link lang_name lang_name}.
90 * @var array Holds information about the imageset to build {@link img() images}.
92 public $img_array = array();
95 * Ablility to add new option (id 7). Enabled user options is stored in $data['user_options'].
96 * @var array user options defining their possibilities to view flash, images, etc. User options only supports set/unset (true/false)
98 public $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10);
101 * @var array The respective true/false values for the {@link keyoptions keyoptions}.
103 public $keyvalues = array();
106 * Constructor to set the lang path. Calls parrent::__construct()
108 * @param string $auth_method The authentication method to use, for example 'db'
109 * @param string $custom_lang_path An optional language pack path.
112 public function __construct($auth_method, $custom_lang_path = false)
114 parent
::__construct();
117 $method = basename(trim($auth_method));
118 $class = 'phpbb_auth_' . $method;
120 if (class_exists($class))
122 $this->auth
= new $class();
126 $this->lang_path
= ($custom_lang_path === false) ? PHPBB_ROOT_PATH
. 'language/' : $this->set_custom_lang_path($custom_lang_path);
130 * Initialize user session
132 * @param bool $update_session_page If true the session page gets updated.
133 * This can be set to false to circumvent certain scripts to update the users last visited page.
136 public function init($update_session_page = true)
138 $this->session_begin($update_session_page);
139 phpbb
::$acl->init($this->data
);
143 * Function to set custom language path (able to use directory outside of phpBB)
145 * @param string $lang_path New language path used.
148 public function set_custom_lang_path($lang_path)
150 $this->lang_path
= $lang_path;
152 if (substr($this->lang_path
, -1) != '/')
154 $this->lang_path
.= '/';
159 * Setup basic user-specific items (style, language, ...)
161 * @param string|array $lang_set Language set to setup.
162 * Can be a string or an array of language files without a path and extension.
163 * Format must match {@link add_lang() add_lang}.
164 * @param int $style If not set to false this specifies the style id to use.
165 * The page will then use the specified style id instead of the default one.
168 public function setup($lang_set = false, $style = false)
170 if ($this->data
['user_id'] != ANONYMOUS
)
172 $this->lang_name
= (file_exists($this->lang_path
. $this->data
['user_lang'] . "/common." . PHP_EXT
)) ?
$this->data
['user_lang'] : basename(phpbb
::$config['default_lang']);
173 $this->date_format
= $this->data
['user_dateformat'];
174 $this->timezone
= $this->data
['user_timezone'] * 3600;
175 $this->dst
= $this->data
['user_dst'] * 3600;
179 $this->lang_name
= basename(phpbb
::$config['default_lang']);
180 $this->date_format
= phpbb
::$config['default_dateformat'];
181 $this->timezone
= phpbb
::$config['board_timezone'] * 3600;
182 $this->dst
= phpbb
::$config['board_dst'] * 3600;
185 * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
186 * If re-enabled we need to make sure only those languages installed are checked
187 * Commented out so we do not loose the code.
189 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
191 $accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
193 foreach ($accept_lang_ary as $accept_lang)
195 // Set correct format ... guess full xx_YY form
196 $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
197 $accept_lang = basename($accept_lang);
199 if (file_exists($this->lang_path . $accept_lang . "/common." . PHP_EXT))
201 $this->lang_name = phpbb::$config['default_lang'] = $accept_lang;
206 // No match on xx_YY so try xx
207 $accept_lang = substr($accept_lang, 0, 2);
208 $accept_lang = basename($accept_lang);
210 if (file_exists($this->lang_path . $accept_lang . "/common." . PHP_EXT))
212 $this->lang_name = phpbb::$config['default_lang'] = $accept_lang;
221 // We include common language file here to not load it every time a custom language file is included
222 $lang = &$this->lang
;
224 if ((include $this->lang_path
. $this->lang_name
. "/common." . PHP_EXT
) === false)
226 die('Language file ' . $this->lang_path
. $this->lang_name
. "/common." . PHP_EXT
. " couldn't be opened.");
229 $this->add_lang($lang_set);
232 if (phpbb_request
::variable('style', false, false, phpbb_request
::GET
) && phpbb
::$acl->acl_get('a_styles'))
234 $style = request_var('style', 0);
235 $this->extra_url
= array('style=' . $style);
240 $style = ($style) ?
$style : ((!phpbb
::$config['override_user_style']) ?
$this->data
['user_style'] : phpbb
::$config['default_style']);
243 $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
244 FROM ' . STYLES_TABLE
. ' s, ' . STYLES_TEMPLATE_TABLE
. ' t, ' . STYLES_THEME_TABLE
. ' c, ' . STYLES_IMAGESET_TABLE
. " i
245 WHERE s.style_id = $style
246 AND t.template_id = s.template_id
247 AND c.theme_id = s.theme_id
248 AND i.imageset_id = s.imageset_id";
249 $result = phpbb
::$db->sql_query($sql, 3600);
250 $this->theme
= phpbb
::$db->sql_fetchrow($result);
251 phpbb
::$db->sql_freeresult($result);
253 // User has wrong style
254 if (!$this->theme
&& $style == $this->data
['user_style'])
256 $style = $this->data
['user_style'] = phpbb
::$config['default_style'];
258 $sql = 'UPDATE ' . USERS_TABLE
. "
259 SET user_style = $style
260 WHERE user_id = {$this->data['user_id']}";
261 phpbb
::$db->sql_query($sql);
263 $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
264 FROM ' . STYLES_TABLE
. ' s, ' . STYLES_TEMPLATE_TABLE
. ' t, ' . STYLES_THEME_TABLE
. ' c, ' . STYLES_IMAGESET_TABLE
. " i
265 WHERE s.style_id = $style
266 AND t.template_id = s.template_id
267 AND c.theme_id = s.theme_id
268 AND i.imageset_id = s.imageset_id";
269 $result = phpbb
::$db->sql_query($sql, 3600);
270 $this->theme
= phpbb
::$db->sql_fetchrow($result);
271 phpbb
::$db->sql_freeresult($result);
276 trigger_error('Could not get style data', E_USER_ERROR
);
279 // Now parse the cfg file and cache it,
280 // we are only interested in the theme configuration for now
281 $parsed_items = phpbb_cache
::obtain_cfg_item($this->theme
, 'theme');
284 'parse_css_file' => (int) 0,
285 'pagination_sep' => (string) ', ',
288 foreach ($check_for as $key => $default_value)
290 $this->theme
[$key] = (isset($parsed_items[$key])) ?
$parsed_items[$key] : $default_value;
291 settype($this->theme
[$key], gettype($default_value));
293 if (is_string($default_value))
295 $this->theme
[$key] = htmlspecialchars($this->theme
[$key]);
299 // If the style author specified the theme needs to be cached
300 // (because of the used paths and variables) than make sure it is the case.
301 // For example, if the theme uses language-specific images it needs to be stored in db.
302 if (!$this->theme
['theme_storedb'] && $this->theme
['parse_css_file'])
304 $this->theme
['theme_storedb'] = 1;
306 $stylesheet = file_get_contents(PHPBB_ROOT_PATH
. "styles/{$this->theme['theme_path']}/theme/stylesheet.css");
309 preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches);
311 if (sizeof($matches))
314 foreach ($matches[0] as $idx => $match)
316 if ($content = @file_get_contents
(PHPBB_ROOT_PATH
. "styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx]))
318 $content = trim($content);
324 $stylesheet = str_replace($match, $content, $stylesheet);
329 $stylesheet = str_replace('./', 'styles/' . $this->theme
['theme_path'] . '/theme/', $stylesheet);
332 'theme_data' => $stylesheet,
333 'theme_mtime' => time(),
337 $sql = 'UPDATE ' . STYLES_THEME_TABLE
. '
338 SET ' . phpbb
::$db->sql_build_array('UPDATE', $sql_ary) . '
339 WHERE theme_id = ' . $this->theme
['theme_id'];
340 phpbb
::$db->sql_query($sql);
345 phpbb
::$template->set_template();
347 $this->img_lang
= (file_exists(PHPBB_ROOT_PATH
. 'styles/' . $this->theme
['imageset_path'] . '/imageset/' . $this->lang_name
)) ?
$this->lang_name
: phpbb
::$config['default_lang'];
349 $sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width
350 FROM ' . STYLES_IMAGESET_DATA_TABLE
. '
351 WHERE imageset_id = ' . $this->theme
['imageset_id'] . "
352 AND image_filename <> ''
353 AND image_lang IN ('" . phpbb
::$db->sql_escape($this->img_lang
) . "', '')";
354 $result = phpbb
::$db->sql_query($sql, 3600);
356 $localised_images = false;
357 while ($row = phpbb
::$db->sql_fetchrow($result))
359 if ($row['image_lang'])
361 $localised_images = true;
364 $row['image_filename'] = rawurlencode($row['image_filename']);
365 $this->img_array
[$row['image_name']] = $row;
367 phpbb
::$db->sql_freeresult($result);
369 // there were no localised images, try to refresh the localised imageset for the user's language
370 if (!$localised_images)
372 // Attention: this code ignores the image definition list from acp_styles and just takes everything
373 // that the config file contains
376 phpbb
::$db->sql_transaction('begin');
378 $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE
. '
379 WHERE imageset_id = ' . $this->theme
['imageset_id'] . '
380 AND image_lang = \'' . phpbb
::$db->sql_escape($this->img_lang
) . '\'';
381 $result = phpbb
::$db->sql_query($sql);
383 if (@file_exists
(PHPBB_ROOT_PATH
. "styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg"))
385 $cfg_data_imageset_data = parse_cfg_file(PHPBB_ROOT_PATH
. "styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg");
386 foreach ($cfg_data_imageset_data as $image_name => $value)
388 if (strpos($value, '*') !== false)
390 if (substr($value, -1, 1) === '*')
392 list($image_filename, $image_height) = explode('*', $value);
397 list($image_filename, $image_height, $image_width) = explode('*', $value);
402 $image_filename = $value;
403 $image_height = $image_width = 0;
406 if (strpos($image_name, 'img_') === 0 && $image_filename)
408 $image_name = substr($image_name, 4);
410 'image_name' => (string) $image_name,
411 'image_filename' => (string) $image_filename,
412 'image_height' => (int) $image_height,
413 'image_width' => (int) $image_width,
414 'imageset_id' => (int) $this->theme
['imageset_id'],
415 'image_lang' => (string) $this->img_lang
,
421 if (sizeof($sql_ary))
423 phpbb
::$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE
, $sql_ary);
424 phpbb
::$db->sql_transaction('commit');
425 phpbb
::$acm->destroy('sql', STYLES_IMAGESET_DATA_TABLE
);
427 add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme
['imageset_name'], $this->img_lang
);
431 phpbb
::$db->sql_transaction('commit');
432 add_log('admin', 'LOG_IMAGESET_LANG_MISSING', $this->theme
['imageset_name'], $this->img_lang
);
436 // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes...
437 // After calling it we continue script execution...
438 phpbb_user_session_handler();
440 // If this function got called from the error handler we are finished here.
441 if (defined('IN_ERROR_HANDLER'))
446 // Disable board if the install/ directory is still present
447 // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
448 if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists(PHPBB_ROOT_PATH
. 'install'))
450 // Adjust the message slightly according to the permissions
451 if (phpbb
::$acl->acl_gets('a_', 'm_') || phpbb
::$acl->acl_getf_global('m_'))
453 $message = 'REMOVE_INSTALL';
457 $message = (!empty(phpbb
::$config['board_disable_msg'])) ? phpbb
::$config['board_disable_msg'] : 'BOARD_DISABLE';
459 trigger_error($message);
462 // Is board disabled and user not an admin or moderator?
463 if (phpbb
::$config['board_disable'] && !defined('IN_LOGIN') && !phpbb
::$acl->acl_gets('a_', 'm_') && !phpbb
::$acl->acl_getf_global('m_'))
465 header('HTTP/1.1 503 Service Unavailable');
467 $message = (!empty(phpbb
::$config['board_disable_msg'])) ? phpbb
::$config['board_disable_msg'] : 'BOARD_DISABLE';
468 trigger_error($message);
472 if (phpbb
::$config['limit_load'] && $this->load
!== false)
474 if ($this->load
> floatval(phpbb
::$config['limit_load']) && !defined('IN_LOGIN'))
476 // Set board disabled to true to let the admins/mods get the proper notification
477 phpbb
::$config['board_disable'] = '1';
479 if (!phpbb
::$acl->acl_gets('a_', 'm_') && !phpbb
::$acl->acl_getf_global('m_'))
481 header('HTTP/1.1 503 Service Unavailable');
482 trigger_error('BOARD_UNAVAILABLE');
487 if (isset($this->data
['session_viewonline']))
489 // Make sure the user is able to hide his session
490 if (!$this->data
['session_viewonline'])
492 // Reset online status if not allowed to hide the session...
493 if (!phpbb
::$acl->acl_get('u_hideonline'))
495 $sql = 'UPDATE ' . SESSIONS_TABLE
. '
496 SET session_viewonline = 1
497 WHERE session_user_id = ' . $this->data
['user_id'];
498 phpbb
::$db->sql_query($sql);
499 $this->data
['session_viewonline'] = 1;
502 else if (!$this->data
['user_allow_viewonline'])
504 // the user wants to hide and is allowed to -> cloaking device on.
505 if (phpbb
::$acl->acl_get('u_hideonline'))
507 $sql = 'UPDATE ' . SESSIONS_TABLE
. '
508 SET session_viewonline = 0
509 WHERE session_user_id = ' . $this->data
['user_id'];
510 phpbb
::$db->sql_query($sql);
511 $this->data
['session_viewonline'] = 0;
517 // Does the user need to change their password? If so, redirect to the
518 // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
519 if (!defined('IN_ADMIN') && !defined('ADMIN_START') && phpbb
::$config['chg_passforce'] && $this->data
['is_registered'] && phpbb
::$acl->acl_get('u_chgpasswd') && $this->data
['user_passchg'] < time() - (phpbb
::$config['chg_passforce'] * 86400))
521 if (strpos($this->page
['query_string'], 'mode=reg_details') === false && $this->page
['page_name'] != 'ucp.' . PHP_EXT
)
523 redirect(append_sid('ucp', 'i=profile&mode=reg_details'));
531 * More advanced language substitution
533 * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms.
534 * Params are the language key and the parameters to be substituted.
535 * This function/functionality was inspired by SHS` and Ashe.
539 * phpbb::$user->lang('NUM_POSTS_IN_QUEUE', 1);
542 * @param string $key The language key to use
543 * @param mixed $parameter,... An unlimited number of parameter to apply.
545 * @return string Substituted language string
549 public function lang()
551 $args = func_get_args();
556 $lang = &$this->lang
[array_shift($key)];
558 foreach ($key as $_key)
560 $lang = &$lang[$_key];
565 $lang = &$this->lang
[$key];
568 // Return if language string does not exist
569 if (!isset($lang) ||
(!is_string($lang) && !is_array($lang)))
574 // If the language entry is a string, we simply mimic sprintf() behaviour
575 if (is_string($lang))
577 if (sizeof($args) == 1)
582 // Replace key with language entry and simply pass along...
584 return call_user_func_array('sprintf', $args);
587 // It is an array... now handle different nullar/singular/plural forms
590 // We now get the first number passed and will select the key based upon this number
591 for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++
)
593 if (is_int($args[$i]))
595 $numbers = array_keys($lang);
597 foreach ($numbers as $num)
599 if ($num > $args[$i])
609 // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
610 if ($key_found === false)
612 $numbers = array_keys($lang);
613 $key_found = end($numbers);
616 // Use the language string we determined and pass it to sprintf()
617 $args[0] = $lang[$key_found];
618 return call_user_func_array('sprintf', $args);
622 * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
626 * $lang_set = array('posting', 'help' => 'faq');
627 * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
628 * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
629 * $lang_set = 'posting'
630 * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
633 * @param mixed $lang_set specifies the language entries to include
634 * @param bool $use_db internal variable for recursion, do not use
635 * @param bool $use_help internal variable for recursion, do not use
638 public function add_lang($lang_set, $use_db = false, $use_help = false)
640 if (is_array($lang_set))
642 foreach ($lang_set as $key => $lang_file)
644 // Please do not delete this line.
645 // We have to force the type here, else [array] language inclusion will not work
646 $key = (string) $key;
650 $this->add_lang($lang_file, true, $use_help);
652 else if ($key == 'help')
654 $this->add_lang($lang_file, $use_db, true);
656 else if (!is_array($lang_file))
658 $this->set_lang($this->lang
, $this->help
, $lang_file, $use_db, $use_help);
662 $this->add_lang($lang_file, $use_db, $use_help);
669 $this->set_lang($this->lang
, $this->help
, $lang_set, $use_db, $use_help);
674 * Set language entry (called by {@link add_lang() add_lang})
676 * @param array &$lang A reference to the language array phpbb::$user->lang
677 * @param array &$help A reference to the language help array phpbb::$user->help
678 * @param string $lang_file Language filename
679 * @param bool $use_db True if the database is used for obtaining the information
680 * @param bool $use_help True if we fetch help entries instead of language entries
683 private function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false)
685 // Make sure the language name is set (if the user setup did not happen it is not set)
686 if (!$this->lang_name
)
688 $this->lang_name
= basename(phpbb
::$config['default_lang']);
691 // $lang == $this->lang
692 // $help == $this->help
693 // - add appropriate variables here, name them as they are used within the language file...
696 if ($use_help && strpos($lang_file, '/') !== false)
698 $language_filename = $this->lang_path
. $this->lang_name
. '/' . substr($lang_file, 0, stripos($lang_file, '/') +
1) . 'help_' . substr($lang_file, stripos($lang_file, '/') +
1) . '.' . PHP_EXT
;
702 $language_filename = $this->lang_path
. $this->lang_name
. '/' . (($use_help) ?
'help_' : '') . $lang_file . '.' . PHP_EXT
;
705 if (!file_exists($language_filename))
707 if ($this->lang_name
== 'en')
709 // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en.
710 $language_filename = str_replace($this->lang_path
. 'en', $this->lang_path
. $this->data
['user_lang'], $language_filename);
711 trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR
);
713 else if ($this->lang_name
== basename(phpbb
::$config['default_lang']))
715 // Fall back to the English Language
716 $this->lang_name
= 'en';
717 $this->set_lang($lang, $help, $lang_file, $use_db, $use_help);
719 else if (file_exists($this->lang_path
. $this->data
['user_lang'] . '/common.' . PHP_EXT
))
721 // Fall back to the board default language
722 $this->lang_name
= basename(phpbb
::$config['default_lang']);
723 $this->set_lang($lang, $help, $lang_file, $use_db, $use_help);
726 // Reset the lang name
727 $this->lang_name
= (file_exists($this->lang_path
. $this->data
['user_lang'] . '/common.' . PHP_EXT
)) ?
$this->data
['user_lang'] : basename(phpbb
::$config['default_lang']);
731 if ((include $language_filename) === false)
733 trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR
);
738 // Get Database Language Strings
739 // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
740 // For example: help:faq, posting
747 * @param int $gmepoch Unix timestamp to format
748 * @param string $format Date format in date() notation.
749 * The character | used to indicate relative dates, for example |d m Y|, h:i is translated to Today, h:i.
750 * @param bool $forcedate Force non-relative date format.
752 * @staticvar int $midnight Midnight time offset
753 * @staticvar array $date_cache Array to cache commonly needed structures within this function
755 * @return mixed translated date
758 public function format_date($gmepoch, $format = false, $forcedate = false)
763 $format = (!$format) ?
$this->date_format
: $format;
765 $delta = $now - $gmepoch;
767 if (!isset($date_cache[$format]))
769 // Is the user requesting a friendly date format (i.e. 'Today 12:42')?
770 $date_cache[$format] = array(
771 'is_short' => strpos($format, '|'),
772 'zone_offset' => $this->timezone +
$this->dst
,
773 'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1),
774 'format_long' => str_replace('|', '', $format),
775 'lang' => $this->lang
['datetime'],
778 // Short representation of month in format? Some languages use different terms for the long and short format of May
779 if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) ||
(strpos($format, '\r') === false && strpos($format, 'r') !== false))
781 $date_cache[$format]['lang']['May'] = $this->lang
['datetime']['May_short'];
785 // Show date <= 1 hour ago as 'xx min ago'
786 // A small tolerence is given for times in the future and times in the future but in the same minute are displayed as '< than a minute ago'
787 if ($delta <= 3600 && ($delta >= -5 ||
(($now / 60) %
60) == (($gmepoch / 60) %
60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang
['datetime']['AGO']))
789 return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));
794 list($d, $m, $y) = explode(' ', gmdate('j n Y', time() +
$date_cache[$format]['zone_offset']));
795 $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $date_cache[$format]['zone_offset'];
798 if ($date_cache[$format]['is_short'] !== false && !$forcedate)
802 if ($gmepoch > $midnight +
86400)
806 else if ($gmepoch > $midnight)
810 else if ($gmepoch > $midnight - 86400)
817 return str_replace('||', $this->lang
['datetime'][$day], strtr(@gmdate
($date_cache[$format]['format_short'], $gmepoch +
$date_cache[$format]['zone_offset']), $date_cache[$format]['lang']));
821 return strtr(@gmdate
($date_cache[$format]['format_long'], $gmepoch +
$date_cache[$format]['zone_offset']), $date_cache[$format]['lang']);
825 * Get language id currently used by the user
827 * @return int language id
830 public function get_iso_lang_id()
832 if (!empty($this->lang_id
))
834 return $this->lang_id
;
837 if (!$this->lang_name
)
839 $this->lang_name
= phpbb
::$config['default_lang'];
842 $sql = 'SELECT lang_id
843 FROM ' . LANG_TABLE
. "
844 WHERE lang_iso = '" . phpbb
::$db->sql_escape($this->lang_name
) . "'";
845 $result = phpbb
::$db->sql_query($sql);
846 $this->lang_id
= (int) phpbb
::$db->sql_fetchfield('lang_id');
847 phpbb
::$db->sql_freeresult($result);
849 return $this->lang_id
;
853 * Get users profile fields
855 * @param int $user_id User id. If not specified the current users profile fields are grabbed.
857 * @return array Profile fields. If the current user then they are also stored as property $profile_fields.
860 public function get_profile_fields($user_id = false)
862 $user_id = ($user_id === false) ?
$this->data
['user_id'] : $user_id;
864 if (isset($this->profile_fields
) && $user_id === $this->data
['user_id'])
866 return $this->profile_fields
;
870 FROM ' . PROFILE_FIELDS_DATA_TABLE
. "
871 WHERE user_id = $user_id";
872 $result = phpbb
::$db->sql_query_limit($sql, 1);
873 $row = phpbb
::$db->sql_fetchrow($result);
874 phpbb
::$db->sql_freeresult($result);
876 if ($user_id === $this->data
['user_id'])
878 $this->profile_fields
= (!$row) ?
array() : $row;
885 * Specify/Get image from style imageset
887 * @param string $img The imageset image key name
888 * @param string $alt An optional alternative image attribute.
889 * If a corresponding language key exist it will be used: phpbb::$user->lang[$alt]
890 * @param string $type The preferred type to return. Allowed types are: full_tag, src, width, height
891 * @param int $width Set image width
893 * @return mixed returns the preferred type from $type
896 public function img($img, $alt = '', $type = 'full_tag', $width = false)
900 $img_data = &$imgs[$img];
902 if (empty($img_data))
904 if (!isset($this->img_array
[$img]))
906 // Do not fill the image to let designers decide what to do if the image is empty
911 $img_data['src'] = PHPBB_ROOT_PATH
. 'styles/' . $this->theme
['imageset_path'] . '/imageset/' . ($this->img_array
[$img]['image_lang'] ?
$this->img_array
[$img]['image_lang'] .'/' : '') . $this->img_array
[$img]['image_filename'];
912 $img_data['width'] = $this->img_array
[$img]['image_width'];
913 $img_data['height'] = $this->img_array
[$img]['image_height'];
916 $alt = (!empty($this->lang
[$alt])) ?
$this->lang
[$alt] : $alt;
921 return $img_data['src'];
925 return ($width === false) ?
$img_data['width'] : $width;
929 return $img_data['height'];
933 $use_width = ($width === false) ?
$img_data['width'] : $width;
935 return '<img src="' . $img_data['src'] . '"' . (($use_width) ?
' width="' . $use_width . '"' : '') . (($img_data['height']) ?
' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />';
941 * Get option bit field from user options.
943 * @param string $key The option key from {@link $keyoptions keyoptions}
944 * @param int $data Optional user options bitfield.
945 * If not specified then {@link $data $data['user_options']} is used.
947 * @return bool Corresponding option value returned. Is the option enabled or disabled.
950 public function optionget($key, $data = false)
954 return $data & 1 << $this->keyoptions
[$key];
957 if (!isset($this->keyvalues
[$key]))
959 $this->keyvalues
[$key] = $this->data
['user_options'] & 1 << $this->keyoptions
[$key];
962 return $this->keyvalues
[$key];
966 * Set option bit field for user options.
968 * @param string $key The option key from {@link $keyoptions keyoptions}
969 * @param bool $value True to enable the option, false to disable it
970 * @param int $data Optional user options bitfield.
971 * If not specified then {@link $data $data['user_options']} is used.
973 * @return bool The new user options bitfield is returned if $data is specified.
974 * Else: false is returned if user options not changed, true if changed.
977 public function optionset($key, $value, $data = false)
979 $var = ($data) ?
$data : $this->data
['user_options'];
981 if ($value && !($var & 1 << $this->keyoptions
[$key]))
983 $var +
= 1 << $this->keyoptions
[$key];
985 else if (!$value && ($var & 1 << $this->keyoptions
[$key]))
987 $var -= 1 << $this->keyoptions
[$key];
991 return ($data) ?
$var : false;
996 $this->data
['user_options'] = $this->keyvalues
[$key] = $var;
1004 * User login. Log the user in.
1006 * @param string $username The specified user name
1007 * @param string $password The specified password
1008 * @param bool $autologin Enable/disable persistent login
1009 * @param bool $viewonline If false then the user will be logged in as hidden
1010 * @param bool $admin If true the user requests an admin login
1012 * @return array Login result array. This array returns results to the login script to show errors, notices, confirmations.
1015 public function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
1017 if ($this->auth
=== false ||
!method_exists($this->auth
, 'login'))
1019 trigger_error('Authentication method not found', E_USER_ERROR
);
1022 $login = $this->auth
->login($username, $password);
1024 // If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS
1025 if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE
)
1027 phpbb
::$api->user
->add($login['user_row'], (isset($login['cp_data'])) ?
$login['cp_data'] : false);
1029 $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
1030 FROM ' . USERS_TABLE
. "
1031 WHERE username_clean = '" . phpbb
::$db->sql_escape(utf8_clean_string($username)) . "'";
1032 $result = phpbb
::$db->sql_query($sql);
1033 $row = phpbb
::$db->sql_fetchrow($result);
1034 phpbb
::$db->sql_freeresult($result);
1039 'status' => LOGIN_ERROR_EXTERNAL_AUTH
,
1040 'error_msg' => 'AUTH_NO_PROFILE_CREATED',
1041 'user_row' => array('user_id' => ANONYMOUS
),
1046 'status' => LOGIN_SUCCESS
,
1047 'error_msg' => false,
1052 // If login succeeded, we will log the user in... else we pass the login array through...
1053 if ($login['status'] == LOGIN_SUCCESS
)
1055 // We create a new session. The session creation makes sure the old session is killed if there was one.
1056 $result = $this->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline);
1058 // Successful session creation
1059 if ($result === true)
1062 'status' => LOGIN_SUCCESS
,
1063 'error_msg' => false,
1064 'user_row' => $login['user_row'],
1069 'status' => LOGIN_BREAK
,
1070 'error_msg' => $result,
1071 'user_row' => $login['user_row'],