b2evolution PHP Cross Reference Blogging Systems

Source: /inc/users/model/_user.funcs.php - 3657 lines - 109308 bytes - Summary - Text - Print

Description: This file implements login/logout handling functions. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements login/logout handling functions.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * {@internal License choice
  12   * - If you have received this file as part of a package, please find the license.txt file in
  13   *   the same folder or the closest folder above for complete license terms.
  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15   *   then you must choose one of the following licenses before using the file:
  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18   * }}
  19   *
  20   * {@internal Open Source relicensing agreement:
  21   * Daniel HAHLER grants Francois PLANQUE the right to license
  22   * Daniel HAHLER's contributions to this file and the b2evolution project
  23   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  24   * }}
  25   *
  26   * @package evocore
  27   *
  28   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  29   * @author cafelog (team)
  30   * @author blueyed: Daniel HAHLER.
  31   * @author fplanque: Francois PLANQUE.
  32   * @author jeffbearer: Jeff BEARER - {@link http://www.jeffbearer.com/}.
  33   * @author jupiterx: Jordan RUNNING.
  34   *
  35   * @version $Id: _user.funcs.php 6136 2014-03-08 07:59:48Z manuel $
  36   */
  37  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  38  
  39  load_class( 'users/model/_group.class.php', 'Group' );
  40  load_class( 'users/model/_user.class.php', 'User' );
  41  
  42  
  43  /**
  44   * Log the user out
  45   */
  46  function logout()
  47  {
  48      global $current_User, $Session, $Plugins;
  49  
  50      $Plugins->trigger_event( 'Logout', array( 'User' => $current_User ) );
  51  
  52      // Reset all global variables
  53      // Note: unset is bugguy on globals
  54      $current_User = NULL; // NULL, as we do isset() on it in several places!
  55  
  56      $Session->logout();
  57  }
  58  
  59  
  60  /**
  61   * is_logged_in(-)
  62   *
  63   * @param boolean true if not active users are considerated as logged in users, false otherwise
  64   */
  65  function is_logged_in( $accept_not_active = true )
  66  {
  67      global $current_User;
  68  
  69      return is_object( $current_User ) && !empty( $current_User->ID ) && ( $accept_not_active || $current_User->check_status( 'is_validated' ) );
  70  }
  71  
  72  
  73  /**
  74   * Check if current User status permit the give action
  75   *
  76   * @param string action
  77   * @param integger target ID - can be a post ID, user ID
  78   * @return boolean true if the user is loggedn in and the action is permitted, false otherwise
  79   */
  80  function check_user_status( $action, $target = NULL )
  81  {
  82      global $current_User;
  83  
  84      if( !is_logged_in() )
  85      {
  86          return false;
  87      }
  88  
  89      return $current_User->check_status( $action, $target );
  90  }
  91  
  92  
  93  /**
  94   * Check if a password is ok for a login.
  95   *
  96   * @param string login
  97   * @param string password
  98   * @param boolean Is the password parameter already MD5()'ed?
  99   * @return boolean
 100   */
 101  function user_pass_ok( $login, $pass, $pass_is_md5 = false )
 102  {
 103      $UserCache = & get_UserCache();
 104      $User = & $UserCache->get_by_login( $login );
 105      if( !$User )
 106      {
 107          return false;
 108      }
 109      // echo 'got data for: ', $User->login;
 110  
 111      return $User->check_password( $pass, $pass_is_md5 );
 112  }
 113  
 114  
 115  /**
 116   * Template tag: Output link to login
 117   */
 118  function user_login_link( $before = '', $after = '', $link_text = '', $link_title = '#', $source = 'user login link' )
 119  {
 120      echo get_user_login_link( $before, $after, $link_text, $link_title, $source );
 121  }
 122  
 123  
 124  /**
 125   * Get link to login
 126   *
 127   * @param string Text before link
 128   * @param string Text after link
 129   * @param string Link text
 130   * @param string Link title
 131   * @param string Source
 132   * @return string Link for log in
 133   */
 134  function get_user_login_link( $before = '', $after = '', $link_text = '', $link_title = '#', $source = 'user login link', $redirect_to = NULL )
 135  {
 136      if( is_logged_in() ) return false;
 137  
 138      if( $link_text == '' ) $link_text = T_('Log in');
 139      if( $link_title == '#' ) $link_title = T_('Log in if you have an account...');
 140  
 141      $r = $before;
 142      $r .= '<a href="'.get_login_url( $source, $redirect_to ).'" title="'.$link_title.'">';
 143      $r .= $link_text;
 144      $r .= '</a>';
 145      $r .= $after;
 146  
 147      return $r;
 148  }
 149  
 150  
 151  /**
 152   * Get user's login with gender color
 153   *
 154   * @param string Login
 155   * @param array Params
 156   * @return string User's preferred name with gender color if this available
 157   */
 158  function get_user_colored_login( $login, $params = array() )
 159  {
 160      $params = array_merge( array(
 161              'mask' => '$avatar$ $login$'
 162          ) );
 163  
 164      $UserCache = & get_UserCache();
 165      $User = & $UserCache->get_by_login( $login );
 166      if( !$User )
 167      { // User doesn't exist by some reason, maybe it was deleted right now
 168          // Return only login
 169          return $login;
 170      }
 171  
 172      return $User->get_colored_login( $params );
 173  }
 174  
 175  
 176  /**
 177   * Get url to login
 178   *
 179   * @param string describe the source ina word or two, used for stats (search current calls to this function for examples)
 180   * @param string
 181   * @return string
 182   */
 183  function get_login_url( $source, $redirect_to = NULL )
 184  {
 185      global $edited_Blog, $secure_htsrv_url;
 186  
 187      if( !empty( $redirect_to ) )
 188      {
 189          $redirect = $redirect_to;
 190      }
 191      else
 192      {
 193          $redirect = regenerate_url( '', '', '', '&' );
 194      }
 195  
 196      if( use_in_skin_login() )
 197      { // use in-skin login
 198          global $blog;
 199          $BlogCache = & get_BlogCache();
 200          $Blog = $BlogCache->get_by_ID( $blog );
 201          if( ! empty($redirect) )
 202          {
 203              $redirect = 'redirect_to='.rawurlencode( url_rel_to_same_host( $redirect, $Blog->get( 'loginurl' ) ) );
 204          }
 205          $url = url_add_param( $Blog->get( 'loginurl' ), $redirect, '&' );
 206      }
 207      else
 208      { // Normal login
 209          if( ! empty($redirect) )
 210          {
 211              $redirect = '?redirect_to='.rawurlencode( url_rel_to_same_host( $redirect, $secure_htsrv_url ) );
 212          }
 213          $url = $secure_htsrv_url.'login.php'.$redirect;
 214      }
 215  
 216      return url_add_param( $url, 'source='.rawurlencode($source), '&' );
 217  }
 218  
 219  
 220  /**
 221   * Get url to show user activate info screen
 222   */
 223  function get_activate_info_url( $redirect_to = NULL )
 224  {
 225      global $Blog, $secure_htsrv_url;
 226  
 227      if( empty( $redirect_to ) )
 228      { // redirect back to current URL
 229          $redirect_to = rawurlencode( url_rel_to_same_host( regenerate_url( '', '', '', '&' ), $secure_htsrv_url ) );
 230      }
 231  
 232      if( use_in_skin_login() )
 233      { // use in-skin login is set, use in-skin activate info page
 234          return url_add_param( $Blog->gen_blogurl(), 'disp=activateinfo&redirect_to='.$redirect_to, '&' );
 235      }
 236  
 237      return $secure_htsrv_url.'login.php?action=req_validatemail&redirect_to='.$redirect_to;
 238  }
 239  
 240  
 241  /**
 242   * Get url where to redirect, after successful account activation
 243   */
 244  function redirect_after_account_activation()
 245  {
 246      global $Settings, $Session, $baseurl;
 247  
 248      // Get general "Users setting" to determine if we want to return to original page after account activation or to a specific url:
 249      $redirect_to = $Settings->get( 'after_email_validation' );
 250      if( $redirect_to == 'return_to_original' )
 251      { // we want to return to original page after account activation
 252          // the redirect_to param should be set in the Session. This was set when the account activation email was sent.
 253          $redirect_to = $Session->get( 'core.validatemail.redirect_to' );
 254          // if the redirect_to is not set in the Session or is empty, we MUST NEVER let to redirect back to the origianl page which can be hotmail, gmail, etc.
 255          if( empty( $redirect_to ) )
 256          { // session redirect_to was not set, initialize $redirect_to to the home page
 257              $redirect_to = $baseurl;
 258          }
 259      }
 260  
 261      return $redirect_to;
 262  }
 263  
 264  
 265  /**
 266   * Send notification to users with edit users permission
 267   *
 268   * @param string notification email suject
 269   * @param string notificaiton email template name
 270   * @param array notification email template params
 271   */
 272  function send_admin_notification( $subject, $template_name, $template_params )
 273  {
 274      global $Session, $UserSettings, $current_User;
 275  
 276      $UserCache = & get_UserCache();
 277      $template_params = array_merge( array(
 278              'login' => '',
 279          ), $template_params );
 280  
 281      // Set default subject and permname:
 282      $subject_suffix = ': '.$template_params['login'];
 283      $perm_name = 'users';
 284  
 285      switch( $template_name )
 286      {
 287          case 'account_new':
 288              $check_setting = 'notify_new_user_registration';
 289              break;
 290  
 291          case 'account_activated':
 292              $check_setting = 'notify_activated_account';
 293              break;
 294  
 295          case 'account_closed':
 296              $check_setting = 'notify_closed_account';
 297              break;
 298  
 299          case 'account_reported':
 300              $check_setting = 'notify_reported_account';
 301              break;
 302  
 303          case 'scheduled_task_error_report':
 304              $subject_suffix = '';
 305              $check_setting = 'notify_cronjob_error';
 306              $perm_name = 'options';
 307              break;
 308  
 309          default:
 310              debug_die( 'Unhandled admin notification template!' );
 311      }
 312  
 313      if( empty( $current_User ) && !empty( $Session ) && $Session->has_User() )
 314      { // current_User is not set at the time of registration
 315          $current_User = & $Session->get_User();
 316      }
 317  
 318      if( empty( $UserSettings ) )
 319      { // initialize UserSettings
 320          load_class( 'users/model/_usersettings.class.php', 'UserSettings' );
 321          $UserSettings = new UserSettings();
 322      }
 323  
 324      // load users with edit all users permission
 325      $UserCache->load_where( 'user_grp_ID = 1 OR user_grp_ID IN ( SELECT gset_grp_ID FROM T_groups__groupsettings WHERE gset_name = "perm_'.$perm_name.'" AND gset_value = "edit" )' );
 326      // iterate through UserCache
 327      $UserCache->rewind();
 328      while( $User = & $UserCache->get_next() )
 329      { // Loop through Users
 330          if( is_logged_in() && $current_User->ID == $User->ID )
 331          { // Don't send a notification to current user, because he already knows about this event
 332              continue;
 333          }
 334          if( $UserSettings->get( $check_setting, $User->ID ) && $User->check_perm( $perm_name, 'edit' ) )
 335          { // this user must be notifed
 336              locale_temp_switch( $User->get( 'locale' ) );
 337              // send mail to user (using his local)
 338              $localized_subject = T_( $subject ).$subject_suffix;
 339              send_mail_to_User( $User->ID, $localized_subject, $template_name, $template_params ); // ok, if this may fail
 340              locale_restore_previous();
 341          }
 342      }
 343  }
 344  
 345  
 346  /**
 347   * Use in-skin login
 348   */
 349  function use_in_skin_login()
 350  {
 351      global $Blog, $blog;
 352  
 353      if( is_admin_page() )
 354      {
 355          return false;
 356      }
 357  
 358      if( !isset( $blog ) )
 359      {
 360          return false;
 361      }
 362  
 363      $BlogCache = & get_BlogCache();
 364      $Blog = $BlogCache->get_by_ID( $blog, false, false );
 365      if( empty( $Blog ) )
 366      {
 367          return false;
 368      }
 369  
 370      return $Blog->get_setting( 'in_skin_login' );
 371  }
 372  
 373  
 374  /**
 375   * Check if show toolbar
 376   */
 377  function show_toolbar()
 378  {
 379      global $current_User;
 380      return ( is_logged_in() && ( $current_User->check_perm( 'admin', 'toolbar' ) ) );
 381  }
 382  
 383  
 384  /**
 385   * Check a settings from user for Back office and from skin for Front office
 386   *
 387   * @param string Setting name ( gender_colored OR bubbletip)
 388   * @return bool Use colored gender
 389   */
 390  function check_setting( $setting_name )
 391  {
 392      global $Settings, $Blog, $SkinCache;
 393  
 394      if( ! isset( $Blog ) && ! is_admin_page() )
 395      {    // If we use some page without blog data
 396          return false;
 397      }
 398  
 399      if( is_admin_page() )
 400      {    // Check setting in the Back office
 401          if( $Settings->get( $setting_name ) )
 402          {    // Set TRUE if the setting is ON
 403              return true;
 404          }
 405      }
 406      else
 407      {    // Check setting in the Front office for current blog & skin
 408          global $Blog, $SkinCache;
 409          if( ! isset( $SkinCache ) )
 410          {    // Init $SkinCache if it doesn't still exist
 411              $SkinCache = & get_SkinCache();
 412          }
 413          $skin = & $SkinCache->get_by_ID( $Blog->get( 'skin_ID' ) );
 414          if( $skin->get_setting( $setting_name ) )
 415          { // If setting is ON for current Blog & Skin
 416              if( $setting_name == 'bubbletip' )
 417              {    // Check separate case for setting 'bubbletip'
 418                  if( is_logged_in() || $Settings->get( $setting_name.'_anonymous' ) )
 419                  {    // If user is logged in OR Anonymous user can see bubbletips
 420                      return true;
 421                  }
 422              }
 423              else
 424              { // Setting 'gender_colored' doesn't depend on user's logged status
 425                  return true;
 426              }
 427          }
 428      }
 429  
 430      return false;
 431  }
 432  
 433  
 434  /**
 435   * Template tag: Output a link to new user registration
 436   * @param string
 437   * @param string
 438   * @param string
 439   * @param boolean Display the link, if the user is already logged in? (this is used by the login form)
 440   * @param string used for source tracking if $source is not already set
 441   */
 442  function user_register_link( $before = '', $after = '', $link_text = '', $link_title = '#', $disp_when_logged_in = false, $default_source_string = '' )
 443  {
 444      echo get_user_register_link( $before, $after, $link_text, $link_title, $disp_when_logged_in, NULL, $default_source_string );
 445  }
 446  
 447  
 448  /**
 449   * Template tag: Get a link to new user registration
 450   *
 451   * @param string
 452   * @param string
 453   * @param string
 454   * @param string
 455   * @param boolean Display the link, if the user is already logged in? (this is used by the login form)
 456   * @param string Where to redirect
 457   * @return string used for source tracking
 458   */
 459  function get_user_register_link( $before = '', $after = '', $link_text = '', $link_title = '#',
 460          $disp_when_logged_in = false, $redirect = null, $default_source_string = '' )
 461  {
 462      $register_url = get_user_register_url( $redirect, $default_source_string, $disp_when_logged_in );
 463  
 464      if( !$register_url )
 465      {
 466          return false;
 467      }
 468  
 469      if( $link_text == '' ) $link_text = T_('Register').' &raquo;';
 470      if( $link_title == '#' ) $link_title = T_('Register for a new account...');
 471  
 472      $r = $before;
 473      $r .= '<a href="'.$register_url.'" title="'.$link_title.'">';
 474      $r .= $link_text;
 475      $r .= '</a>';
 476      $r .= $after;
 477      return $r;
 478  }
 479  
 480  
 481  /**
 482   * Get a user registration url
 483   *
 484   * @param string redirect to url
 485   * @param string where this registration url will be displayed
 486   * @param boolean force to display even when a user is logged in
 487   * @param string delimiter to use for more url params
 488   */
 489  function get_user_register_url( $redirect = NULL, $default_source_string = '', $disp_when_logged_in = false, $glue = '&amp;' )
 490  {
 491      global $Settings, $edited_Blog, $secure_htsrv_url;
 492  
 493      if( is_logged_in() && ! $disp_when_logged_in )
 494      { // Do not display, when already logged in:
 495          return false;
 496      }
 497  
 498      if( ! $Settings->get('newusers_canregister'))
 499      { // We won't let him register
 500          return false;
 501      }
 502  
 503      if( use_in_skin_login() )
 504      {
 505          global $blog;
 506  
 507          $BlogCache = & get_BlogCache();
 508          $Blog = $BlogCache->get_by_ID( $blog );
 509  
 510          $register_url = url_add_param( $Blog->get( 'url' ), 'disp=register', $glue );
 511      }
 512      else
 513      {
 514          $register_url = $secure_htsrv_url.'register.php';
 515      }
 516  
 517      // Source=
 518      $source = param( 'source', 'string', '' );
 519      if( empty($source) )
 520      {
 521          $source = $default_source_string;
 522      }
 523      if( ! empty($source) )
 524      {
 525          $register_url = url_add_param( $register_url, 'source='.rawurlencode($source), $glue );
 526      }
 527  
 528      // Redirect_to=
 529      if( ! isset($redirect) )
 530      {
 531          $redirect = regenerate_url( '', '', '', $glue );
 532      }
 533  
 534      if( ! empty($redirect) )
 535      {
 536          $register_url = url_add_param( $register_url, 'redirect_to='.rawurlencode( url_rel_to_same_host( $redirect, $secure_htsrv_url ) ), $glue );
 537      }
 538  
 539      return $register_url;
 540  }
 541  
 542  
 543  /**
 544   * Template tag: Output a link to logout
 545   */
 546  function user_logout_link( $before = '', $after = '', $link_text = '', $link_title = '#', $params = array() )
 547  {
 548      echo get_user_logout_link( $before, $after, $link_text, $link_title, $params );
 549  }
 550  
 551  
 552  /**
 553   * Template tag: Get a link to logout
 554   *
 555   * @param string
 556   * @param string
 557   * @param string link text can include %s for current user login
 558   * @return string
 559   */
 560  function get_user_logout_link( $before = '', $after = '', $link_text = '', $link_title = '#', $params = array() )
 561  {
 562      global $current_User;
 563  
 564      if( ! is_logged_in() )
 565      {
 566          return false;
 567      }
 568  
 569      if( $link_text == '' ) $link_text = T_('Logout');
 570      if( $link_title == '#' ) $link_title = T_('Logout from your account');
 571  
 572      $r = $before;
 573      $r .= '<a href="'.get_user_logout_url().'"';
 574      $r .= get_field_attribs_as_string( $params, false );
 575      $r .= ' title="'.$link_title.'">';
 576      $r .= sprintf( $link_text, $current_User->login );
 577      $r .= '</a>';
 578      $r .= $after;
 579      return $r;
 580  }
 581  
 582  
 583  /**
 584   * Get the URL for the logout button
 585   *
 586   * @return string
 587   */
 588  function get_user_logout_url()
 589  {
 590      global $admin_url, $baseurl, $is_admin_page, $Blog, $secure_htsrv_url;
 591  
 592      if( ! is_logged_in() )
 593      {
 594          return false;
 595      }
 596  
 597      $redirect_to = url_rel_to_same_host( regenerate_url( 'disp,action','','','&' ), $secure_htsrv_url );
 598      if( require_login( $redirect_to, true ) )
 599      { // if redirect_to page is a login page, or also require login ( e.g. admin.php )
 600          if( !empty( $Blog ) )
 601          { // Blog is set
 602              // set redirect_to to Blog url
 603              $redirect_to = $Blog->gen_blogurl();
 604          }
 605          else
 606          { // Blog is empty, set abort url to baseurl
 607              $redirect_to =  url_rel_to_same_host( $baseurl, $secure_htsrv_url );
 608          }
 609      }
 610  
 611      return $secure_htsrv_url.'login.php?action=logout&amp;redirect_to='.rawurlencode($redirect_to);
 612  }
 613  
 614  
 615  /**
 616   * Template tag: Output a link to the backoffice.
 617   *
 618   * Usually provided in skins in order for newbies to find the admin interface more easily...
 619   *
 620   * @param string To be displayed before the link.
 621   * @param string To be displayed after the link.
 622   * @param string The page/controller to link to inside of {@link $admin_url}
 623   * @param string Text for the link.
 624   * @param string Title for the link.
 625   */
 626  function user_admin_link( $before = '', $after = '', $link_text = '', $link_title = '#', $not_visible = '' )
 627  {
 628      echo get_user_admin_link( $before, $after, $link_text, $link_title, $not_visible );
 629  }
 630  
 631  
 632  /**
 633   * Template tag: Get a link to the backoffice.
 634   *
 635   * Usually provided in skins in order for newbies to find the admin interface more easily...
 636   *
 637   * @param string To be displayed before the link.
 638   * @param string To be displayed after the link.
 639   * @param string The page/controller to link to inside of {@link $admin_url}
 640   * @param string Text for the link.
 641   * @param string Title for the link.
 642   * @return string
 643   */
 644  function get_user_admin_link( $before = '', $after = '', $link_text = '', $link_title = '#', $not_visible = '' )
 645  {
 646      global $admin_url, $blog, $current_User;
 647  
 648      if( is_logged_in() && ! $current_User->check_perm( 'admin', 'normal' ) )
 649      { // If user should NOT see admin link:
 650          return $not_visible;
 651      }
 652  
 653      if( $link_text == '' ) $link_text = T_('Admin');
 654      if( $link_title == '#' ) $link_title = T_('Go to the back-office...');
 655      // add the blog param to $page if it is not already in there
 656  
 657      if( !empty( $blog ) )
 658      {
 659          $url = url_add_param( $admin_url, 'blog='.$blog );
 660      }
 661      else
 662      {
 663          $url = $admin_url;
 664      }
 665  
 666      $r = $before;
 667      $r .= '<a href="'.$url.'" title="'.$link_title.'">';
 668      $r .= $link_text;
 669      $r .= '</a>';
 670      $r .= $after;
 671      return $r;
 672  }
 673  
 674  
 675  /**
 676   * Template tag: Display a link to user profile
 677   */
 678  function user_profile_link( $before = '', $after = '', $link_text = '', $link_title = '#' )
 679  {
 680      echo get_user_profile_link( $before, $after, $link_text, $link_title );
 681  }
 682  
 683  
 684  /**
 685   * Template tag: Get a link to user profile
 686   *
 687   * @return string|false
 688   */
 689  function get_user_profile_link( $before = '', $after = '', $link_text = '', $link_title = '#' )
 690  {
 691      global $current_User;
 692  
 693      if( ! is_logged_in() )
 694      {
 695          return false;
 696      }
 697  
 698      if( $link_text == '' )
 699      {
 700          $link_text = T_('Profile');
 701      }
 702      else
 703      {
 704          $link_text = str_replace( '%s', $current_User->login, $link_text );
 705      }
 706      if( $link_title == '#' ) $link_title = T_('Edit your profile');
 707  
 708      $r = $before
 709          .'<a href="'.get_user_profile_url().'" title="'.$link_title.'">'
 710          .sprintf( $link_text, $current_User->login )
 711          .'</a>'
 712          .$after;
 713  
 714      return $r;
 715  }
 716  
 717  
 718  /**
 719   * Template tag: Display a link to user tab
 720   */
 721  function user_tab_link( $user_tab = 'user', $before = '', $after = '', $link_text = '', $link_title = '#' )
 722  {
 723      echo get_user_tab_link( $user_tab, $before, $after, $link_text, $link_title );
 724  }
 725  
 726  
 727  /**
 728   * Template tag: Get a link to view user
 729   *
 730   * @return string|false
 731   */
 732  function get_user_tab_link( $user_tab = 'user', $before = '', $after = '', $link_text = '#', $link_title = '#' )
 733  {
 734      if( ! is_logged_in() )
 735      {
 736          return false;
 737      }
 738  
 739      $user_tab_url = get_user_settings_url( $user_tab );
 740  
 741      if( empty( $user_tab_url ) )
 742      {
 743          return false;
 744      }
 745  
 746      if( $link_text == '#' )
 747      {
 748          $link_text = T_('My profile');
 749      }
 750  
 751      if( $link_title == '#' )
 752      {
 753          $link_title = T_('My profile');
 754      }
 755  
 756      $r = $before
 757          .'<a href="'.$user_tab_url.'" title="'.$link_title.'">'
 758          .$link_text
 759          .'</a>'
 760          .$after;
 761  
 762      return $r;
 763  }
 764  
 765  
 766  /**
 767   * Get URL to edit user profile
 768   */
 769  function get_user_profile_url()
 770  {
 771      return get_user_settings_url( 'profile' );
 772  }
 773  
 774  
 775  /**
 776   * Get URL to edit user avatar
 777   */
 778  function get_user_avatar_url()
 779  {
 780      return get_user_settings_url( 'avatar' );
 781  }
 782  
 783  
 784  /**
 785   * Get URL to change user password
 786   */
 787  function get_user_pwdchange_url()
 788  {
 789      return get_user_settings_url( 'pwdchange' );
 790  }
 791  
 792  
 793  /**
 794   * Get URL to edit user preferences
 795   */
 796  function get_user_preferences_url()
 797  {
 798      return get_user_settings_url( 'userprefs' );
 799  }
 800  
 801  
 802  /**
 803   * Template tag: Provide a link to subscription screen
 804   */
 805  function user_subs_link( $before = '', $after = '', $link_text = '', $link_title = '#' )
 806  {
 807      echo get_user_subs_link( $before, $after, $link_text, $link_title );
 808  }
 809  
 810  
 811  /**
 812   * Get a link to subscription screen
 813   */
 814  function get_user_subs_link( $before = '', $after = '', $link_text = '', $link_title = '#' )
 815  {
 816      global $current_User;
 817  
 818      if( ! $url = get_user_subs_url() )
 819      {
 820          return false;
 821      }
 822  
 823      if( $link_text == '' ) $link_text = T_('Subscribe');
 824      if( $link_title == '#' ) $link_title = T_('Subscribe to email notifications');
 825  
 826      $r = $before
 827          .'<a href="'.$url.'" title="'.$link_title.'">'
 828          .sprintf( $link_text, $current_User->login )
 829          .'</a>'
 830          .$after;
 831  
 832      return $r;
 833  }
 834  
 835  
 836  /**
 837   * Get url to set notificaitons/subscription screen
 838   *
 839   * @return string Url to subscription screen
 840   */
 841  function get_user_subs_url()
 842  {
 843      return get_user_settings_url( 'subs' );
 844  }
 845  
 846  /**
 847   * Get User identity link. User is given with his login or ID. User login or ID must be set.
 848   *
 849   * @param string User login ( can be NULL if ID is set )
 850   * @param integer User ID ( can be NULL if login is set )
 851   * @param string On which user profile tab should this link point to
 852   * @return NULL|string NULL if this user or the profile tab doesn't exists, the identity link otherwise.
 853   */
 854  function get_user_identity_link( $user_login, $user_ID = NULL, $profile_tab = 'profile', $link_text = 'avatar' )
 855  {
 856      $UserCache = & get_UserCache();
 857  
 858      if( empty( $user_login ) )
 859      {
 860          $User = & $UserCache->get_by_ID( $user_ID, false, false );
 861          if( !$User )
 862          { // user with given user_ID doesn't exist
 863              return NULL;
 864          }
 865      }
 866      else
 867      {
 868          $User = & $UserCache->get_by_login( $user_login );
 869      }
 870  
 871      if( $User == false )
 872      {
 873          return NULL;
 874      }
 875  
 876      return $User->get_identity_link( array( 'profile_tab' => $profile_tab, 'link_text' => $link_text ) );
 877  }
 878  
 879  
 880  /**
 881   * Get the available user display url
 882   *
 883   * @param integer User ID
 884   * @param string Name of user tab in backoffice ( values: profile, avatar, pwdchange, userprefs, advanced, admin, blogs )
 885   * @return string Url
 886   */
 887  function get_user_identity_url( $user_ID, $user_tab = 'profile' )
 888  {
 889      global $current_User, $Blog, $Settings;
 890  
 891      if( $user_ID == NULL )
 892      {
 893          return NULL;
 894      }
 895  
 896      $UserCache = & get_UserCache();
 897      $User = $UserCache->get_by_ID( $user_ID, false );
 898  
 899      if( empty( $User ) )
 900      {
 901          return NULL;
 902      }
 903  
 904      if( !$User->check_status( 'can_display_link' ) && !( is_admin_page() && is_logged_in( false ) && ( $current_User->check_perm( 'users', 'edit' ) ) ) )
 905      { // if the account status restrict to display user profile link and current User is not an admin in admin interface, then do not return identity url!
 906          return NULL;
 907      }
 908  
 909      if( !is_logged_in() )
 910      { // user is not logged in
 911          if( $Settings->get( 'allow_anonymous_user_profiles' ) && ( isset( $Blog ) ) )
 912          {
 913              return url_add_param( $Blog->gen_blogurl(), 'disp=user&amp;user_ID='.$user_ID );
 914          }
 915          // return NULL if user is not logged in and display is not allowed or Blog is not set
 916          return NULL;
 917      }
 918  
 919      if( !$current_User->check_status( 'can_view_user', $User->ID ) )
 920      { // if the current user status restrict to view other user profile
 921          return NULL;
 922      }
 923  
 924      if( isset($Blog) && !is_admin_page() )
 925      {    // can't display the profile form, display the front office User form
 926          return url_add_param( $Blog->gen_blogurl(), 'disp=user&amp;user_ID='.$user_ID );
 927      }
 928  
 929      if( $current_User->check_status( 'can_access_admin' ) && ( ($current_User->ID == $user_ID ) || $current_User->check_perm( 'users', 'view' ) ) )
 930      {    // Go to backoffice profile:
 931          return get_user_settings_url( $user_tab, $user_ID );
 932      }
 933  
 934      // can't show anything:
 935      return NULL;
 936  }
 937  
 938  
 939  /**
 940   * Get URL to a specific user settings tab (profile, avatar, pwdchange, userprefs)
 941   *
 942   * @param string user tab
 943   * @param integer user ID for the requested user. If isn't set then return $current_User settings url.
 944   */
 945  function get_user_settings_url( $user_tab, $user_ID = NULL )
 946  {
 947      global $current_User, $Blog, $is_admin_page, $admin_url, $ReqURI;
 948  
 949      if( !is_logged_in() )
 950      {
 951          debug_die( 'Active user not found.' );
 952      }
 953  
 954      if( in_array( $user_tab, array( 'advanced', 'admin', 'sessions', 'activity' ) ) )
 955      {
 956          $is_admin_tab = true;
 957      }
 958      else
 959      {
 960          $is_admin_tab = false;
 961      }
 962  
 963      if( ( !$is_admin_tab ) && ( ! in_array( $user_tab, array( 'profile', 'user', 'avatar', 'pwdchange', 'userprefs', 'subs', 'report' ) ) ) )
 964      {
 965          debug_die( 'Not supported user tab!' );
 966      }
 967  
 968      if( $user_ID == NULL )
 969      {
 970          $user_ID = $current_User->ID;
 971      }
 972  
 973      if( $is_admin_page || $is_admin_tab || empty( $Blog ) || $current_User->ID != $user_ID )
 974      {
 975          if( ( $current_User->ID != $user_ID ) && ( ! $current_User->check_perm( 'users', 'view' ) ) )
 976          {
 977              return NULL;
 978          }
 979          if( ( $user_tab == 'admin' ) && ( $current_User->grp_ID != 1 ) )
 980          {
 981              $user_tab = 'profile';
 982          }
 983          return $admin_url.'?ctrl=user&amp;user_tab='.$user_tab.'&amp;user_ID='.$user_ID;
 984      }
 985  
 986      return url_add_param( $Blog->gen_blogurl(), 'disp='.$user_tab );
 987  }
 988  
 989  
 990  /**
 991   * Template tag: Display a link to messaging module
 992   */
 993  function user_messaging_link( $before = '', $after = '', $link_text = '#', $link_title = '#', $show_badge = false )
 994  {
 995      echo get_user_messaging_link( $before, $after, $link_text, $link_title );
 996  }
 997  
 998  
 999  /**
1000   * Template tag: Get a link to messaging module
1001   *
1002   * @return string|false
1003   */
1004  function get_user_messaging_link( $before = '', $after = '', $link_text = '#', $link_title = '#', $show_badge = false )
1005  {
1006      global $unread_messages_count;
1007  
1008      $user_messaging_url = get_user_messaging_url();
1009  
1010      if( !$user_messaging_url )
1011      {    // Messages link is not available
1012          return false;
1013      }
1014  
1015      if( $link_text == '#' )
1016      {
1017          $link_text = T_('Messages');
1018      }
1019  
1020      if( $link_title == '#' )
1021      {
1022          $link_title = T_('Messages');
1023      }
1024  
1025      $badge = '';
1026      if( $show_badge && $unread_messages_count > 0 )
1027      {
1028          $badge = ' <span class="badge">'.$unread_messages_count.'</span>';
1029      }
1030  
1031      $r = $before
1032          .'<a href="'.$user_messaging_url.'" title="'.$link_title.'">'
1033          .$link_text
1034          .'</a>'
1035          .$badge
1036          .$after;
1037  
1038      return $r;
1039  }
1040  
1041  
1042  /**
1043   * Get URL to messaging module
1044   */
1045  function get_user_messaging_url()
1046  {
1047      global $current_User, $Blog;
1048  
1049      if( !is_logged_in() )
1050      {
1051          return false;
1052      }
1053  
1054      if( !$current_User->check_perm( 'perm_messaging', 'reply' ) )
1055      {    // No minimum permissions for messaging module
1056          return false;
1057      }
1058  
1059      return get_dispctrl_url( 'threads' );
1060  }
1061  
1062  
1063  /**
1064   * Template tag: Display a link to user contacts
1065   */
1066  function user_contacts_link( $before = '', $after = '', $link_text = '#', $link_title = '#' )
1067  {
1068      echo get_user_contacts_link( $before, $after, $link_text, $link_title );
1069  }
1070  
1071  
1072  /**
1073   * Template tag: Get a link to user contacts
1074   *
1075   * @return string|false
1076   */
1077  function get_user_contacts_link( $before = '', $after = '', $link_text = '#', $link_title = '#' )
1078  {
1079      $user_contacts_url = get_user_contacts_url();
1080  
1081      if( !$user_contacts_url )
1082      {    // Messages link is not available
1083          return false;
1084      }
1085  
1086      if( $link_text == '#' )
1087      {
1088          $link_text = T_('Messages');
1089      }
1090  
1091      if( $link_title == '#' )
1092      {
1093          $link_title = T_('Messages');
1094      }
1095  
1096      $r = $before
1097          .'<a href="'.$user_contacts_url.'" title="'.$link_title.'">'
1098          .$link_text
1099          .'</a>'
1100          .$after;
1101  
1102      return $r;
1103  }
1104  
1105  
1106  /**
1107   * Get URL to user contacts
1108   */
1109  function get_user_contacts_url()
1110  {
1111      global $current_User, $Blog;
1112  
1113      if( !is_logged_in() )
1114      {
1115          return false;
1116      }
1117  
1118      return get_dispctrl_url( 'contacts' );
1119  }
1120  
1121  
1122  /**
1123   * Get colored tag with user field "required"
1124   *
1125   * @param string required value
1126   * @param integer user ID for the requested user. If isn't set then return $current_User settings url.
1127   */
1128  function get_userfield_required( $value )
1129  {
1130      return '<span class="userfield '.$value.'">'.T_( $value ).'</span>';
1131  }
1132  
1133  
1134  /**
1135   * Template tag: Display the user's preferred name
1136   *
1137   * Used in result lists.
1138   *
1139   * @param integer user ID
1140   */
1141  function user_preferredname( $user_ID )
1142  {
1143      $UserCache = & get_UserCache();
1144      if( !empty( $user_ID )
1145          && ($User = & $UserCache->get_by_ID( $user_ID )) )
1146      {
1147          $User->disp('preferredname');
1148      }
1149  }
1150  
1151  
1152  /**
1153   * Check profile parameters and add errors through {@link param_error()}.
1154   *
1155   * @param array associative array.
1156   *     Either array( $value, $input_name ) or just $value;
1157   *     ($input_name gets used for associating it to a form fieldname)
1158   *     - 'login': check for non-empty
1159   *     - 'nickname': check for non-empty
1160   *     - 'icq': must be a number
1161   *     - 'email': mandatory, must be well formed
1162   *     - 'country': check for non-empty
1163   *     - 'url': must be well formed, in allowed scheme, not blacklisted
1164   *     - 'pass1' / 'pass2': passwords (twice), must be the same and not == login (if given)
1165   *     - 'pass_required': false/true (default is true)
1166   * @param User|NULL A user to use for additional checks (password != login/nick).
1167   */
1168  function profile_check_params( $params, $User = NULL )
1169  {
1170      global $Messages, $Settings;
1171  
1172      foreach( $params as $k => $v )
1173      {
1174          // normalize params:
1175          if( $k != 'pass_required' && ! is_array($v) )
1176          {
1177              $params[$k] = array($v, $k);
1178          }
1179      }
1180  
1181      // checking login has been typed:
1182      if( isset($params['login'][0]) )
1183      {
1184          if( empty( $params['login'][0] ) )
1185          { // login can't be empty
1186              param_error( $params['login'][1], T_('Please enter your login.') );
1187          }
1188          else
1189          {
1190              param_check_valid_login( 'login' );
1191          }
1192      }
1193  
1194      // checking e-mail address
1195      if( isset($params['email'][0]) )
1196      {
1197          if( empty($params['email'][0]) )
1198          {
1199              param_error( $params['email'][1], T_('Please enter your e-mail address.') );
1200          }
1201          elseif( !is_email($params['email'][0]) )
1202          {
1203              param_error( $params['email'][1], T_('The email address is invalid.') );
1204          }
1205      }
1206  
1207      // Checking country
1208      if( isset($params['country']) && empty($params['country'][0]) )
1209      {
1210          param_error( 'country', T_('Please select country.') );
1211      }
1212  
1213      // Checking first name
1214      if( isset($params['firstname']) && empty($params['firstname'][0]) )
1215      {
1216          param_error( 'firstname', T_('Please enter your first name.') );
1217      }
1218  
1219      // Checking gender
1220      if( isset($params['gender']) )
1221      {
1222          if( empty($params['gender'][0]) )
1223          {
1224              param_error( 'gender', T_('Please select gender.') );
1225          }
1226          elseif( ( $params['gender'][0] != 'M' ) && ( $params['gender'][0] != 'F' ) )
1227          {
1228              param_error( 'gender', 'Gender value is invalid' );
1229          }
1230      }
1231  
1232      // Checking URL:
1233      if( isset($params['url']) )
1234      {
1235          if( $error = validate_url( $params['url'][0], 'commenting' ) )
1236          {
1237              param_error( $params['url'][1], T_('Supplied URL is invalid: ').$error );
1238          }
1239      }
1240  
1241      // Check passwords:
1242  
1243      $pass_required = isset( $params['pass_required'] ) ? $params['pass_required'] : true;
1244  
1245      if( isset($params['pass1'][0]) && isset($params['pass2'][0]) )
1246      {
1247          if( $pass_required || !empty($params['pass1'][0]) || !empty($params['pass2'][0]) )
1248          { // Password is required or was given
1249              // checking the password has been typed twice
1250              if( empty($params['pass1'][0]) || empty($params['pass2'][0]) )
1251              {
1252                  param_error( $params['pass2'][1], T_('Please enter your password twice.') );
1253              }
1254  
1255              // checking the password has been typed twice the same:
1256              if( $params['pass1'][0] !== $params['pass2'][0] )
1257              {
1258                  param_error( $params['pass1'][1], T_('You typed two different passwords.') );
1259              }
1260              elseif( $Settings->get('passwd_special') && !preg_match('~[\x20-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]~', $params['pass1'][0] )  )
1261              {
1262                  param_error( $params['pass1'][1], T_('Your password should contain at least one special character (like & ! $ * - _ + etc.)') );
1263              }
1264              elseif( evo_strlen($params['pass1'][0]) < $Settings->get('user_minpwdlen') )
1265              {
1266                  param_error( $params['pass1'][1], sprintf( T_('The minimum password length is %d characters.'), $Settings->get('user_minpwdlen')) );
1267              }
1268              elseif( isset($User) && $params['pass1'][0] == $User->get('login') )
1269              {
1270                  param_error( $params['pass1'][1], T_('The password must be different from your login.') );
1271              }
1272              elseif( isset($User) && $params['pass1'][0] == $User->get('nickname') )
1273              {
1274                  param_error( $params['pass1'][1], T_('The password must be different from your nickname.') );
1275              }
1276          }
1277      }
1278  }
1279  
1280  
1281  /**
1282   * Get avatar <img> tag by user login
1283   *
1284   * @param user login
1285   * @param if true show user login after avatar
1286   * @param if true link to user profile
1287   * @param avatar size
1288   * @param style class of image
1289   * @param image align
1290   * @param avatar overlay text
1291   * @param style class of link
1292   * @param if true show user avatar
1293   * @return login <img> tag
1294   */
1295  function get_avatar_imgtag( $user_login, $show_login = true, $link = true, $size = 'crop-top-15x15', $img_class = 'avatar_before_login', $align = '', $avatar_overlay_text = '', $link_class = '', $show_avatar = true )
1296  {
1297      global $current_User;
1298  
1299      $UserCache = & get_UserCache();
1300      $User = & $UserCache->get_by_login( $user_login );
1301  
1302      if( $User === false )
1303      {
1304          return '';
1305      }
1306  
1307      $img_tag = '';
1308      if( $show_avatar )
1309      {    // Get user avatar
1310          $img_tag = $User->get_avatar_imgtag( $size, $img_class, $align, false, $avatar_overlay_text );
1311      }
1312  
1313      if( $show_login )
1314      {
1315          $img_tag = '<span class="nowrap">'.$img_tag.'<b>'.$user_login.'</b></span>';
1316      }
1317  
1318      $identity_url = get_user_identity_url( $User->ID );
1319      if( empty( $identity_url ) )
1320      {    // Current user has not permissions to view other user profile
1321          $img_tag = '<span class="'.$User->get_gender_class().'" rel="bubbletip_user_'.$User->ID.'">'.$img_tag.'</span>';
1322      }
1323      else if( !empty( $img_tag ) )
1324      {    // Show avatar & user login as link to the profile page
1325          $link_class = ( $link_class != '' ) ? ' '.$link_class : '';
1326          $img_tag = '<a href="'.$identity_url.'" class="'.$User->get_gender_class().$link_class.'" rel="bubbletip_user_'.$User->ID.'">'.$img_tag.'</a>';
1327      }
1328  
1329      return $img_tag;
1330  }
1331  
1332  
1333  /**
1334   * Get avatar <img> tags for list of user logins
1335   *
1336   * @param list of user logins
1337   * @param if true show user login after each avatar
1338   * @param avatar size
1339   * @param style class
1340   * @param image align
1341   * @param mixed read status, Set icon of the read status, 'left'/'left_message' - if user has left the conversation ( left messsage will display different title ), TRUE - users have seen message, FALSE - users have not seen the message
1342   *              leave it on NULL - to not display read status icon
1343   * @param if true show user avatar
1344   * @param separator between users
1345   * @param boolean set true to also show deleted users with 'Deleted user' label
1346   * @return coma separated login <img> tag
1347   */
1348  function get_avatar_imgtags( $user_logins_list, $show_login = true, $link = true, $size = 'crop-top-15x15', $class = 'avatar_before_login', $align = '', $read_status = NULL, $show_avatar = true, $separator = '<br />', $show_deleted_users = false )
1349  {
1350      if( !is_array( $user_logins_list ) )
1351      {
1352          $user_logins_list = explode( ', ', $user_logins_list );
1353      }
1354  
1355      $user_imgtags_list = array();
1356      foreach( $user_logins_list as $user_login )
1357      {
1358          $icon = '';
1359          if( ! is_null( $read_status ) )
1360          { // Add icon behind user login (read status)
1361              if( $read_status === 'left' )
1362              { // user has left the conversation
1363                  $icon = get_icon( 'bullet_black', 'imgtag', array( 'alt' => sprintf( T_('%s has left this conversation.'), $user_login ), 'style' => 'margin:1px 4px' ) );
1364              }
1365              elseif( $read_status === 'left_message' )
1366              { // user has left the conversation before this message
1367                  $icon = get_icon( 'bullet_black', 'imgtag', array( 'alt' => sprintf( T_('%s has left the conversation and has not received this message.'), $user_login ), 'style' => 'margin:1px 4px' ) );
1368              }
1369              elseif( $read_status )
1370              { // User has seen a message
1371                  $icon = get_icon( 'allowback', 'imgtag', array( 'alt' => sprintf( T_('%s has seen this message.'), $user_login ), 'style' => 'margin:0 2px' ) );
1372              }
1373              else
1374              { // User has not seen a message
1375                  $icon = get_icon( 'bullet_red', 'imgtag', array( 'alt' => sprintf( T_('%s has NOT seen this message yet.'), $user_login ), 'style' => 'margin:1px 4px' ) );
1376              }
1377          }
1378          if( empty( $user_login ) )
1379          { // user login is empty, we can't show avatar
1380              if( $show_deleted_users )
1381              { // show this users as deleted user
1382                  $user_imgtags_list[] = '<span class="nowrap">'.get_avatar_imgtag_default( $size, $class, $align ).'<span class="user deleted"><b>'.T_( 'Deleted user' ).'</b></span></span>';
1383              }
1384          }
1385          else
1386          {
1387              $user_imgtags_list[] = '<span class="nowrap">'.$icon.get_avatar_imgtag( $user_login, $show_login, $link, $size, $class, $align, '', '', $show_avatar ).'</span>';
1388          }
1389      }
1390      return implode( $separator, $user_imgtags_list );
1391  }
1392  
1393  
1394  /**
1395   * Get styled avatar
1396   *
1397   * @param integer user ID
1398   * @param array params
1399   * @return string
1400   */
1401  function get_user_avatar_styled( $user_ID, $params )
1402  {
1403      global $thumbnail_sizes;
1404  
1405      $params = array_merge( array(
1406              'block_class'  => 'avatar_rounded',
1407              'size'         => 'crop-top-64x64',
1408              'avatar_class' => 'avatar',
1409              'bubbletip'    => true,
1410          ), $params );
1411  
1412      $UserCache = & get_UserCache();
1413      $User = & $UserCache->get_by_ID( $user_ID, false, false );
1414  
1415      if( $User )
1416      { // requested user exists
1417          return $User->get_avatar_styled( $params );
1418      }
1419  
1420      // user doesn't exists because it was deleted
1421      $bubbletip_param = '';
1422      if( $params['bubbletip'] )
1423      {    // Init bubbletip param
1424          $bubbletip_param = 'rel="bubbletip_user_'.$user_ID.'"';
1425      }
1426      $style_width = '';
1427      if( isset( $thumbnail_sizes[$params['size']] ) )
1428      {
1429          $style_width = ' style="width:'.$thumbnail_sizes[$params['size']][1].'px"';
1430      }
1431  
1432      $result = '<div class="'.$params['block_class'].'" '.$bubbletip_param.$style_width.'>'
1433               .get_avatar_imgtag_default( $params['size'], $params['avatar_class'] )
1434               .'<span class="user deleted">'.T_( 'Deleted user' ).'</span>'
1435               .'</div>';
1436      return $result;
1437  }
1438  
1439  
1440  /**
1441   * Get avatar <img> tag with default picture
1442   *
1443   * @param avatar size
1444   * @param style class of image
1445   * @param image align
1446   * @return <img> tag
1447   */
1448  function get_avatar_imgtag_default( $size = 'crop-top-15x15', $class = '', $align = '', $params = array() )
1449  {
1450      global $Settings, $thumbnail_sizes;
1451  
1452      if( ! $Settings->get('allow_avatars') )
1453      { // Avatars are not allowed, Exit here
1454          return '';
1455      }
1456  
1457      // Default params:
1458      $params = array_merge( array(
1459              'email'    => '',
1460              'username' => '',
1461              'default'  => '',
1462          ), $params );
1463  
1464      if( ! $Settings->get('use_gravatar') )
1465      { // Gravatars are not allowed, Use default avatars instead
1466          global $default_avatar;
1467          $img_url = $default_avatar;
1468          $gravatar_width = isset( $thumbnail_sizes[$size] ) ? $thumbnail_sizes[$size][1] : '15';
1469          $gravatar_height = isset( $thumbnail_sizes[$size] ) ? $thumbnail_sizes[$size][2] : '15';
1470      }
1471      else
1472      { // Gravatars are enabled
1473          $default_gravatar = $Settings->get('default_gravatar');
1474  
1475          if( empty( $params['default'] ) )
1476          { // Set default gravatar
1477              if( $default_gravatar == 'b2evo' )
1478              { // Use gravatar from b2evo default avatar image
1479                  global $default_avatar;
1480                  $params['default'] = $default_avatar;
1481              }
1482              else
1483              { // Use a selected gravatar type
1484                  $params['default'] = $default_gravatar;
1485              }
1486          }
1487  
1488          if( empty( $img_url ) )
1489          {
1490              $img_url = 'http://www.gravatar.com/avatar/'.md5( $params['email'] );
1491              $gravatar_width = isset( $thumbnail_sizes[$size] ) ? $thumbnail_sizes[$size][1] : '15';
1492              $gravatar_height = $gravatar_width;
1493  
1494              $img_url_params = array();
1495              if( !empty( $params['rating'] ) )
1496              { // Rating
1497                  $img_url_params[] = 'rating='.$params['rating'];
1498              }
1499  
1500              if( !empty( $gravatar_width ) )
1501              { // Size
1502                  $img_url_params[] = 'size='.$gravatar_width;
1503              }
1504  
1505              if( !empty( $params['default'] ) )
1506              { // Type
1507                  $img_url_params[] = 'default='.urlencode( $params['default'] );
1508              }
1509  
1510              if( count( $img_url_params ) > 0 )
1511              { // Append url params to request gravatar
1512                  $img_url .= '?'.implode( '&', $img_url_params );
1513              }
1514          }
1515      }
1516  
1517      $img_params = array(
1518              'src'    => $img_url,
1519              'width'  => $gravatar_width,  // dh> NOTE: works with gravatar, check if extending
1520              'height' => $gravatar_height, // dh> NOTE: works with gravatar, check if extending
1521          );
1522  
1523      if( !empty( $params['username'] ) )
1524      { // Add alt & title
1525          $img_params['alt']   = $params['username'];
1526          $img_params['title'] = $params['username'];
1527      }
1528      if( !empty( $class ) )
1529      { // Add class
1530          $img_params['class'] = $class;
1531      }
1532      if( !empty( $align ) )
1533      { // Add align
1534          $img_params['align'] = $align;
1535      }
1536  
1537      return '<img'.get_field_attribs_as_string( $img_params ).' />';
1538  }
1539  
1540  
1541  /**
1542   * Convert seconds to months, days, hours, minutes and seconds format
1543   *
1544   * @param integer seconds
1545   * @return string
1546   */
1547  function duration_format( $duration, $show_seconds = true )
1548  {
1549      $result = '';
1550  
1551      $fields = get_duration_fields( $duration );
1552      if( $fields[ 'months' ] > 0 )
1553      {
1554          $result .= sprintf( T_( '%d months' ), $fields[ 'months' ] ).' ';
1555      }
1556      if( $fields[ 'days' ] > 0 )
1557      {
1558          $result .= sprintf( T_( '%d days' ), $fields[ 'days' ] ).' ';
1559      }
1560      if( $fields[ 'hours' ] > 0 )
1561      {
1562          $result .= sprintf( T_( '%d hours' ), $fields[ 'hours' ] ).' ';
1563      }
1564      if( $fields[ 'minutes' ] > 0 )
1565      {
1566          $result .= sprintf( T_( '%d minutes' ), $fields[ 'minutes' ] ).' ';
1567      }
1568      if( $show_seconds && ( $fields[ 'seconds' ] > 0 ) )
1569      {
1570          $result .= sprintf( T_( '%d seconds' ),  $fields[ 'seconds' ] );
1571      }
1572  
1573      $result = trim( $result );
1574      if( empty( $result ) )
1575      {
1576          $result = '0';
1577      }
1578  
1579      return $result;
1580  }
1581  
1582  
1583  /**
1584   * Get the integer value of a status permission
1585   * The status permissions are stored as a set, and each status has an integer value also
1586   *
1587   * @param string status
1588   * @return integer status perm value
1589   */
1590  function get_status_permvalue( $status )
1591  {
1592      static $status_permission_map = array(
1593              'trash'      => 0, // Note that 'trash' status doesn't have a real permission value, with this value no-one has permission, and that is OK
1594              'review'     => 1,
1595              'draft'      => 2,
1596              'private'    => 4,
1597              'protected'  => 8,
1598              'deprecated' => 16,
1599              'community'  => 32,
1600              'published'  => 64,
1601              'redirected' => 128
1602          );
1603  
1604      switch( $status )
1605      {
1606          case 'published_statuses':
1607              return $status_permission_map['protected'] + $status_permission_map['community'] + $status_permission_map['published'];
1608  
1609          default:
1610              break;
1611      }
1612  
1613      if( !isset( $status_permission_map[$status] ) )
1614      {
1615          debug_die( 'Invalid status permvalue was requested!' );
1616      }
1617  
1618      return $status_permission_map[$status];
1619  }
1620  
1621  
1622  /**
1623   * Load blog advanced User/Group permission
1624   *
1625   * @param array the array what should be loaded with the permission values ( it should be the User or Group blog_post_statuses array )
1626   * @param integer the target blog ID
1627   * @param integer the target User or Group ID
1628   * @param string the prefix which must be bloguser or bloggroup depends from where we call this fucntion
1629   * @return boolean true on success, false on failure
1630   */
1631  function load_blog_advanced_perms( & $blog_perms, $perm_target_blog, $perm_target_ID, $prefix )
1632  {
1633      global $DB;
1634  
1635      $BlogCache = & get_BlogCache();
1636      /**
1637       * @var Blog
1638       */
1639      $Blog = & $BlogCache->get_by_ID( $perm_target_blog );
1640      if( ! $Blog->advanced_perms )
1641      { // We do not abide to advanced perms
1642          return false;
1643      }
1644  
1645      if( empty( $perm_target_ID ) )
1646      { // Target object is not in DB, nothing to load!:
1647          return false;
1648      }
1649  
1650      if( !empty( $blog_perms ) )
1651      { // perms are already loaded, don't load again
1652          return false;
1653      }
1654  
1655      switch( $prefix )
1656      {
1657          case 'bloguser':
1658              $table = 'T_coll_user_perms';
1659              $perm_target_key = 'bloguser_user_ID';
1660              break;
1661  
1662          case 'bloggroup':
1663              $table = 'T_coll_group_perms';
1664              $perm_target_key = 'bloggroup_group_ID';
1665              break;
1666  
1667          default:
1668              debug_die( 'Invalid call of load blog permission' );
1669      }
1670  
1671      // Load now:
1672      $query = '
1673          SELECT *, '.$prefix.'_perm_poststatuses + 0 as perm_poststatuses_bin, '.$prefix.'_perm_cmtstatuses + 0 as perm_cmtstatuses_bin
1674            FROM '.$table.'
1675           WHERE '.$prefix.'_blog_ID = '.$perm_target_blog.'
1676             AND '.$perm_target_key.' = '.$perm_target_ID;
1677      $row = $DB->get_row( $query, ARRAY_A );
1678  
1679      if( empty($row) )
1680      { // No rights set for this Blog - User/Group: remember this (in order not to have the same query next time)
1681          $blog_perms = array(
1682                  'blog_ismember' => '0',
1683                  'blog_post_statuses' => 0,
1684                  'blog_edit' => 'no',
1685                  'blog_del_post' => '0',
1686                  'blog_edit_ts' => '0',
1687                  'blog_edit_cmt' => 'no',
1688                  'blog_del_cmts' => '0',
1689                  'blog_recycle_owncmts' => '0',
1690                  'blog_vote_spam_comments' => '0',
1691                  'blog_cmt_statuses' => 0,
1692                  'blog_cats' => '0',
1693                  'blog_properties' => '0',
1694                  'blog_admin' => '0',
1695                  'blog_page' => '0',
1696                  'blog_intro' => '0',
1697                  'blog_podcast' => '0',
1698                  'blog_sidebar' => '0',
1699                  'blog_media_upload' => '0',
1700                  'blog_media_browse' => '0',
1701                  'blog_media_change' => '0',
1702              );
1703      }
1704      else
1705      { // OK, rights found:
1706          $blog_perms['blog_ismember'] = $row[$prefix.'_ismember'];
1707  
1708          $blog_perms['blog_post_statuses'] = $row['perm_poststatuses_bin'];
1709          $blog_perms['blog_cmt_statuses'] = $row['perm_cmtstatuses_bin'];
1710  
1711          $blog_perms['blog_edit'] = $row[$prefix.'_perm_edit'];
1712          $blog_perms['blog_del_post'] = $row[$prefix.'_perm_delpost'];
1713          $blog_perms['blog_edit_ts'] = $row[$prefix.'_perm_edit_ts'];
1714          $blog_perms['blog_del_cmts'] = $row[$prefix.'_perm_delcmts'];
1715          $blog_perms['blog_recycle_owncmts'] = $row[$prefix.'_perm_recycle_owncmts'];
1716          $blog_perms['blog_vote_spam_comments'] = $row[$prefix.'_perm_vote_spam_cmts'];
1717          $blog_perms['blog_edit_cmt'] = $row[$prefix.'_perm_edit_cmt'];
1718          $blog_perms['blog_cats'] = $row[$prefix.'_perm_cats'];
1719          $blog_perms['blog_properties'] = $row[$prefix.'_perm_properties'];
1720          $blog_perms['blog_admin'] = $row[$prefix.'_perm_admin'];
1721          $blog_perms['blog_page'] = $row[$prefix.'_perm_page'];
1722          $blog_perms['blog_intro'] = $row[$prefix.'_perm_intro'];
1723          $blog_perms['blog_podcast'] = $row[$prefix.'_perm_podcast'];
1724          $blog_perms['blog_sidebar'] = $row[$prefix.'_perm_sidebar'];
1725          $blog_perms['blog_media_upload'] = $row[$prefix.'_perm_media_upload'];
1726          $blog_perms['blog_media_browse'] = $row[$prefix.'_perm_media_browse'];
1727          $blog_perms['blog_media_change'] = $row[$prefix.'_perm_media_change'];
1728      }
1729  
1730      return true;
1731  }
1732  
1733  
1734  /**
1735   * Check blog advanced user/group permission
1736   *
1737   * @param array blog user or group advanced permission settings
1738   * @param integer the user ID for whow we are checking the permission
1739   * @param string permission name
1740   * @param string permission level
1741   * @param Object permission target which can be a Comment or an Item depends from the permission what we are checking
1742   * @return boolean true if checked User/Group has permission, false otherwise
1743   */
1744  function check_blog_advanced_perm( & $blog_perms, $user_ID, $permname, $permlevel, $perm_target = NULL )
1745  {
1746      if( empty( $blog_perms ) )
1747      {
1748          return false;
1749      }
1750  
1751      // Check if permission is granted:
1752      switch( $permname )
1753      {
1754          case 'stats':
1755              // Wiewing stats is the same perm as being authorized to edit properties: (TODO...)
1756              if( $permlevel == 'view' )
1757              {
1758                  return $blog_perms['blog_properties'];
1759              }
1760              // No other perm can be granted here (TODO...)
1761              return false;
1762  
1763          case 'blog_post_statuses':
1764              // We grant this permission only if user has rights to create posts with any status different then 'deprecated' or 'redirected'
1765              $deprecated_value = get_status_permvalue( 'deprecated' );
1766              $redirected_value = get_status_permvalue( 'redirected' );
1767              return ( ( ~ ( $deprecated_value + $redirected_value ) ) & $blog_perms['blog_post_statuses'] ) > 0;
1768  
1769          case 'blog_comment_statuses':
1770              // We grant this permission only if user has rights to create comments with any status different then 'deprecated'
1771              $deprecated_value = get_status_permvalue( 'deprecated' );
1772              return ( ( ~ $deprecated_value ) & $blog_perms['blog_cmt_statuses'] ) > 0;
1773  
1774          case 'blog_comments':
1775              $edit_permname = 'blog_edit_cmt';
1776              $perm = ( $blog_perms['blog_cmt_statuses'] > 0 );
1777              break;
1778  
1779          case 'blog_post!published':
1780          case 'blog_post!community':
1781          case 'blog_post!protected':
1782          case 'blog_post!private':
1783          case 'blog_post!review':
1784          case 'blog_post!draft':
1785          case 'blog_post!deprecated':
1786          case 'blog_post!redirected':
1787              // We want a specific post permission:
1788              $status = substr( $permname, 10 );
1789              $edit_permname = 'blog_edit';
1790              $perm_statuses_value = $blog_perms['blog_post_statuses'];
1791              if( !empty( $perm_target ) )
1792              {
1793                  $Item = & $perm_target;
1794                  $creator_user_ID = $Item->creator_user_ID;
1795              }
1796  
1797              $perm = $perm_statuses_value & get_status_permvalue( $status );
1798              break;
1799  
1800          case 'blog_comment!published':
1801          case 'blog_comment!community':
1802          case 'blog_comment!protected':
1803          case 'blog_comment!private':
1804          case 'blog_comment!review':
1805          case 'blog_comment!draft':
1806          case 'blog_comment!deprecated':
1807              // We want a specific comment permission:
1808              $status = substr( $permname, 13 );
1809              $edit_permname = 'blog_edit_cmt';
1810              $perm_statuses_value = $blog_perms['blog_cmt_statuses'];
1811              if( !empty( $perm_target ) )
1812              {
1813                  $Comment = & $perm_target;
1814                  $creator_user_ID = $Comment->author_user_ID;
1815              }
1816  
1817              $perm = $perm_statuses_value & get_status_permvalue( $status );
1818              break;
1819  
1820          case 'files':
1821              switch( $permlevel )
1822              {
1823                  case 'add':
1824                      return $blog_perms['blog_media_upload'];
1825                  case 'view':
1826                      return $blog_perms['blog_media_browse'];
1827                  case 'edit':
1828                      return $blog_perms['blog_media_change'];
1829                  default:
1830                      return false;
1831              }
1832              break;
1833  
1834          case 'blog_edit':
1835          case 'blog_edit_cmt':
1836              if( $permlevel == 'no' )
1837              { // Doesn't make sensce to check that the user has at least 'no' permission
1838                  debug_die( 'Invalid edit pemlevel!' );
1839              }
1840              $edit_permvalue = $blog_perms[$permname];
1841              switch( $edit_permvalue )
1842              {
1843                  case 'all':
1844                      return true;
1845  
1846                  case 'le':
1847                      return $permlevel != 'all';
1848  
1849                  case 'lt':
1850                      return $permlevel != 'all' && $permlevel != 'le';
1851  
1852                  case 'anon':
1853                      return $permlevel == 'anon' || $permlevel == 'own';
1854  
1855                  case 'own':
1856                      return $permlevel == 'own';
1857  
1858                  default:
1859                      return false;
1860              }
1861  
1862          default:
1863              return $blog_perms[$permname];
1864      }
1865  
1866      // TODO: the following probably should be handled by the Item class!
1867      if( $perm && ( $permlevel == 'edit' || $permlevel == 'moderate' )
1868          && ( !empty( $creator_user_ID ) || ( !empty( $Comment ) ) ) ) // Check if Comment is not empty because in case of comments authors may be empty ( anonymous users )
1869      {    // Can we edit this specific Item/Comment?
1870          $edit_permvalue = $blog_perms[$edit_permname];
1871          switch( $edit_permvalue )
1872          {
1873              case 'own': // Own posts/comments only:
1874                  return ( $creator_user_ID == $user_ID );
1875  
1876              case 'lt': // Own + Lower level posts only:
1877              case 'le': // Own + Lower or equal level posts only:
1878                  if( empty( $creator_user_ID ) || ( $creator_user_ID == $user_ID ) )
1879                  { // allow if the comment creator is not registered or it is the current User
1880                      return true;
1881                  }
1882                  $UserCache = & get_UserCache();
1883                  // Get creator User
1884                  $creator_User = & $UserCache->get_by_ID( $creator_user_ID, false, false );
1885                  // Get user for who we are checking this permission
1886                  $User = & $UserCache->get_by_ID( $user_ID, false, false );
1887                  return ( $creator_User && $User && ( $creator_User->level < $User->level || ( $edit_permvalue == 'le' && $creator_User->level == $User->level ) ) );
1888  
1889              case 'anon': // Anonymous comment or own comment ( This perm value may have only for comments )
1890                  return ( empty( $creator_user_ID ) || ( $creator_user_ID == $user_ID ) );
1891  
1892              case 'all':
1893                  return true;
1894  
1895              case 'no':
1896              default:
1897                  return false;
1898          }
1899      }
1900  
1901      if( $perm && $permlevel == 'edit' && empty( $creator_user_ID ) )
1902      {
1903          return $blog_perms[$edit_permname] != 'no';
1904      }
1905  
1906      if( $perm && $permlevel == 'moderate' && empty( $creator_user_ID ) )
1907      { // check moderator rights
1908          return in_array( $blog_perms[$edit_permname], array( 'anon', 'lt', 'le', 'all' ) );
1909      }
1910  
1911      return $perm;
1912  }
1913  
1914  
1915  /**
1916   * Display user edit forms action icons
1917   *
1918   * @param object Widget(Form,Table,Results) where to display
1919   * @param objcet Edited User
1920   * @param string the action string, 'view' or 'edit'
1921   */
1922  function echo_user_actions( $Widget, $edited_User, $action )
1923  {
1924      global $current_User, $admin_url;
1925  
1926      if( $edited_User->ID != 0 )
1927      { // show these actions only if user already exists
1928          if( $current_User->ID != $edited_User->ID && $current_User->check_status( 'can_report_user' ) )
1929          {
1930              global $user_tab;
1931              // get current User report from edited User
1932              $current_report = get_report_from( $edited_User->ID );
1933              if( $current_report == NULL )
1934              { // Current user has no report for this user yet
1935                  $report_text_title = $report_text = T_('Report User');
1936              }
1937              else
1938              { // Current user already reported about this user
1939                  $report_text_title = $report_text = T_('You have reported this user');
1940                  $report_text = '<span class="red">'.$report_text.'</span>';
1941              }
1942              $Widget->global_icon( $report_text_title, 'warning_yellow', $admin_url.'?ctrl=user&amp;user_tab=report&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.$report_text, 3, 4, array( 'onclick' => 'return user_report( '.$edited_User->ID.', \''.$user_tab.'\')' ) );
1943          }
1944          if( ( $current_User->check_perm( 'users', 'edit', false ) ) && ( $current_User->ID != $edited_User->ID )
1945              && ( $edited_User->ID != 1 ) )
1946          {
1947              $Widget->global_icon( T_('Delete this user!'), 'delete', $admin_url.'?ctrl=users&amp;action=delete&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.T_('Delete'), 3, 4  );
1948              $Widget->global_icon( T_('Delete this user as spammer!'), 'delete', $admin_url.'?ctrl=users&amp;action=delete&amp;deltype=spammer&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.T_('Delete spammer'), 3, 4  );
1949          }
1950          if( $edited_User->get_msgform_possibility( $current_User ) )
1951          {
1952              $Widget->global_icon( T_('Compose message'), 'comments', $admin_url.'?ctrl=threads&action=new&user_login='.$edited_User->login );
1953          }
1954      }
1955  
1956      $redirect_to = get_param( 'redirect_to' );
1957      if( $redirect_to == NULL )
1958      {
1959          $redirect_to = regenerate_url( 'user_ID,action,ctrl', 'ctrl=users' );
1960      }
1961      $Widget->global_icon( ( $action != 'view' ? T_('Cancel editing!') : T_('Close user profile!') ), 'close', $redirect_to );
1962  }
1963  
1964  
1965  /**
1966   * Get user menu sub entries
1967   *
1968   * @param boolean true to get admin interface user sub menu entries, false to get front office user sub menu entries
1969   * @param integer edited user ID
1970   * @return array user sub entries
1971   */
1972  function get_user_sub_entries( $is_admin, $user_ID )
1973  {
1974      global $current_User, $Settings, $Blog;
1975      $users_sub_entries = array();
1976      if( empty( $user_ID ) )
1977      {
1978          $user_ID = $current_User->ID;
1979      }
1980  
1981      if( $is_admin )
1982      {
1983          $ctrl_param = 'ctrl=user&amp;user_tab=';
1984          $user_param = '&amp;user_ID='.$user_ID;
1985          $base_url = '';
1986      }
1987      else
1988      {
1989          $ctrl_param = 'disp=';
1990          $user_param = '';
1991          $base_url = $Blog->gen_blogurl();
1992      }
1993      $edit_perm = ( $user_ID == $current_User->ID || $current_User->check_perm( 'users', 'edit' ) );
1994      $view_perm = ( $user_ID == $current_User->ID || $current_User->check_perm( 'users', 'view' ) );
1995  
1996      if( $view_perm )
1997      {
1998          $users_sub_entries['profile'] = array(
1999                              'text' => T_('Profile'),
2000                              'href' => url_add_param( $base_url, $ctrl_param.'profile'.$user_param ) );
2001  
2002          if( $Settings->get('allow_avatars') )
2003          {
2004              $users_sub_entries['avatar'] = array(
2005                              'text' => T_('Profile picture'),
2006                              'href' => url_add_param( $base_url, $ctrl_param.'avatar'.$user_param ) );
2007          }
2008  
2009          if( $edit_perm )
2010          {
2011              $users_sub_entries['pwdchange'] = array(
2012                                  'text' => T_('Password'),
2013                                  'href' => url_add_param( $base_url, $ctrl_param.'pwdchange'.$user_param ) );
2014          }
2015  
2016          $users_sub_entries['userprefs'] = array(
2017                              'text' => T_('Preferences'),
2018                              'href' => url_add_param( $base_url, $ctrl_param.'userprefs'.$user_param ) );
2019  
2020          $users_sub_entries['subs'] = array(
2021                              'text' => T_('Notifications'),
2022                              'href' => url_add_param( $base_url, $ctrl_param.'subs'.$user_param ) );
2023  
2024          if( $is_admin )
2025          {    // show this only in backoffice
2026              $users_sub_entries['advanced'] = array(
2027                                  'text' => T_('Advanced'),
2028                                  'href' => url_add_param( $base_url, 'ctrl=user&amp;user_tab=advanced'.$user_param ) );
2029  
2030              if( $current_User->check_perm( 'users', 'edit' ) )
2031              { // User have edit/delete all users permission, so this user is an administrator
2032                  $users_sub_entries['admin'] = array(
2033                                  'text' => T_('Admin'),
2034                                  'href' => url_add_param( $base_url, 'ctrl=user&amp;user_tab=admin'.$user_param ) );
2035  
2036                  // Only users with view/edit all users permission can see the 'Sessions' & 'User Activity' tabs
2037                  $users_sub_entries['sessions'] = array(
2038                                      'text' => T_('Sessions'),
2039                                      'href' => url_add_param( $base_url, 'ctrl=user&amp;user_tab=sessions'.$user_param ) );
2040  
2041                  $users_sub_entries['activity'] = array(
2042                                      'text' => $current_User->ID == $user_ID ? T_('My Activity') : T_('User Activity'),
2043                                      'href' => url_add_param( $base_url, 'ctrl=user&amp;user_tab=activity'.$user_param ) );
2044              }
2045          }
2046      }
2047  
2048      return $users_sub_entries;
2049  }
2050  
2051  
2052  /**
2053   * Get if user is subscribed to get emails, when a new comment is published on this item.
2054   *
2055   * @param integer user ID
2056   * @param integer item ID
2057   * @return boolean true if user is subscribed and false otherwise
2058   */
2059  function get_user_isubscription( $user_ID, $item_ID )
2060  {
2061      global $DB;
2062      $result = $DB->get_var( 'SELECT count( isub_user_ID )
2063                                  FROM T_items__subscriptions
2064                                  WHERE isub_user_ID = '.$user_ID.' AND isub_item_ID = '.$item_ID.' AND isub_comments <> 0' );
2065      return $result > 0;
2066  }
2067  
2068  
2069  /**
2070   * Set user item subscription
2071   *
2072   * @param integer user ID
2073   * @param integer item ID
2074   * @param integer value 0 for unsubscribe and 1 for subscribe
2075   * @return boolean true is new value was successfully set, false otherwise
2076   */
2077  function set_user_isubscription( $user_ID, $item_ID, $value )
2078  {
2079      global $DB;
2080      if( ( $value < 0 ) || ( $value > 1 ) )
2081      { // Invalid value. It should be 0 for unsubscribe and 1 for subscribe.
2082          return false;
2083      }
2084  
2085      return $DB->query( 'REPLACE INTO T_items__subscriptions( isub_item_ID, isub_user_ID, isub_comments )
2086                                  VALUES ( '.$item_ID.', '.$user_ID.', '.$value.' )' );
2087  }
2088  
2089  
2090  /**
2091   * Get usertab header. Contains the user avatar image, the user tab title, and the user menu.
2092   *
2093   * @param object edited User
2094   * @param string user tab name
2095   * @param string user tab title
2096   * @return string tab header
2097   */
2098  function get_usertab_header( $edited_User, $user_tab, $user_tab_title )
2099  {
2100      global $AdminUI;
2101  
2102      // user status
2103      $user_status_icons = get_user_status_icons();
2104      $user_status_titles = get_user_statuses();
2105      $user_status = ' <small>('.$user_status_icons[ $edited_User->get( 'status' ) ].' '.$user_status_titles[ $edited_User->get( 'status' ) ].')</small>';
2106  
2107      // set title
2108      $form_title = '<h2 class="user_title">'.$edited_User->get_colored_login().$user_status.' &ndash; '.$user_tab_title.'</h2>';
2109  
2110      // set avatar tag
2111      $avatar_tag = $edited_User->get_avatar_imgtag( 'crop-top-48x48', 'floatleft', '', true );
2112  
2113      // build menu3
2114      $AdminUI->add_menu_entries( array( 'users', 'users' ), get_user_sub_entries( true, $edited_User->ID ) );
2115      $AdminUI->set_path( 'users', 'users', $user_tab );
2116      $user_menu3 = $AdminUI->get_html_menu( array( 'users', 'users' ), 'menu3' );
2117  
2118      $result = $avatar_tag.'<div class="user_header_content">'.$form_title.$user_menu3.'</div>';
2119      return '<div class="user_header">'.$result.'</div>'.'<div class="clear"></div>';
2120  }
2121  
2122  
2123  /**
2124   * Check if user can receive new email today with the given email type or the limit was already exceeded
2125   * This function will update the corresponding UserSettings but won't save it until the email is not sent
2126   *
2127   * @param string the name of limit/day setting
2128   * @param string the name of the last email setting
2129   * @param integer the user ID
2130   * @return boolean true if new email is allowed, false otherwise
2131   */
2132  function check_allow_new_email( $limit_setting, $last_email_setting, $user_ID )
2133  {
2134      global $UserSettings, $servertimenow;
2135  
2136      $limit = $UserSettings->get( $limit_setting, $user_ID );
2137      if( $limit == 0 )
2138      { // user doesn't allow this kind of emails at all
2139          return false;
2140      }
2141      $email_count = 0;
2142      $last_email = $UserSettings->get( $last_email_setting, $user_ID );
2143      if( !empty( $last_email ) )
2144      { // at least one email was sent
2145          $current_date = date( 'Y-m-d', $servertimenow );
2146          list( $last_email_ts, $last_email_count ) = explode( '_', $last_email );
2147          $last_date = date( 'Y-m-d', $last_email_ts );
2148          if( $last_date == $current_date )
2149          { // last email was sent today
2150              if( $last_email_count >= $limit )
2151              { // the limit was already reached
2152                  return false;
2153              }
2154              $email_count = $last_email_count;
2155          }
2156      }
2157      // new email is allowed, set new email setting value, after the email will be sent
2158      $email_count++;
2159      $last_email = $servertimenow.'_'.$email_count;
2160      $UserSettings->set( $last_email_setting, $last_email, $user_ID );
2161      return true;
2162  }
2163  
2164  
2165  /**
2166   * Send account validation email with a permanent validation link
2167   *
2168   * @param array user ids to send validation email
2169   * @param boolean true if this email is an account activation reminder, false if the account status was changed right now
2170   * @return integer the number of successfully sent emails
2171   */
2172  function send_easy_validate_emails( $user_ids, $is_reminder = true, $email_changed = false )
2173  {
2174      global $UserSettings, $servertimenow, $secure_htsrv_url;
2175  
2176      $UserCache = & get_UserCache();
2177  
2178      if( isset($GLOBALS['messaging_Module']) )
2179      {    // Get already received messages for each recepient user
2180          $already_received_messages = get_users_unread_threads( $user_ids );
2181      }
2182  
2183      $cache_by_locale = array();
2184      $email_sent = 0;
2185      foreach( $user_ids as $user_ID )
2186      { // Iterate through user ids and send account activation reminder to all user
2187          $User = $UserCache->get_by_ID( $user_ID, false );
2188          if( !$User )
2189          { // user not exists
2190              continue;
2191          }
2192  
2193          if( !$User->check_status( 'can_be_validated' ) )
2194          { // User is validated or it is not allowed to be validated
2195              continue;
2196          }
2197  
2198          if( $is_reminder && ( !$UserSettings->get( 'send_activation_reminder' ) ) )
2199          { // This is an activation reminder, but user wouldn't like to receive this kind of emails
2200              continue;
2201          }
2202  
2203          if( mail_is_blocked( $User->get( 'email' ) ) )
2204          { // prevent trying to send an email to a blocked email address
2205              continue;
2206          }
2207  
2208          $notify_locale = $User->get( 'locale' );
2209          $reminder_key = $UserSettings->get( 'last_activation_reminder_key', $User->ID );
2210          if( empty( $reminder_key ) || $email_changed )
2211          { // reminder key was not generated yet, or the user email address was changed and we need a new one, to invalidate old requests
2212              $reminder_key = generate_random_key(32);
2213              $UserSettings->set( 'last_activation_reminder_key', $reminder_key, $User->ID );
2214          }
2215          if( ! isset($cache_by_locale[$notify_locale]) )
2216          { // No subject for this locale generated yet:
2217              locale_temp_switch( $notify_locale );
2218  
2219              $cache_by_locale[$notify_locale]['subject'] = T_( 'Activate your account: $login$' );
2220  
2221              locale_restore_previous();
2222          }
2223  
2224          $email_template_params = array(
2225                  'locale'       => $notify_locale,
2226                  'status'       => $User->get( 'status' ),
2227                  'reminder_key' => $reminder_key,
2228                  'is_reminder'  => $is_reminder,
2229              );
2230  
2231          if( !empty( $already_received_messages[$User->ID] ) )
2232          { // add already received message list to email body
2233              $email_template_params['already_received_messages'] = $already_received_messages[$User->ID];
2234          }
2235  
2236          // Update notification sender's info from General settings
2237          $User->update_sender( true );
2238  
2239          if( send_mail_to_User( $User->ID, $cache_by_locale[$notify_locale]['subject'], 'account_activate', $email_template_params, true ) )
2240          { // save corresponding user settings right after the email was sent, to prevent not saving if an eroor occurs
2241              $email_sent++;
2242              // Set last remind activation email date and increase sent reminder emails number in UserSettings
2243              $UserSettings->set( 'last_activation_email', date2mysql( $servertimenow ), $User->ID );
2244              if( $is_reminder )
2245              {
2246                  $reminder_sent_to_user = $UserSettings->get( 'activation_reminder_count', $User->ID );
2247                  $UserSettings->set( 'activation_reminder_count', $reminder_sent_to_user + 1, $User->ID );
2248              }
2249              $UserSettings->dbupdate();
2250          }
2251      }
2252  
2253      return $email_sent;
2254  }
2255  
2256  
2257  /**
2258   * Get account activation reminder informaton for the given user. This is used on the user admin settings form.
2259   *
2260   * @param $edited_User
2261   * @return array of arrays with field label, info and note about the Last and Next account activation emails
2262   */
2263  function get_account_activation_info( $edited_User )
2264  {
2265      global $Settings, $UserSettings, $servertimenow, $activate_account_reminder_config;
2266  
2267      $field_label = T_('Latest account activation email');
2268      $can_be_validated = $edited_User->check_status( 'can_be_validated' );
2269      if( ! $can_be_validated )
2270      {
2271          if( $edited_User->check_status( 'is_validated' ) )
2272          { // The user account is already activated
2273              return array( array( $field_label, T_('Account is already activated') ) );
2274          }
2275  
2276          if( $edited_User->check_status( 'is_closed' ) )
2277          {
2278              return array( array( $field_label, T_('The account is closed, it cannot be activated') ) );
2279          }
2280  
2281          debug_die('Unhandled user account status!');
2282      }
2283  
2284      if( ! $UserSettings->get( 'send_activation_reminder', $edited_User->ID ) )
2285      { // The user doesn't want to receive account activation reminders
2286          return array( array( $field_label, T_('This user doesn\'t want to receive account activation reminders') ) );
2287      }
2288  
2289      $field_note = '';
2290      $is_secure_validation = ( $Settings->get( 'validation_process' ) != 'easy' );
2291      if( $is_secure_validation )
2292      { // The easy validation process is not allowed, so account activation emails are sent only for request
2293          $field_note = T_('Account validation process is secured, so account activation emails are sent only upon request');
2294      }
2295  
2296      $result = array();
2297      $last_activation_email = $UserSettings->get( 'last_activation_email', $edited_User->ID );
2298      if( empty( $last_activation_email ) )
2299      { // latest activation email date is not set because email was not sent yet ( it is possuble that there is some problem with the user email address )
2300          $result[] = array( $field_label, T_('None yet'), $field_note );
2301      }
2302      else
2303      { // format last activation email date
2304          $last_activation_email_info = format_to_output( $last_activation_email );
2305          $result[] = array( $field_label, $last_activation_email_info, $field_note );
2306      }
2307  
2308      if( $is_secure_validation )
2309      { // When validation process is secure, then account activation email is not known, and this was already added as a note into the 'Last account activation email' field
2310          return $result;
2311      }
2312  
2313      $field_label = T_('Next account activation reminder');
2314      $number_of_max_reminders = ( count( $activate_account_reminder_config ) - 1 );
2315      $activation_reminder_count = (int) $UserSettings->get( 'activation_reminder_count', $edited_User->ID );
2316      $field_note = sprintf( T_('%d reminders were sent out of the maximum allowed of %d.'), $activation_reminder_count, $number_of_max_reminders );
2317      // The validation process is easy, so reminders should be sent
2318      $responsible_job_note = T_('Scheduled job responsible for reminders is "Send reminders about not activated accounts".');
2319  
2320      if( $edited_User->status == 'failedactivation' )
2321      { // The user account status was changed to failed activation, this user won't be reminded again to activate the account
2322          $result[] = array( $field_label, T_('Account activation has failed'), $field_note.' '.$responsible_job_note );
2323      }
2324      elseif( $activation_reminder_count >= $number_of_max_reminders )
2325      { // This is the case when the account status was not changed to failed activation yet, but the last reminder was sent
2326          $result[] = array( $field_label, sprintf( T_('We already sent %d account activation reminders of the maximum allowed of %d, no more reminders will be sent'), $activation_reminder_count, $number_of_max_reminders ) );
2327      }
2328      elseif( empty( $last_activation_email ) )
2329      { // Account activation email was not sent at all. This can happen when some problem is with the user email
2330          $result[] = array( $field_label, T_('At least one activation email should have been already sent. Check if the user email address is correct, and PHP is sending emails correctly'), $responsible_job_note );
2331      }
2332      else
2333      { // Activate account reminder email should be send to the user, set information when it should be done
2334          $next_activation_email_ts = strtotime( '+'.$activate_account_reminder_config[$activation_reminder_count].' second', strtotime( $last_activation_email ) );
2335          if( $next_activation_email_ts > $servertimenow )
2336          { // The next activation email issue date is in the future
2337              $time_left = seconds_to_period( $next_activation_email_ts - $servertimenow );
2338              $info = sprintf( T_('%s left before next notification').' - '.$field_note, $time_left );
2339              $result[] = array( $field_label, $info, $responsible_job_note );
2340          }
2341          else
2342          { // The next reminder issue date was in the past
2343              $time_since = seconds_to_period( $servertimenow - $next_activation_email_ts );
2344              $info = sprintf( T_('next notification pending since %s - check the "Send reminders about not activated accounts" scheduled job'), $time_since );
2345              $result[] = array( $field_label, $info, $field_note );
2346          }
2347      }
2348      return $result;
2349  }
2350  
2351  
2352  /**
2353   * Callback function to initialize a select element on the identity user form
2354   *
2355   * @param string Value
2356   * @return string Option elements for the select tag
2357   */
2358  function callback_options_user_new_fields( $value = 0 )
2359  {
2360      global $DB, $edited_User;
2361  
2362      $exclude_fields_sql = '';
2363      if( !empty( $edited_User ) )
2364      {    // Exclude not multiple fields for edited user
2365          $exclude_fields_sql = ' AND ( ufdf_duplicated != "forbidden" OR ufdf_required NOT IN ( "recommended", "require") )
2366              AND ufdf_ID NOT IN (
2367                  SELECT ufdf_ID
2368                    FROM T_users__fields
2369                    LEFT JOIN T_users__fielddefs ON ufdf_ID = uf_ufdf_ID
2370                   WHERE ufdf_duplicated = "forbidden"
2371                     AND uf_user_ID = "'.$edited_User->ID.'" )';
2372      }
2373  
2374      // Get list of possible field types:
2375      $userfielddefs = $DB->get_results( '
2376          SELECT ufdf_ID, ufdf_type, ufdf_name, ufgp_ID, ufgp_name, ufdf_suggest
2377            FROM T_users__fielddefs
2378            LEFT JOIN T_users__fieldgroups ON ufgp_ID = ufdf_ufgp_ID
2379           WHERE ufdf_required != "hidden"
2380             '.$exclude_fields_sql.'
2381           ORDER BY ufgp_order, ufdf_order' );
2382  
2383      $field_options = '';
2384  
2385      if( count( $userfielddefs ) > 0 )
2386      {    // Field types exist in DB
2387          global $user_fields_empty_name;
2388          $empty_name = isset( $user_fields_empty_name ) ? $user_fields_empty_name : T_('Add field...');
2389  
2390          $field_options .= '<option value="0">'.$empty_name.'</option>';
2391          $current_group_ID = 0;
2392          foreach( $userfielddefs as $f => $fielddef )
2393          {
2394              if( $fielddef->ufgp_ID != $current_group_ID )
2395              {    // New group
2396                  if( $f != 0 )
2397                  {    // Close tag of previous group
2398                      $field_options .= "\n".'</optgroup>';
2399                  }
2400                  $field_options .= "\n".'<optgroup label="'.$fielddef->ufgp_name.'">';
2401              }
2402              $field_options .= "\n".'<option value="'.$fielddef->ufdf_ID.'"';
2403              if( $value == $fielddef->ufdf_ID )
2404              {    // We had selected this type before getting an error:
2405                  $field_options .= ' selected="selected"';
2406              }
2407              if( $fielddef->ufdf_suggest )
2408              {    // We can suggest a values for this field type
2409                  $field_options .= ' rel="suggest"';
2410              }
2411              $field_options .= '>'.$fielddef->ufdf_name.'</option>';
2412              $current_group_ID = $fielddef->ufgp_ID;
2413          }
2414          $field_options .= "\n".'</optgroup>';
2415      }
2416  
2417      return $field_options;
2418  }
2419  
2420  
2421  /**
2422   * Display user fields from given array
2423   *
2424   * @param array User fields given from sql query with following structure:
2425   *                         ufdf_ID
2426   *                         uf_ID
2427   *                         ufdf_type
2428   *                         ufdf_name
2429   *                         uf_varchar
2430   *                         ufdf_required
2431   *                         ufdf_option
2432   * @param object Form
2433   * @param string Field name of the new fields ( new | add )
2434   * @param boolean Add a fieldset for group or don't
2435   */
2436  function userfields_display( $userfields, $Form, $new_field_name = 'new', $add_group_fieldset = true )
2437  {
2438      global $action;
2439  
2440      // Array contains values of the new fields from the request
2441      $uf_new_fields = param( 'uf_'.$new_field_name, 'array/array/string' );
2442  
2443      // Type of the new field
2444      global $new_field_type;
2445  
2446      $group_ID = 0;
2447      foreach( $userfields as $userfield )
2448      {
2449          if( $group_ID != $userfield->ufgp_ID && $add_group_fieldset )
2450          {    // Start new group
2451              if( $group_ID > 0 )
2452              {    // End previous group
2453                  $Form->end_fieldset();
2454              }
2455              $Form->begin_fieldset( T_( $userfield->ufgp_name ), array( 'id' => $userfield->ufgp_ID ) );
2456          }
2457  
2458          $uf_val = param( 'uf_'.$userfield->uf_ID, 'string', NULL );
2459  
2460          $uf_ID = $userfield->uf_ID;
2461          if( $userfield->uf_ID == '0' )
2462          {    // Set uf_ID for new (not saved) fields (recommended & require types)
2463              $userfield->uf_ID = $new_field_name.'['.$userfield->ufdf_ID.'][]';
2464  
2465              $value_num = 'uf_'.$new_field_name.'_'.$userfield->ufdf_ID.'prev_value_num';
2466              global $$value_num;    // Used when user add a many fields with the same type
2467              $$value_num = (int)$$value_num;
2468              if( isset( $uf_new_fields[$userfield->ufdf_ID][$$value_num] ) )
2469              {    // Get a value from submitted form
2470                  $uf_val = $uf_new_fields[$userfield->ufdf_ID][$$value_num];
2471                  $$value_num++;
2472              }
2473          }
2474  
2475          if( is_null( $uf_val ) )
2476          {    // No value submitted yet, get DB val:
2477              $uf_val = $userfield->uf_varchar;
2478          }
2479  
2480          $field_note = '';
2481          if( $action != 'view' )
2482          {
2483              if( in_array( $userfield->ufdf_duplicated, array( 'allowed', 'list' ) ) )
2484              {    // Icon to add a new field for multiple field
2485                  $field_note .= get_icon( 'add', 'imgtag', array( 'rel' => 'add_ufdf_'.$userfield->ufdf_ID, 'style' => 'display:none !important; cursor: pointer; position: relative;' ) );
2486              }
2487          }
2488  
2489          if( $userfield->ufdf_type == 'url' && !empty( $uf_val ) )
2490          {
2491              $url = format_to_output( $uf_val, 'formvalue' );
2492              if( !preg_match('#://#', $url) )
2493              {
2494                  $url = 'http://'.$url;
2495              }
2496              $field_note .= '<a href="'.$url.'" target="_blank" class="action_icon" style="vertical-align: 0;">'.get_icon( 'play', 'imgtag', array('title'=>T_('Visit the site')) ).'</a>';
2497          }
2498  
2499          $field_params = array();
2500          $field_params['rel'] = 'ufdf_'.$userfield->ufdf_ID;
2501          if( $userfield->ufdf_required == 'require' )
2502          {    // Field is required
2503              $field_params['required'] = true;
2504          }
2505          if( $userfield->ufdf_suggest == '1' && $userfield->ufdf_type == 'word' )
2506          {    // Mark field with this tag to suggest a values
2507              $field_params['autocomplete'] = 'on';
2508          }
2509  
2510  
2511          if( $action == 'view' )
2512          {    // Only view
2513              $Form->info( $userfield->ufdf_name, $uf_val.' '.$field_note );
2514          }
2515          else
2516          {    // Edit mode
2517              switch( $userfield->ufdf_type )
2518              {    // Display existing field:
2519                  case 'text':
2520                      $field_params['cols'] = 38;
2521                      $field_params['note'] = $field_note;
2522                      $Form->textarea_input( 'uf_'.$userfield->uf_ID, $uf_val, 5, $userfield->ufdf_name, $field_params );
2523                      break;
2524  
2525                  case 'list':
2526                      $uf_options = explode( "\n", str_replace( "\r", '', $userfield->ufdf_options ) );
2527                      if( $userfield->ufdf_required != 'require' || // Not required field
2528                              $uf_ID == '0' || // New reqired field has to have an empty value
2529                              ( $uf_val != '' && ! in_array( $uf_val, $uf_options ) ) ) // Required field has a value that doesn't exist
2530                      {    // Add empty value
2531                          $uf_options = array_merge( array( '---' ), $uf_options );
2532                      }
2533                      $Form->select_input_array( 'uf_'.$userfield->uf_ID, $uf_val, $uf_options, $userfield->ufdf_name, $field_note, $field_params );
2534                      break;
2535  
2536                  default:
2537                      $field_params['maxlength'] = 255;
2538                      $Form->text_input( 'uf_'.$userfield->uf_ID, $uf_val, 40, $userfield->ufdf_name, $field_note, $field_params );
2539              }
2540          }
2541  
2542          $group_ID = $userfield->ufgp_ID;
2543      }
2544  
2545      if( $group_ID > 0 && $add_group_fieldset )
2546      {    // End gruop fieldset if userfields are exist
2547          $Form->end_fieldset();
2548      }
2549  }
2550  
2551  
2552  /**
2553   * Prepare some data for Userfield
2554   *
2555   * @param Userfield
2556   */
2557  function userfield_prepare( & $userfield )
2558  {
2559      $userfield->uf_varchar = format_to_output( $userfield->uf_varchar, 'formvalue' );
2560      if( $userfield->ufdf_type == 'url' )
2561      {    // Prepare value for url field
2562          $url = $userfield->uf_varchar;
2563          if( !preg_match('#://#', $url) )
2564          {
2565              $url = 'http://'.$url;
2566          }
2567          $userfield->uf_varchar = '<a href="'.$url.'" target="_blank" rel="nofollow">'.$userfield->uf_varchar.'</a>';
2568      }
2569  }
2570  
2571  
2572  /**
2573   * Callback to add filters on top of the result set
2574   *
2575   * @param Form
2576   */
2577  function callback_filter_userlist( & $Form )
2578  {
2579      global $Settings, $current_User;
2580  
2581      $Form->hidden( 'filter', 'new' );
2582  
2583      $Form->text( 'keywords', get_param('keywords'), 20, T_('Name'), '', 50 );
2584  
2585      echo '<span class="nowrap">';
2586      $Form->checkbox( 'gender_men', get_param('gender_men'), T_('Men') );
2587      $Form->checkbox( 'gender_women', get_param('gender_women'), T_('Women') );
2588      echo '</span>';
2589      if( !is_admin_page() )
2590      {
2591          echo '<br />';
2592      }
2593  
2594      if( is_admin_page() )
2595      { // show this filters only on admin interface
2596          if( $current_User->check_perm( 'users', 'edit' ) )
2597          { // Show "Reported users" filter only for users with edit user permission
2598              $Form->checkbox( 'reported', get_param('reported'), T_('Reported users') );
2599              $Form->checkbox( 'custom_sender_email', get_param('custom_sender_email'), T_('Users with custom sender address') );
2600              $Form->checkbox( 'custom_sender_name', get_param('custom_sender_name'), T_('Users with custom sender name') );
2601          }
2602  
2603          $Form->select_input_array( 'account_status', get_param('account_status'), get_user_statuses( T_('All') ), T_('Account status') );
2604  
2605          $GroupCache = new DataObjectCache( 'Group', true, 'T_groups', 'grp_', 'grp_ID', 'grp_name' );
2606          $group_options_array = array(
2607                  '-1' => T_('All (Ungrouped)'),
2608                  '0'  => T_('All (Grouped)'),
2609              ) + $GroupCache->get_option_array();
2610          $Form->select_input_array( 'group', get_param('group'), $group_options_array, T_('User group'), '', array( 'force_keys_as_values' => true ) );
2611          echo '<br />';
2612      }
2613  
2614      if( user_country_visible() )
2615      {    // Filter by country
2616          load_class( 'regional/model/_country.class.php', 'Country' );
2617          load_funcs( 'regional/model/_regional.funcs.php' );
2618          $CountryCache = & get_CountryCache( T_('All') );
2619          $Form->select_country( 'country', get_param('country'), $CountryCache, T_('Country'), array( 'allow_none' => true ) );
2620      }
2621  
2622      if( user_region_visible() )
2623      {    // Filter by region
2624          echo '<span id="region_filter"'.( !regions_exist( get_param('country'), true ) ? ' style="display:none"' : '' ).'>';
2625          $Form->select_input_options( 'region', get_regions_option_list( get_param('country'), get_param('region') ), T_('Region') );
2626          echo '</span>';
2627      }
2628  
2629      if( user_subregion_visible() )
2630      {    // Filter by subregion
2631          echo '<span id="subregion_filter"'.( !subregions_exist( get_param('region'), true ) ? ' style="display:none"' : '' ).'>';
2632          $Form->select_input_options( 'subregion', get_subregions_option_list( get_param('region'), get_param('subregion') ), T_('Sub-region') );
2633          echo '</span>';
2634      }
2635  
2636      if( user_city_visible() )
2637      {    // Filter by city
2638          echo '<span id="city_filter"'.( !cities_exist( get_param('country'), get_param('region'), get_param('subregion'), true ) ? ' style="display:none"' : '' ).'>';
2639          $Form->select_input_options( 'city', get_cities_option_list( get_param('country'), get_param('region'), get_param('subregion'), get_param('city') ), T_('City') );
2640          echo '</span>';
2641      }
2642  
2643      echo '<br />';
2644  
2645      $Form->interval( 'age_min', get_param('age_min'), 'age_max', get_param('age_max'), 3, T_('Age group') );
2646      echo '<br />';
2647  
2648      $criteria_types = param( 'criteria_type', 'array/integer' );
2649      $criteria_values = param( 'criteria_value', 'array/string' );
2650  
2651      if( count( $criteria_types ) == 0 )
2652      {    // Init one criteria fieldset for first time
2653          $criteria_types[] = '';
2654          $criteria_values[] = '';
2655      }
2656  
2657      foreach( $criteria_types as $c => $type )
2658      {
2659          $value = trim( strip_tags( $criteria_values[$c] ) );
2660          if( $value == '' && count( $criteria_types ) > 1 && $c > 0 )
2661          {    // Don't display empty field again after filter request
2662              continue;
2663          }
2664  
2665          if( $c > 0 )
2666          {    // Separator between criterias
2667              echo '<br />';
2668          }
2669          $Form->output = false;
2670          $criteria_input = $Form->text( 'criteria_value[]', $value, 17, '', '', 50 );
2671          $criteria_input .= get_icon( 'add', 'imgtag', array( 'rel' => 'add_criteria' ) );
2672          $Form->output = true;
2673  
2674          global $user_fields_empty_name;
2675          $user_fields_empty_name = T_('Select...');
2676  
2677          $Form->select( 'criteria_type[]', $type, 'callback_options_user_new_fields', T_('Specific criteria'), $criteria_input );
2678      }
2679  
2680      if( user_region_visible() )
2681      {    // JS functions for AJAX loading of regions, subregions & cities
2682  ?>
2683  <script type="text/javascript">
2684  jQuery( '#country' ).change( function()
2685  {
2686      var this_obj = jQuery( this );
2687      jQuery.ajax( {
2688      type: 'POST',
2689      url: '<?php echo get_samedomain_htsrv_url(); ?>anon_async.php',
2690      data: 'action=get_regions_option_list&ctry_id=' + jQuery( this ).val(),
2691      success: function( result )
2692          {
2693              jQuery( '#region' ).html( ajax_debug_clear( result ) );
2694              if( jQuery( '#region option' ).length > 1 )
2695              {
2696                  jQuery( '#region_filter' ).show();
2697              }
2698              else
2699              {
2700                  jQuery( '#region_filter' ).hide();
2701              }
2702              load_subregions( 0 ); // Reset sub-regions
2703          }
2704      } );
2705  } );
2706  
2707  jQuery( '#region' ).change( function ()
2708  {    // Change option list with sub-regions
2709      load_subregions( jQuery( this ).val() );
2710  } );
2711  
2712  jQuery( '#subregion' ).change( function ()
2713  {    // Change option list with cities
2714      load_cities( jQuery( '#country' ).val(), jQuery( '#region' ).val(), jQuery( this ).val() );
2715  } );
2716  
2717  function load_subregions( region_ID )
2718  {    // Load option list with sub-regions for seleted region
2719      jQuery.ajax( {
2720      type: 'POST',
2721      url: '<?php echo get_samedomain_htsrv_url(); ?>anon_async.php',
2722      data: 'action=get_subregions_option_list&rgn_id=' + region_ID,
2723      success: function( result )
2724          {
2725              jQuery( '#subregion' ).html( ajax_debug_clear( result ) );
2726              if( jQuery( '#subregion option' ).length > 1 )
2727              {
2728                  jQuery( '#subregion_filter' ).show();
2729              }
2730              else
2731              {
2732                  jQuery( '#subregion_filter' ).hide();
2733              }
2734              load_cities( jQuery( '#country' ).val(), region_ID, 0 );
2735          }
2736      } );
2737  }
2738  
2739  function load_cities( country_ID, region_ID, subregion_ID )
2740  {    // Load option list with cities for seleted region or sub-region
2741      jQuery.ajax( {
2742      type: 'POST',
2743      url: '<?php echo get_samedomain_htsrv_url(); ?>anon_async.php',
2744      data: 'action=get_cities_option_list&ctry_id=' + country_ID + '&rgn_id=' + region_ID + '&subrg_id=' + subregion_ID,
2745      success: function( result )
2746          {
2747              jQuery( '#city' ).html( ajax_debug_clear( result ) );
2748              if( jQuery( '#city option' ).length > 1 )
2749              {
2750                  jQuery( '#city_filter' ).show();
2751              }
2752              else
2753              {
2754                  jQuery( '#city_filter' ).hide();
2755              }
2756          }
2757      } );
2758  }
2759  </script>
2760  <?php
2761      }
2762  }
2763  
2764  
2765  /**
2766   * Country is visible for defining
2767   *
2768   * @return boolean TRUE if users can define a country for own profile
2769   */
2770  function user_country_visible()
2771  {
2772      global $Settings;
2773  
2774      return $Settings->get( 'location_country' ) != 'hidden' || user_region_visible();
2775  }
2776  
2777  
2778  /**
2779   * Region is visible for defining
2780   *
2781   * @return boolean TRUE if users can define a region for own profile
2782   */
2783  function user_region_visible()
2784  {
2785      global $Settings;
2786  
2787      return $Settings->get( 'location_region' ) != 'hidden' || user_subregion_visible();
2788  }
2789  
2790  
2791  /**
2792   * Subregion is visible for defining
2793   *
2794   * @return boolean TRUE if users can define a subregion for own profile
2795   */
2796  function user_subregion_visible()
2797  {
2798      global $Settings;
2799  
2800      return $Settings->get( 'location_subregion' ) != 'hidden' || user_city_visible();
2801  }
2802  
2803  
2804  /**
2805   * City is visible for defining
2806   *
2807   * @return boolean TRUE if users can define a city for own profile
2808   */
2809  function user_city_visible()
2810  {
2811      global $Settings;
2812  
2813      return $Settings->get( 'location_city' ) != 'hidden';
2814  }
2815  
2816  
2817  /**
2818   * Get array for options of account statuses
2819   *
2820   * @param string Null option name
2821   * @return array Account statuses
2822   */
2823  function get_user_statuses( $null_option_name = '' )
2824  {
2825      $user_statuses = array(
2826              'new'              => T_( 'New' ),
2827              'activated'        => T_( 'Activated by email' ),
2828              'autoactivated'    => T_( 'Autoactivated' ),
2829              'emailchanged'     => T_( 'Email changed' ),
2830              'deactivated'      => T_( 'Deactivated email' ),
2831              'failedactivation' => T_( 'Failed activation' ),
2832              'closed'           => T_( 'Closed account' )
2833          );
2834  
2835      if( !empty( $null_option_name ) )
2836      {    // Set null option
2837          $user_statuses = array_merge( array(
2838                      '' => $null_option_name
2839                  ), $user_statuses
2840              );
2841      }
2842  
2843      return $user_statuses;
2844  }
2845  
2846  
2847  /**
2848   * Get array with user statuses and icons
2849   *
2850   * @param boolean TRUE - display text after icon
2851   * @return array Array where Key is user status and Value is html icon
2852   */
2853  function get_user_status_icons( $display_text = false )
2854  {
2855      $user_status_icons = array(
2856              'activated'        => get_icon( 'bullet_green', 'imgtag', array( 'title' => T_( 'Account has been activated by email' ) ) ),
2857              'autoactivated'    => get_icon( 'bullet_green', 'imgtag', array( 'title' => T_( 'Account has been automatically activated' ) ) ),
2858              'new'              => get_icon( 'bullet_blue', 'imgtag', array( 'title' => T_( 'New account' ) ) ),
2859              'deactivated'      => get_icon( 'bullet_blue', 'imgtag', array( 'title' => T_( 'Deactivated account' ) ) ),
2860              'emailchanged'     => get_icon( 'bullet_yellow', 'imgtag', array( 'title' => T_( 'Email address was changed' ) ) ),
2861              'closed'           => get_icon( 'bullet_black', 'imgtag', array( 'title' => T_( 'Closed account' ) ) ),
2862              'failedactivation' => get_icon( 'bullet_red', 'imgtag', array( 'title' => T_( 'Account was not activated or the activation failed' ) ) )
2863          );
2864  
2865      if( $display_text )
2866      {
2867          $user_status_icons['activated']        .= ' '.T_( 'Activated' );
2868          $user_status_icons['autoactivated']    .= ' '.T_( 'Autoactivated' );
2869          $user_status_icons['new']              .= ' '.T_( 'New' );
2870          $user_status_icons['deactivated']      .= ' '.T_( 'Deactivated' );
2871          $user_status_icons['emailchanged']     .= ' '.T_( 'Email changed' );
2872          $user_status_icons['closed']           .= ' '.T_( 'Closed' );
2873          $user_status_icons['failedactivation'] .= ' '.T_( 'Failed activation' );
2874      }
2875  
2876      return $user_status_icons;
2877  }
2878  
2879  
2880  /**
2881   * Get all user ID and login where user_login starts with the reserved 'usr_' prefix
2882   *
2883   * @return array result list
2884   */
2885  function find_logins_with_reserved_prefix()
2886  {
2887      global $DB;
2888  
2889      return $DB->get_results('SELECT user_ID, user_login FROM T_users WHERE user_login REGEXP "^usr_"');
2890  }
2891  
2892  
2893  /**
2894   * Count those users who have custom setting which is different then the general
2895   *
2896   * @param string setting name
2897   * @param string general setting value
2898   * @return integer the number of users with custom settings
2899   */
2900  function count_users_with_custom_setting( $setting_name, $general_value )
2901  {
2902      global $DB;
2903  
2904      return $DB->get_var( 'SELECT count( uset_user_ID )
2905          FROM T_users__usersettings
2906          WHERE uset_name = '.$DB->quote( $setting_name ).' AND uset_value != '.$DB->quote( $general_value ) );
2907  }
2908  
2909  
2910  /**
2911   * Get user reports available statuses
2912   *
2913   * @return array with status key and status text
2914   */
2915  function get_report_statuses()
2916  {
2917      return array(
2918          'fake'       => T_('This user profile is fake'),
2919          'guidelines' => T_('This user does not follow the guidelines'),
2920          'harass'     => T_('This user is harassing me'),
2921          'spam'       => T_('This user is spamming me'),
2922          'other'      => T_('Other')
2923      );
2924  }
2925  
2926  
2927  /**
2928   * Get current User report from the given user
2929   *
2930   * @param integer user ID to get report from
2931   * @return array with report status, info and date. The return value is an empty array if current User didn't report the given user.
2932   */
2933  function get_report_from( $user_ID )
2934  {
2935      global $DB, $current_User;
2936  
2937      return $DB->get_row( 'SELECT urep_status as status, urep_info as info, urep_datetime as date
2938                                  FROM T_users__reports
2939                                  WHERE urep_target_user_ID = '.$DB->quote( $user_ID ).'
2940                                      AND urep_reporter_ID = '.$DB->quote( $current_User->ID ),
2941                      ARRAY_A );
2942  }
2943  
2944  
2945  /**
2946   * Count reprots by status from the given user
2947   *
2948   * @param integer user ID
2949   * @param boolean set false to get plain result array, or set true to get display format
2950   * @return mixed array if display format is true, string otherwise
2951   */
2952  function count_reports_from( $user_ID, $display_format = true )
2953  {
2954      global $DB, $admin_url;
2955  
2956      $SQL = new SQL();
2957      $SQL->SELECT( 'urep_status as status, COUNT( DISTINCT( urep_reporter_ID ) ) as num_count' );
2958      $SQL->FROM( 'T_users__reports' );
2959      $SQL->WHERE( 'urep_target_user_ID = '.$DB->quote( $user_ID ) );
2960      $SQL->GROUP_BY( 'urep_status' );
2961      $reports = $DB->get_assoc( $SQL->get() );
2962  
2963      if( !$display_format )
2964      { // don't display return result
2965          return $reports;
2966      }
2967  
2968      if( empty( $reports ) )
2969      { // there are no reports yet from the given user
2970          return '<span style="color:green">'.T_('No reports yet.').'</span>';
2971      }
2972  
2973      $result = '<span style="color:red">';
2974      foreach( $reports as $status => $num_count )
2975      {
2976          $result .= $status.': '.$num_count.'; ';
2977      }
2978      $result .= '</span>- <a href="'.url_add_param( $admin_url, 'ctrl=user&amp;user_ID='.$user_ID.'&amp;user_tab=activity#reports_result' ).'">'.T_('View').' &raquo;</a>';
2979      return $result;
2980  }
2981  
2982  
2983  /**
2984   * Report a user
2985   *
2986   * @param integer reported User ID
2987   * @param string reported user status (fake, guidelines, harass, spam, other )
2988   * @param string more info
2989   * @return mixed 1 on success false on error
2990   */
2991  function add_report_from( $user_ID, $status, $info )
2992  {
2993      global $DB, $current_User, $localtimenow;
2994  
2995      $UserCache = & get_UserCache();
2996      $reported_User = $UserCache->get_by_ID( $user_ID, false );
2997      if( !$reported_User )
2998      { // if user doesn't exists return false
2999          return false;
3000      }
3001  
3002      $result = $DB->query( 'REPLACE INTO T_users__reports( urep_target_user_ID, urep_reporter_ID, urep_status, urep_info, urep_datetime )
3003                          VALUES( '.$DB->quote( $user_ID ).', '.$DB->quote( $current_User->ID ).', '.$DB->quote( $status ).', '.$DB->quote( $info ).', '.$DB->quote( date2mysql( $localtimenow ) ).' )' );
3004      if( $result )
3005      { // if report was successful send user reported notificaitons to admin users
3006          $email_template_params = array(
3007                              'login'          => $reported_User->login,
3008                              'email'          => $reported_User->email,
3009                              'report_status'  => get_report_status_text( $status ),
3010                              'report_info'    => $info,
3011                              'user_ID'        => $user_ID,
3012                              'reported_by'    => $current_User->login,
3013                          );
3014          // send notificaiton ( it will be send to only those users who want to receive this kind of notifications )
3015          send_admin_notification( NT_('User account reported'), 'account_reported', $email_template_params );
3016      }
3017  
3018      return $result;
3019  }
3020  
3021  
3022  /**
3023   * Remove current User report from the given user
3024   *
3025   * @param integer user ID
3026   * @return mixed 1 if report was removed, 0 if there was no report, false on failure
3027   */
3028  function remove_report_from( $user_ID )
3029  {
3030      global $DB, $current_User;
3031  
3032      return $DB->query( 'DELETE FROM T_users__reports
3033                          WHERE urep_target_user_ID = '.$DB->quote( $user_ID ).' AND urep_reporter_ID = '.$DB->quote( $current_User->ID ) );
3034  }
3035  
3036  
3037  /**
3038   * Get form to quick users search
3039   *
3040   * @param array Params
3041   * @return string Form
3042   */
3043  function get_user_quick_search_form( $params = array() )
3044  {
3045      $params = array_merge( array(
3046              'before' => '<div class="quick_search_form">',
3047              'after'  => '</div>',
3048              'title'  => T_('Quick search'),
3049              'button' => T_('Find User'),
3050          ), $params );
3051  
3052      $r = $params['before'];
3053  
3054      $Form = new Form();
3055  
3056      $Form->output = false;
3057      $Form->switch_layout( 'none' );
3058  
3059      $r .= $Form->begin_form();
3060  
3061      $Form->hidden( 'ctrl', 'users' );
3062      $Form->add_crumb( 'user' );
3063  
3064      $r .= $Form->text_input( 'user_search', '', 15, $params['title'], '', array( 'maxlength' => 100 ) );
3065  
3066      $r .= $Form->submit_input( array(
3067              'name'  => 'actionArray[search]',
3068              'value' => $params['button']
3069          ) );
3070  
3071      $r .= $Form->end_form();
3072  
3073      $r .= $params['after'];
3074  
3075      return $r;
3076  }
3077  
3078  
3079  /**
3080   * Display a voting form
3081   *
3082   * @param array Params
3083   */
3084  function display_voting_form( $params = array() )
3085  {
3086      $params = array_merge( array(
3087              'vote_type' => 'file',
3088              'vote_ID'   => 0,
3089              'display_like'          => true,
3090              'display_noopinion'     => true,
3091              'display_dontlike'      => true,
3092              'display_inappropriate' => true,
3093              'display_spam'          => true,
3094              'title_text'            => T_('My vote:'),
3095              'title_like'            => T_('I like this picture'),
3096              'title_like_voted'      => T_('You like this!'),
3097              'title_noopinion'       => T_('I have no opinion'),
3098              'title_noopinion_voted' => T_('You have no opinion on this.'),
3099              'title_dontlike'        => T_('I don\'t like this picture'),
3100              'title_dontlike_voted'  => T_('You don\'t like this.'),
3101              'title_inappropriate'   => T_('I think the content of this picture is inappropriate'),
3102              'title_spam'            => T_('I think this picture was posted by a spammer'),
3103          ), $params );
3104  
3105      if( !is_logged_in() || empty( $params['vote_ID'] ) )
3106      {
3107          return;
3108      }
3109  
3110      global $current_User, $DB;
3111  
3112      $params_like = array(
3113              'id' => 'votingLike',
3114              'title' => $params['title_like']
3115          );
3116      $params_noopinion = array(
3117              'id' => 'votingNoopinion',
3118              'title' => $params['title_noopinion']
3119          );
3120      $params_dontlike = array(
3121              'id' => 'votingDontlike',
3122              'title' => $params['title_dontlike']
3123          );
3124      $params_inappropriate = array(
3125              'id' => 'votingInappropriate',
3126              'title' => $params['title_inappropriate']
3127          );
3128      $params_spam = array(
3129              'id' => 'votingSpam',
3130              'title' => $params['title_spam']
3131          );
3132  
3133      switch( $params['vote_type'] )
3134      {    // Get a voting results for current user
3135          case 'file':
3136              // Picture
3137              $SQL = new SQL( 'Get file voting for current user' );
3138              $SQL->SELECT( 'fvot_like AS result, fvot_inappropriate AS inappropriate, fvot_spam AS spam' );
3139              $SQL->FROM( 'T_files__vote' );
3140              $SQL->WHERE( 'fvot_file_ID = '.$DB->quote( $params['vote_ID'] ) );
3141              $SQL->WHERE_and( 'fvot_user_ID = '.$DB->quote( $current_User->ID ) );
3142              $vote = $DB->get_row( $SQL->get() );
3143  
3144              $params_spam['class'] = 'cboxCheckbox';
3145  
3146              break;
3147  
3148          case 'comment':
3149              // Comment
3150              $SQL = new SQL();
3151              $SQL->SELECT( 'cmvt_helpful AS result' );
3152              $SQL->FROM( 'T_comments__votes' );
3153              $SQL->WHERE( 'cmvt_cmt_ID = '.$DB->quote( $params['vote_ID'] ) );
3154              $SQL->WHERE_and( 'cmvt_user_ID = '.$DB->quote( $current_User->ID ) );
3155              $SQL->WHERE_and( 'cmvt_helpful IS NOT NULL' );
3156              $vote = $DB->get_row( $SQL->get() );
3157  
3158              break;
3159      }
3160  
3161      if( empty( $vote ) || is_null( $vote->result ) )
3162      {    // Current user didn't vote for this file yet
3163          $icon_like = 'thumb_up';
3164          $icon_noopinion = 'ban';
3165          $icon_dontlike = 'thumb_down';
3166          $type_voted = '';
3167      }
3168      else
3169      {    // Current user already voted for this file, We should set a disabled icons correctly
3170          switch( $vote->result )
3171          {
3172              case '-1':
3173                  // Don't like
3174                  $type_voted = 'dontlike';
3175                  $icon_like = 'thumb_up_disabled';
3176                  $icon_noopinion = 'ban_disabled';
3177                  $icon_dontlike = 'thumb_down';
3178                  $params_dontlike['class'] = 'voted';
3179                  $params_dontlike['title'] = $params['title_dontlike_voted'];
3180                  unset( $params_dontlike['id'] );
3181                  break;
3182  
3183              case '0':
3184                  // No opinion
3185                  $type_voted = 'noopinion';
3186                  $icon_like = 'thumb_up_disabled';
3187                  $icon_noopinion = 'ban';
3188                  $icon_dontlike = 'thumb_down_disabled';
3189                  $params_noopinion['class'] = 'voted';
3190                  $params_noopinion['title'] = $params['title_noopinion_voted'];
3191                  unset( $params_noopinion['id'] );
3192                  break;
3193  
3194              case '1':
3195                  // Like
3196                  $type_voted = 'like';
3197                  $icon_like = 'thumb_up';
3198                  $icon_noopinion = 'ban_disabled';
3199                  $icon_dontlike = 'thumb_down_disabled';
3200                  $params_like['class'] = 'voted';
3201                  $params_like['title'] = $params['title_like_voted'];
3202                  unset( $params_like['id'] );
3203                  break;
3204          }
3205      }
3206  
3207      $checked_inappropriate = '';
3208      $checked_spam = '';
3209      if( !empty( $vote ) )
3210      {    // Current user already marked this file
3211          if( !empty( $vote->inappropriate ) )
3212          {    // File is marked as 'Inappropriate'
3213              $checked_inappropriate = ' checked="checked"';
3214          }
3215          if( !empty( $vote->spam ) )
3216          {    // File is marked as 'Spam'
3217              $checked_spam = ' checked="checked"';
3218          }
3219      }
3220  
3221      echo '<span>'.$params['title_text'].'</span>';
3222  
3223      // Set this url for case when JavaScript is not enabled
3224      $url = get_secure_htsrv_url().'anon_async.php?action=voting&vote_type='.$params['vote_type'].'&vote_ID='.$params['vote_ID'].'&'.url_crumb( 'voting' );
3225      $redirect_to = regenerate_url();
3226      if( strpos( $redirect_to, 'async.php' ) === false )
3227      {    // Append a redirect param
3228          $url .= '&redirect_to='.$redirect_to;
3229      }
3230  
3231      if( $params['display_like'] )
3232      {    // Display 'Like' icon
3233          $tag_icon = get_icon( $icon_like, 'imgtag', $params_like );
3234          if( $type_voted == 'like' )
3235          {
3236              echo $tag_icon;
3237          }
3238          else
3239          {
3240              $url_like = $url.'&vote_action=like';
3241              $class = ( strpos( $icon_like, 'disabled' ) !== false ) ? ' rollover_sprite' : '';
3242              echo '<a href="'.$url_like.'" class="action_icon'.$class.'">'.$tag_icon.'</a>';
3243          }
3244      }
3245  
3246      if( $params['display_noopinion'] )
3247      {    // Display 'No opinion' icon
3248          $tag_icon = get_icon( $icon_noopinion, 'imgtag', $params_noopinion );
3249          if( $type_voted == 'noopinion' )
3250          {
3251              echo $tag_icon;
3252          }
3253          else
3254          {
3255              $url_noopinion = $url.'&vote_action=noopinion';
3256              $class = ( strpos( $icon_noopinion, 'disabled' ) !== false ) ? ' rollover_sprite' : '';
3257              echo '<a href="'.$url_noopinion.'" class="action_icon'.$class.'">'.$tag_icon.'</a>';
3258          }
3259      }
3260  
3261      if( $params['display_dontlike'] )
3262      {    // Display 'Dont like' icon
3263          $tag_icon = get_icon( $icon_dontlike, 'imgtag', $params_dontlike );
3264          if( $type_voted == 'dontlike' )
3265          {
3266              echo $tag_icon;
3267          }
3268          else
3269          {
3270              $url_dontlike = $url.'&vote_action=dontlike';
3271              $class = ( strpos( $icon_dontlike, 'disabled' ) !== false ) ? ' rollover_sprite' : '';
3272              echo '<a href="'.$url_dontlike.'" class="action_icon'.$class.'">'.$tag_icon.'</a>';
3273          }
3274      }
3275  
3276      if( $params['display_inappropriate'] || $params['display_spam'] )
3277      {    // Display separator between icons and checkboxes
3278          echo '<span class="separator">&nbsp;</span>';
3279      }
3280  
3281      if( $params['display_inappropriate'] )
3282      {    // Display 'Inappropriate' checkbox
3283          echo '<label for="'.$params_inappropriate['id'].'" title="'.$params_inappropriate['title'].'">'.
3284                  '<input type="checkbox" id="'.$params_inappropriate['id'].'" name="'.$params_inappropriate['id'].'"'.$checked_inappropriate.' />'.
3285                  '<span>'.T_('Inappropriate').'</span>'.
3286              '</label>';
3287      }
3288  
3289      if( $params['display_spam'] )
3290      {    // Display 'Spam' checkbox
3291          echo '<label for="'.$params_spam['id'].'" class="'.$params_spam['class'].'" title="'.$params_spam['title'].'">'.
3292                  '<input type="checkbox" id="'.$params_spam['id'].'" name="'.$params_spam['id'].'"'.$checked_spam.' />'.
3293                  '<span>'.T_('Spam').'</span>'.
3294              '</label>';
3295      }
3296  
3297      // Create a hidden input with current ID
3298      echo '<input type="hidden" id="votingID" value="'.$params['vote_ID'].'" />';
3299  }
3300  
3301  
3302  /**
3303   * Find other users with the same email address
3304   *
3305   * @param integer User ID to exclude current edited user from list
3306   * @param string User email
3307   * @param string Message for note about users with the same email
3308   * @return boolean|string FALSE if no users with the same email | Message about other users also have the same email
3309   */
3310  function find_users_with_same_email( $user_ID, $user_email, $message )
3311  {
3312      global $DB;
3313  
3314      $email_users_SQL = new SQL();
3315      $email_users_SQL->SELECT( 'user_ID, user_login' );
3316      $email_users_SQL->FROM( 'T_users' );
3317      $email_users_SQL->WHERE( 'user_email = '.$DB->quote( $user_email ) );
3318      $email_users_SQL->WHERE_and( 'user_ID != '.$DB->quote( $user_ID ) );
3319      $email_users = $DB->get_assoc( $email_users_SQL->get() );
3320      if( empty( $email_users ) )
3321      { // No users found with email
3322          return false;
3323      }
3324  
3325      $users_links = array();
3326      foreach( $email_users as $email_user_ID => $email_user_login )
3327      {
3328          global $admin_url;
3329          $users_links[] = '<a href="'.$admin_url.'?ctrl=user&amp;user_ID='.$email_user_ID.'">'.$email_user_login.'</a>';
3330      }
3331  
3332      return sprintf( $message, $user_email, implode( ', ', $users_links ) );
3333  }
3334  
3335  
3336  /**
3337   * Initialize JavaScript for AJAX loading of popup window to report user
3338   */
3339  function echo_user_report_js()
3340  {
3341      global $rsc_url, $admin_url;
3342  ?>
3343  <script type="text/javascript">
3344  function user_report( user_ID, user_tab_from )
3345  {
3346      userReportForm( '<img src="<?php echo $rsc_url; ?>img/ajax-loader2.gif" alt="<?php echo T_('Loading...'); ?>" title="<?php echo T_('Loading...'); ?>" style="display:block;margin:auto;position:absolute;top:0;bottom:0;left:0;right:0;" />', '680px' );
3347      jQuery.ajax(
3348      {
3349          type: 'POST',
3350          url: '<?php echo $admin_url; ?>',
3351          data:
3352          {
3353              'ctrl': 'user',
3354              'user_tab': 'report',
3355              'user_tab_from': user_tab_from,
3356              'user_ID': user_ID,
3357              'display_mode': 'js',
3358              'crumb_user': '<?php echo get_crumb('user'); ?>',
3359          },
3360          success: function(result)
3361          {
3362              userReportForm( result, '680px' );
3363          }
3364      } );
3365      return false;
3366  }
3367  
3368  /*
3369   * This is called when we get the response from the server:
3370   */
3371  function userReportForm( the_html, width )
3372  {
3373      if( typeof width == 'undefined' )
3374      {
3375          width = '560px';
3376      }
3377  
3378      // add placeholder for antispam settings form:
3379      jQuery( 'body' ).append( '<div id="screen_mask" onclick="closeUserReportForm()"></div><div id="overlay_page" style="width:' + width + '"></div>' );
3380      var evobar_height = jQuery( '#evo_toolbar' ).height();
3381      jQuery( '#screen_mask' ).css({ top: evobar_height });
3382      jQuery( '#screen_mask' ).fadeTo(1,0.5).fadeIn(200);
3383      jQuery( '#overlay_page' ).html( the_html ).addClass( 'overlay_page_active_transparent' );
3384      jQuery( '#close_button' ).bind( 'click', closeUserReportForm );
3385  
3386      // Close antispam popup if Escape key is pressed:
3387      var keycode_esc = 27;
3388      jQuery(document).keyup(function(e)
3389      {
3390          if( e.keyCode == keycode_esc )
3391          {
3392              closeUserReportForm();
3393          }
3394      } );
3395  }
3396  
3397  // This is called to close the antispam ban overlay page
3398  function closeUserReportForm()
3399  {
3400      jQuery( '#overlay_page' ).hide();
3401      jQuery( '.action_messages').remove();
3402      jQuery( '#server_messages' ).insertBefore( '.first_payload_block' );
3403      jQuery( '#overlay_page' ).remove();
3404      jQuery( '#screen_mask' ).remove();
3405      return false;
3406  }
3407  </script>
3408  <?php
3409  }
3410  
3411  
3412  /**
3413   * Display user report form
3414   *
3415   * @param array Params
3416   */
3417  function user_report_form( $params = array() )
3418  {
3419      global $current_User;
3420  
3421      $params = array_merge( array(
3422              'Form'       => NULL,
3423              'user_ID'    => 0,
3424              'crumb_name' => '',
3425              'cancel_url' => '',
3426          ), $params );
3427  
3428      if( ! is_logged_in() || $current_User->ID == $params['user_ID'] || ! $current_User->check_status( 'can_report_user' ) )
3429      { // Current user must be logged in, cannot report own account, and must has a permission to report
3430          return;
3431      }
3432  
3433      $Form = & $params['Form'];
3434  
3435      $Form->add_crumb( $params['crumb_name'] );
3436      $Form->hidden( 'user_ID', $params['user_ID'] );
3437  
3438      $report_options = array_merge( array( 'none' => '' ), get_report_statuses() );
3439  
3440      $Form->custom_content( '<p><strong>'.get_icon('warning_yellow').' '.T_( 'If you have an issue with this user, you can report it here:' ).'</strong></p>' );
3441  
3442      // get current User report from edited User
3443      $current_report = get_report_from( $params['user_ID'] );
3444  
3445      if( $current_report == NULL )
3446      { // currentUser didn't add any report from this user yet
3447          $report_content = '<select id="report_user_status" name="report_user_status">';
3448          foreach( $report_options as $option => $option_label )
3449          { // add select option, none must be selected
3450              $report_content .= '<option '.( ( $option == 'none' ) ? 'selected="selected" ' : '' ).'value="'.$option.'">'.$option_label.'</option>';
3451          }
3452          $report_content .= '</select><div id="report_info" style="width:100%;"></div>';
3453  
3454          $info_content = '<div><span>'.T_('You can provide additional information below').':</span></div>';
3455          $info_content .= '<table style="width:100%;"><td style="width:99%;background-color:inherit;"><textarea id="report_info_content" name="report_info_content" class="form_textarea_input" style="width:100%;" rows="2" maxlength="240"></textarea></td>';
3456          $info_content .= '<td style="vertical-align:top;background-color:inherit;"><input type="submit" class="SaveButton" style="color:red;margin-left:2px;" value="'.T_('Report this user now!').'" name="actionArray[report_user]" /></td></table>';
3457          $report_content .= '<script type="text/javascript">
3458              var info_content = \''.$info_content.'\';
3459              jQuery("#report_user_status").change( function() {
3460                  var report_info = jQuery("#report_info");
3461                  var value = jQuery(this).val();
3462                  if( value == "none" )
3463                  {
3464                      report_info.html("");
3465                  }
3466                  else if( report_info.is(":empty") )
3467                  {
3468                      report_info.html( info_content );
3469                  }
3470              });
3471              </script>';
3472          $report_content .= '<noscript>'.$info_content.'</noscript>';
3473          $Form->info( T_('Report NOW'), $report_content );
3474      }
3475      else
3476      {
3477          $report_content = T_('You have reported this user on %s as "%s" with the additional info "%s" - <a %s>Cancel report</a>');
3478          $report_content = sprintf( $report_content, mysql2localedatetime( $current_report[ 'date' ] ), $report_options[ $current_report[ 'status' ] ], $current_report[ 'info' ], 'href="'.$params['cancel_url'].'"' );
3479          $Form->info( T_('Already reported'), $report_content );
3480      }
3481  }
3482  
3483  
3484  /**
3485   * Get IDs of users by logins separated by comma
3486   * Used to filter the posts by authors and assigned users
3487   *
3488   * @param string Logins (e.g. 'admin,ablogger,auser')
3489   * @return string Users IDs (e.g. '1,3,5')
3490   */
3491  function get_users_IDs_by_logins( $logins )
3492  {
3493      if( empty( $logins ) )
3494      {
3495          return '';
3496      }
3497  
3498      $UserCache = & get_UserCache();
3499  
3500      $logins = explode( ',', $logins );
3501      $ids = array();
3502      foreach( $logins as $login )
3503      {
3504          if( $User = $UserCache->get_by_login( $login, true ) )
3505          { // User exists with this login
3506              $ids[] = $User->ID;
3507          }
3508      }
3509  
3510      return implode( ',', $ids );
3511  }
3512  
3513  
3514  /**
3515   * Display user's reposts results table
3516   *
3517   * @param array Params
3518   */
3519  function user_reports_results_block( $params = array() )
3520  {
3521      // Make sure we are not missing any param:
3522      $params = array_merge( array(
3523              'edited_User'          => NULL,
3524              'results_param_prefix' => 'actv_reports_',
3525              'results_title'        => T_('This user profile has been reported by other users!'),
3526              'results_no_text'      => T_('User was not reported yet.'),
3527          ), $params );
3528  
3529      if( !is_logged_in() )
3530      {    // Only logged in users can access to this function
3531          return;
3532      }
3533  
3534      global $current_User;
3535      if( !$current_User->check_perm( 'users', 'edit' ) )
3536      {    // Check minimum permission:
3537          return;
3538      }
3539  
3540      $edited_User = $params['edited_User'];
3541      if( !$edited_User )
3542      {    // No defined User, probably the function is calling from AJAX request
3543          $user_ID = param( 'user_ID', 'integer', 0 );
3544          if( empty( $user_ID ) )
3545          {    // Bad request, Exit here
3546              return;
3547          }
3548          $UserCache = & get_UserCache();
3549          if( ( $edited_User = & $UserCache->get_by_ID( $user_ID, false ) ) === false )
3550          {    // Bad request, Exit here
3551              return;
3552          }
3553      }
3554  
3555      global $DB;
3556  
3557      param( 'user_tab', 'string', '', true );
3558      param( 'user_ID', 'integer', 0, true );
3559  
3560  
3561      $SQL = new SQL();
3562      $SQL->SELECT( 'user_login, urep_datetime, urep_status, urep_info' );
3563      $SQL->FROM( 'T_users__reports' );
3564      $SQL->FROM_add( 'LEFT JOIN T_users ON user_ID = urep_reporter_ID' );
3565      $SQL->WHERE( 'urep_target_user_ID = '.$DB->quote( $edited_User->ID ) );
3566  
3567      // Create result set:
3568      $reports_Results = new Results( $SQL->get(), $params['results_param_prefix'], 'D' );
3569      $reports_Results->title = $params['results_title'];
3570      $reports_Results->no_results_text = $params['results_no_text'];
3571  
3572      // Initialize Results object
3573      user_reports_results( $reports_Results );
3574  
3575      if( is_ajax_content() )
3576      {    // init results param by template name
3577          if( !isset( $params[ 'skin_type' ] ) || ! isset( $params[ 'skin_name' ] ) )
3578          {
3579              debug_die( 'Invalid ajax results request!' );
3580          }
3581          $reports_Results->init_params_by_skin( $params[ 'skin_type' ], $params[ 'skin_name' ] );
3582      }
3583  
3584      $display_params = array(
3585          'before' => '<div class="results" style="margin-top:25px" id="reports_result">'
3586      );
3587      $reports_Results->display( $display_params );
3588  
3589      if( !is_ajax_content() )
3590      {    // Create this hidden div to get a function name for AJAX request
3591          echo '<div id="'.$params['results_param_prefix'].'ajax_callback" style="display:none">'.__FUNCTION__.'</div>';
3592      }
3593  
3594      // Who should be able to delete other users reports???
3595      /*if( $reports_Results->total_rows > 0 )
3596      {    // Display button to delete all records if at least one record exists & current user can delete at least one item created by user
3597          echo action_icon( sprintf( T_('Delete all reports from %s'), $edited_User->login ), 'delete', '?ctrl=user&amp;user_tab=activity&amp;action=delete_all_reports_from&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.T_('Delete all'), 3, 4 );
3598      }*/
3599  }
3600  
3601  
3602  /**
3603   * Initialize Results object for threads list
3604   *
3605   * @param object Results
3606   * @param array Params
3607   */
3608  function user_reports_results( & $reports_Results, $params = array() )
3609  {
3610      $reports_Results->cols[] = array(
3611          'th' => T_('Date and time'),
3612          'order' => 'urep_datetime',
3613          'default_dir' => 'D',
3614          'th_class' => 'nowrap',
3615          'td_class' => 'shrinkwrap',
3616          'td' => '<span class="date">%mysql2localedatetime( #urep_datetime# )%</span>',
3617      );
3618  
3619      $reports_Results->cols[] = array(
3620          'th' => T_('Reporting user'),
3621          'order' => 'user_login',
3622          'td_class' => 'left',
3623          'td' => '%get_user_identity_link( #user_login# )%',
3624      );
3625  
3626      $reports_Results->cols[] = array(
3627          'th' => T_('Selected option in the select list'),
3628          'order' => 'urep_status',
3629          'td_class' => 'nowrap',
3630          'td' => '%get_report_status_text( #urep_status# )%',
3631      );
3632  
3633      $reports_Results->cols[] = array(
3634          'th' => T_('Additional info'),
3635          'order' => 'urep_info',
3636          'td_class' => 'left',
3637          'td' => '$urep_info$',
3638      );
3639  }
3640  
3641  
3642  /**
3643   * Helper functions to display User's reports results.
3644   * New ( not display helper ) functions must be created above user_reports_results function
3645   */
3646  
3647  function get_report_status_text( $status )
3648  {
3649      $statuses = get_report_statuses();
3650      return isset( $statuses[ $status ] ) ? $statuses[ $status ] : '';
3651  }
3652  
3653  /**
3654   * Helper functions to display User's reports results.
3655   * New ( not display helper ) functions must be created above user_reports_results function
3656   */
3657  ?>

title

Description

title

Description

title

Description

title

title

Body