Textpattern PHP Cross Reference Content Management Systems

Source: /textpattern/include/txp_admin.php - 789 lines - 22621 bytes - Summary - Text - Print

Description: Users panel.

   1  <?php
   2  
   3  /*
   4   * Textpattern Content Management System
   5   * http://textpattern.com
   6   *
   7   * Copyright (C) 2005 Dean Allen
   8   * Copyright (C) 2016 The Textpattern Development Team
   9   *
  10   * This file is part of Textpattern.
  11   *
  12   * Textpattern is free software; you can redistribute it and/or
  13   * modify it under the terms of the GNU General Public License
  14   * as published by the Free Software Foundation, version 2.
  15   *
  16   * Textpattern is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19   * GNU General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU General Public License
  22   * along with Textpattern. If not, see <http://www.gnu.org/licenses/>.
  23   */
  24  
  25  /**
  26   * Users panel.
  27   *
  28   * @package Admin\Admin
  29   */
  30  
  31  use Textpattern\Search\Filter;
  32  
  33  if (!defined('txpinterface')) {
  34      die('txpinterface is undefined.');
  35  }
  36  
  37  $levels = get_groups();
  38  
  39  if ($event == 'admin') {
  40      require_privs('admin');
  41  
  42      include_once txpath.'/lib/txplib_admin.php';
  43  
  44      $available_steps = array(
  45          'admin_multi_edit'    => true,
  46          'admin_change_pageby' => true,
  47          'author_list'         => false,
  48          'author_edit'         => false,
  49          'author_save'         => true,
  50          'author_save_new'     => true,
  51          'change_email'        => true,
  52          'change_email_form'   => false,
  53          'change_pass'         => true,
  54          'new_pass_form'       => false,
  55      );
  56  
  57      if ($step && bouncer($step, $available_steps)) {
  58          $step();
  59      } else {
  60          author_list();
  61      }
  62  }
  63  
  64  /**
  65   * Changes an email address.
  66   */
  67  
  68  function change_email()
  69  {
  70      global $txp_user;
  71  
  72      $new_email = ps('new_email');
  73  
  74      if (!is_valid_email($new_email)) {
  75          change_email_form(array(gTxt('email_required'), E_ERROR));
  76  
  77          return;
  78      }
  79  
  80      $rs = update_user($txp_user, $new_email);
  81  
  82      if ($rs) {
  83          author_list(gTxt('email_changed', array('{email}' => $new_email)));
  84  
  85          return;
  86      }
  87  
  88      change_email_form(array(gTxt('author_save_failed'), E_ERROR));
  89  }
  90  
  91  /**
  92   * Updates a user.
  93   */
  94  
  95  function author_save()
  96  {
  97      global $txp_user;
  98  
  99      require_privs('admin.edit');
 100  
 101      extract(psa(array(
 102          'privs',
 103          'name',
 104          'RealName',
 105          'email',
 106      )));
 107  
 108      $privs = assert_int($privs);
 109  
 110      if (!is_valid_email($email)) {
 111          author_edit(array(gTxt('email_required'), E_ERROR));
 112  
 113          return;
 114      }
 115  
 116      $rs = update_user($name, $email, $RealName);
 117  
 118      if ($rs && ($txp_user === $name || change_user_group($name, $privs))) {
 119          author_list(gTxt('author_updated', array('{name}' => $RealName)));
 120  
 121          return;
 122      }
 123  
 124      author_edit(array(gTxt('author_save_failed'), E_ERROR));
 125  }
 126  
 127  /**
 128   * Changes current user's password.
 129   */
 130  
 131  function change_pass()
 132  {
 133      global $txp_user;
 134  
 135      extract(psa(array('current_pass', 'new_pass')));
 136  
 137      if (empty($new_pass)) {
 138          new_pass_form(array(gTxt('password_required'), E_ERROR));
 139  
 140          return;
 141      }
 142  
 143      if (txp_validate($txp_user, $current_pass)) {
 144          $rs = change_user_password($txp_user, $new_pass);
 145  
 146          if ($rs) {
 147              $message = gTxt('password_changed');
 148              author_list($message);
 149          }
 150      } else {
 151          new_pass_form(array(gTxt('password_invalid'), E_ERROR));
 152      }
 153  }
 154  
 155  /**
 156   * Creates a new user.
 157   */
 158  
 159  function author_save_new()
 160  {
 161      require_privs('admin.edit');
 162  
 163      extract(psa(array(
 164          'privs',
 165          'name',
 166          'email',
 167          'RealName',
 168      )));
 169  
 170      $privs = assert_int($privs);
 171  
 172      if (is_valid_username($name) && is_valid_email($email)) {
 173          if (user_exists($name)) {
 174              author_edit(array(gTxt('author_already_exists', array('{name}' => $name)), E_ERROR));
 175  
 176              return;
 177          }
 178  
 179          $password = Txp::get('\Textpattern\Password\Random')->generate(PASSWORD_LENGTH);
 180  
 181          $rs = create_user($name, $email, $password, $RealName, $privs);
 182  
 183          if ($rs) {
 184              $message = send_account_activation($name);
 185  
 186              author_list($message);
 187  
 188              return;
 189          }
 190      }
 191  
 192      author_edit(array(gTxt('error_adding_new_author'), E_ERROR));
 193  }
 194  
 195  /**
 196   * Lists user groups as a &lt;select&gt; input.
 197   *
 198   * @param  int $priv Selected option
 199   * @return string HTML
 200   */
 201  
 202  function privs($priv = '')
 203  {
 204      global $levels;
 205  
 206      return selectInput('privs', $levels, $priv, '', '', 'privileges');
 207  }
 208  
 209  /**
 210   * Translates a numeric ID to a human-readable user group.
 211   *
 212   * @param  int $priv The group
 213   * @return string
 214   */
 215  
 216  function get_priv_level($priv)
 217  {
 218      global $levels;
 219  
 220      return $levels[$priv];
 221  }
 222  
 223  /**
 224   * Password changing form.
 225   *
 226   * @param string|array $message The activity message
 227   */
 228  
 229  function new_pass_form($message = '')
 230  {
 231      pagetop(gTxt('tab_site_admin'), $message);
 232  
 233      echo form(
 234          hed(gTxt('change_password'), 2).
 235          inputLabel(
 236              'current_pass',
 237              fInput('password', 'current_pass', '', '', '', '', INPUT_REGULAR, '', 'current_pass'),
 238              'current_password', '', array('class' => 'txp-form-field edit-admin-current-password')
 239          ).
 240          inputLabel(
 241              'new_pass',
 242              fInput('password', 'new_pass', '', 'txp-maskable txp-strength-hint', '', '', INPUT_REGULAR, '', 'new_pass').
 243              n.tag(null, 'div', array('class' => 'strength-meter')).
 244              n.tag(
 245                  checkbox('unmask', 1, false, 0, 'show_password').
 246                  n.tag(gTxt('show_password'), 'label', array('for' => 'show_password')),
 247                  'div', array('class' => 'edit-admin-show-password')),
 248              'new_password', '', array('class' => 'txp-form-field edit-admin-new-password')
 249          ).
 250          graf(
 251              sLink('admin', '', gTxt('cancel'), 'txp-button').
 252              fInput('submit', 'change_pass', gTxt('submit'), 'publish'),
 253              array('class' => 'txp-edit-actions')
 254          ).
 255          eInput('admin').
 256          sInput('change_pass'),
 257      '', '', 'post', 'txp-edit', '', 'change_password');
 258  }
 259  
 260  /**
 261   * Email changing form.
 262   *
 263   * @param string|array $message The activity message
 264   */
 265  
 266  function change_email_form($message = '')
 267  {
 268      global $txp_user;
 269  
 270      pagetop(gTxt('tab_site_admin'), $message);
 271  
 272      $email = fetch('email', 'txp_users', 'name', $txp_user);
 273  
 274      echo form(
 275          hed(gTxt('change_email_address'), 2).
 276          inputLabel(
 277              'new_email',
 278              fInput('text', 'new_email', $email, '', '', '', INPUT_REGULAR, '', 'new_email'),
 279              'new_email', '', array('class' => 'txp-form-field edit-admin-new-email')
 280          ).
 281          graf(
 282              sLink('admin', '', gTxt('cancel'), 'txp-button').
 283              fInput('submit', 'change_email', gTxt('submit'), 'publish'),
 284              array('class' => 'txp-edit-actions')
 285          ).
 286          eInput('admin').
 287          sInput('change_email'),
 288      '', '', 'post', 'txp-edit', '', 'change_email');
 289  }
 290  
 291  /**
 292   * The main panel listing all authors.
 293   *
 294   * @param string|array $message The activity message
 295   */
 296  
 297  function author_list($message = '')
 298  {
 299      global $event, $txp_user, $author_list_pageby, $levels;
 300  
 301      pagetop(gTxt('tab_site_admin'), $message);
 302  
 303      if (is_disabled('mail')) {
 304          echo graf(
 305              span(null, array('class' => 'ui-icon ui-icon-alert')).' '.
 306              gTxt('warn_mail_unavailable'),
 307              array('class' => 'alert-block warning')
 308          );
 309      }
 310  
 311      $buttons = array();
 312  
 313      // Change password button.
 314      $buttons[] = sLink('admin', 'new_pass_form', gTxt('change_password'), 'txp-button');
 315  
 316      if (!has_privs('admin.edit')) {
 317          // Change email address button.
 318          $buttons[] = sLink('admin', 'change_email_form', gTxt('change_email_address'), 'txp-button');
 319      } else {
 320          // New author button.
 321          $buttons[] = sLink('admin', 'author_edit', gTxt('add_new_author'), 'txp-button');
 322      }
 323  
 324      // User list.
 325      if (has_privs('admin.list')) {
 326          extract(gpsa(array(
 327              'page',
 328              'sort',
 329              'dir',
 330              'crit',
 331              'search_method',
 332          )));
 333  
 334          if ($sort === '') {
 335              $sort = get_pref('admin_sort_column', 'name');
 336          } else {
 337              if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
 338                  $sort = 'name';
 339              }
 340  
 341              set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE);
 342          }
 343  
 344          if ($dir === '') {
 345              $dir = get_pref('admin_sort_dir', 'asc');
 346          } else {
 347              $dir = ($dir == 'desc') ? "desc" : "asc";
 348              set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE);
 349          }
 350  
 351          $sort_sql = $sort.' '.$dir;
 352  
 353          $switch_dir = ($dir == 'desc') ? 'asc' : 'desc';
 354  
 355          $search = new Filter($event,
 356              array(
 357                  'login' => array(
 358                      'column' => 'txp_users.name',
 359                      'label'  => gTxt('login_name'),
 360                  ),
 361                  'RealName' => array(
 362                      'column' => 'txp_users.RealName',
 363                      'label'  => gTxt('real_name'),
 364                  ),
 365                  'email' => array(
 366                      'column' => 'txp_users.email',
 367                      'label'  => gTxt('email'),
 368                  ),
 369                  'privs' => array(
 370                      'column' => array('txp_users.privs'),
 371                      'label'  => gTxt('privileges'),
 372                      'type'   => 'boolean',
 373                  ),
 374              )
 375          );
 376  
 377          $search->setAliases('privs', $levels);
 378  
 379          list($criteria, $crit, $search_method) = $search->getFilter();
 380  
 381          $search_render_options = array(
 382              'placeholder' => 'search_users',
 383          );
 384  
 385          $total = getCount('txp_users', $criteria);
 386  
 387          echo n.'<div class="txp-layout">'.
 388              n.tag(
 389                  hed(gTxt('tab_site_admin'), 1, array('class' => 'txp-heading')),
 390                  'div', array('class' => 'txp-layout-4col-alt')
 391              );
 392  
 393          $searchBlock =
 394              n.tag(
 395                  $search->renderForm('author_list', $search_render_options),
 396                  'div', array(
 397                      'class' => 'txp-layout-4col-3span',
 398                      'id'    => 'users_control',
 399                  )
 400              );
 401  
 402          $createBlock = array();
 403  
 404          $createBlock[] = n.tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel'));
 405  
 406          $contentBlockStart = n.tag_start('div', array(
 407                  'class' => 'txp-layout-1col',
 408                  'id'    => 'users_container',
 409              ));
 410  
 411          $createBlock = implode(n, $createBlock);
 412  
 413          if ($total < 1) {
 414              if ($criteria != 1) {
 415                  echo $searchBlock.
 416                      $contentBlockStart.
 417                      $createBlock.
 418                      graf(
 419                          span(null, array('class' => 'ui-icon ui-icon-info')).' '.
 420                          gTxt('no_results_found'),
 421                          array('class' => 'alert-block information')
 422                      ).
 423                      n.tag_end('div'). // End of .txp-layout-1col.
 424                      n.'</div>'; // End of .txp-layout.
 425              }
 426  
 427              return;
 428          }
 429  
 430          $limit = max($author_list_pageby, 15);
 431  
 432          list($page, $offset, $numPages) = pager($total, $limit, $page);
 433  
 434          $use_multi_edit = (has_privs('admin.edit') && ($total > 1 or safe_count('txp_users', "1 = 1") > 1));
 435  
 436          echo $searchBlock.$contentBlockStart.$createBlock;
 437  
 438          $rs = safe_rows_start(
 439              "*, UNIX_TIMESTAMP(last_access) AS last_login",
 440              'txp_users',
 441              "$criteria ORDER BY $sort_sql LIMIT $offset, $limit"
 442          );
 443  
 444          if ($rs) {
 445              echo
 446                  n.tag_start('form', array(
 447                      'class'  => 'multi_edit_form',
 448                      'id'     => 'users_form',
 449                      'name'   => 'longform',
 450                      'method' => 'post',
 451                      'action' => 'index.php',
 452                  )).
 453                  n.tag_start('div', array('class' => 'txp-listtables')).
 454                  n.tag_start('table', array('class' => 'txp-list')).
 455                  n.tag_start('thead').
 456                  tr(
 457                      (
 458                          ($use_multi_edit)
 459                          ? hCell(
 460                              fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'),
 461                                  '', ' class="txp-list-col-multi-edit" scope="col" title="'.gTxt('toggle_all_selected').'"'
 462                          )
 463                          : hCell('', '', ' class="txp-list-col-multi-edit" scope="col"')
 464                      ).
 465                      column_head(
 466                          'login_name', 'name', 'admin', true, $switch_dir, '', '',
 467                              (('name' == $sort) ? "$dir " : '').'txp-list-col-login-name name'
 468                      ).
 469                      column_head(
 470                          'real_name', 'RealName', 'admin', true, $switch_dir, '', '',
 471                              (('RealName' == $sort) ? "$dir " : '').'txp-list-col-real-name name'
 472                      ).
 473                      column_head(
 474                          'email', 'email', 'admin', true, $switch_dir, '', '',
 475                              (('email' == $sort) ? "$dir " : '').'txp-list-col-email'
 476                      ).
 477                      column_head(
 478                          'privileges', 'privs', 'admin', true, $switch_dir, '', '',
 479                              (('privs' == $sort) ? "$dir " : '').'txp-list-col-privs'
 480                      ).
 481                      column_head(
 482                          'last_login', 'last_login', 'admin', true, $switch_dir, '', '',
 483                              (('last_login' == $sort) ? "$dir " : '').'txp-list-col-last-login date'
 484                      )
 485                  ).
 486                  n.tag_end('thead').
 487                  n.tag_start('tbody');
 488  
 489              while ($a = nextRow($rs)) {
 490                  extract(doSpecial($a));
 491  
 492                  echo tr(
 493                      td(
 494                          ((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : ''), '', 'txp-list-col-multi-edit'
 495                      ).
 496                      hCell(
 497                          ((has_privs('admin.edit')) ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name), '', ' class="txp-list-col-login-name name" scope="row"'
 498                      ).
 499                      td(
 500                          $RealName, '', 'txp-list-col-real-name name'
 501                      ).
 502                      td(
 503                          href($email, 'mailto:'.$email), '', 'txp-list-col-email'
 504                      ).
 505                      td(
 506                          get_priv_level($privs), '', 'txp-list-col-privs'
 507                      ).
 508                      td(
 509                          ($last_login ? safe_strftime('%b&#160;%Y', $last_login) : ''), '', 'txp-list-col-last-login date'
 510                      )
 511                  );
 512              }
 513  
 514              echo
 515                  n.tag_end('tbody').
 516                  n.tag_end('table').
 517                  n.tag_end('div'). // End of .txp-listtables.
 518                  (
 519                      ($use_multi_edit)
 520                      ? author_multiedit_form($page, $sort, $dir, $crit, $search_method)
 521                      : ''
 522                  ).
 523                  tInput().
 524                  n.tag_end('form').
 525                  n.tag_start('div', array(
 526                      'class' => 'txp-navigation',
 527                      'id'    => 'users_navigation',
 528                  )).
 529                  pageby_form('admin', $author_list_pageby).
 530                  nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method).
 531                  n.tag_end('div');
 532          }
 533  
 534          echo n.tag_end('div'); // End of .txp-layout-1col.
 535      } else {
 536          echo
 537              n.tag_start('div', array(
 538                  'class' => 'txp-layout-1col',
 539                  'id'    => 'users_container',
 540              )).
 541              n.tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel')).
 542              n.tag_end('div'); // End of .txp-layout-1col.
 543      }
 544  
 545      echo n.'</div>'; // End of .txp-layout.
 546  }
 547  
 548  /**
 549   * Renders and outputs the user editor panel.
 550   *
 551   * Accessing requires 'admin.edit' privileges.
 552   *
 553   * @param string|array $message The activity message
 554   */
 555  
 556  function author_edit($message = '')
 557  {
 558      global $step, $txp_user;
 559  
 560      require_privs('admin.edit');
 561  
 562      pagetop(gTxt('tab_site_admin'), $message);
 563  
 564      $vars = array('user_id', 'name', 'RealName', 'email', 'privs');
 565      $rs = array();
 566      $out = array();
 567  
 568      extract(gpsa($vars));
 569  
 570      $is_edit = ($user_id && $step == 'author_edit');
 571  
 572      if ($is_edit) {
 573          $user_id = assert_int($user_id);
 574          $rs = safe_row("*", 'txp_users', "user_id = $user_id");
 575          extract($rs);
 576      }
 577  
 578      if ($is_edit) {
 579          $out[] = hed(gTxt('edit_author'), 2);
 580      } else {
 581          $out[] = hed(gTxt('add_new_author'), 2);
 582      }
 583  
 584      if ($is_edit) {
 585          $out[] = inputLabel(
 586              'login_name',
 587              strong(txpspecialchars($name)),
 588              '', '', array('class' => 'txp-form-field edit-admin-login-name')
 589          );
 590      } else {
 591          $out[] = inputLabel(
 592              'login_name',
 593              fInput('text', 'name', $name, '', '', '', INPUT_REGULAR, '', 'login_name'),
 594              'login_name', 'add_new_author', array('class' => 'txp-form-field edit-admin-login-name')
 595          );
 596      }
 597  
 598      $out[] = inputLabel(
 599              'real_name',
 600              fInput('text', 'RealName', $RealName, '', '', '', INPUT_REGULAR, '', 'real_name'),
 601              'real_name', '', array('class' => 'txp-form-field edit-admin-name')
 602          ).
 603          inputLabel(
 604              'login_email',
 605              fInput('email', 'email', $email, '', '', '', INPUT_REGULAR, '', 'login_email'),
 606              'email', '', array('class' => 'txp-form-field edit-admin-email')
 607          );
 608  
 609      if ($txp_user != $name) {
 610          $out[] = inputLabel(
 611              'privileges',
 612              privs($privs),
 613              'privileges', 'about_privileges', array('class' => 'txp-form-field edit-admin-privileges')
 614          );
 615      } else {
 616          $out[] = inputLabel(
 617              'privileges',
 618              strong(get_priv_level($privs)),
 619              '', '', array('class' => 'txp-form-field edit-admin-privileges')
 620          ).
 621          hInput('privs', $privs);
 622      }
 623  
 624      $out[] = pluggable_ui('author_ui', 'extend_detail_form', '', $rs).
 625          graf(
 626              sLink('admin', '', gTxt('cancel'), 'txp-button').
 627              fInput('submit', '', gTxt('save'), 'publish'),
 628              array('class' => 'txp-edit-actions')
 629          ).
 630          eInput('admin');
 631  
 632      if ($user_id) {
 633          $out[] = hInput('user_id', $user_id).
 634              hInput('name', $name).
 635              sInput('author_save');
 636      } else {
 637          $out[] = sInput('author_save_new');
 638      }
 639  
 640      echo form(join('', $out), '', '', 'post', 'txp-edit', '', 'user_edit');
 641  }
 642  
 643  /**
 644   * Updates pageby value.
 645   */
 646  
 647  function admin_change_pageby()
 648  {
 649      event_change_pageby('author');
 650      author_list();
 651  }
 652  
 653  /**
 654   * Renders multi-edit form.
 655   *
 656   * @param  int    $page          The page
 657   * @param  string $sort          The sorting value
 658   * @param  string $dir           The sorting direction
 659   * @param  string $crit          The search string
 660   * @param  string $search_method The search method
 661   * @return string HTML
 662   */
 663  
 664  function author_multiedit_form($page, $sort, $dir, $crit, $search_method)
 665  {
 666      $privileges = privs();
 667      $users = safe_column("name", 'txp_users', "1 = 1");
 668  
 669      $methods = array(
 670          'changeprivilege'  => array('label' => gTxt('changeprivilege'), 'html' => $privileges),
 671          'resetpassword'    => gTxt('resetpassword'),
 672          'resendactivation' => gTxt('resend_activation'),
 673      );
 674  
 675      if (count($users) > 1) {
 676          $methods['delete'] = array(
 677              'label' => gTxt('delete'),
 678              'html'  => tag(gTxt('assign_assets_to'), 'label', array('for' => 'assign_assets')).
 679                  selectInput('assign_assets', $users, '', true, '', 'assign_assets'),
 680          );
 681      }
 682  
 683      return multi_edit($methods, 'admin', 'admin_multi_edit', $page, $sort, $dir, $crit, $search_method);
 684  }
 685  
 686  /**
 687   * Processes multi-edit actions.
 688   *
 689   * Accessing requires 'admin.edit' privileges.
 690   */
 691  
 692  function admin_multi_edit()
 693  {
 694      global $txp_user;
 695  
 696      require_privs('admin.edit');
 697  
 698      $selected = ps('selected');
 699      $method = ps('edit_method');
 700      $changed = array();
 701      $msg = '';
 702  
 703      if (!$selected or !is_array($selected)) {
 704          return author_list();
 705      }
 706  
 707      $clause = '';
 708  
 709      if ($method === 'resetpassword') {
 710          $clause = " AND last_access IS NOT NULL";
 711      } elseif ($method === 'resendactivation') {
 712          $clause = " AND last_access IS NULL";
 713      }
 714  
 715      $names = safe_column(
 716          "name",
 717          'txp_users',
 718          "name IN (".join(',', quote_list($selected)).") AND name != '".doSlash($txp_user)."'".$clause
 719      );
 720  
 721      if (!$names) {
 722          return author_list();
 723      }
 724  
 725      switch ($method) {
 726          case 'delete':
 727  
 728              $assign_assets = ps('assign_assets');
 729  
 730              if (!$assign_assets) {
 731                  $msg = array('must_reassign_assets', E_ERROR);
 732              } elseif (in_array($assign_assets, $names)) {
 733                  $msg = array('cannot_assign_assets_to_deletee', E_ERROR);
 734              } elseif (remove_user($names, $assign_assets)) {
 735                  $changed = $names;
 736                  callback_event('authors_deleted', '', 0, $changed);
 737                  $msg = 'author_deleted';
 738              }
 739  
 740              break;
 741  
 742          case 'changeprivilege':
 743  
 744              if (change_user_group($names, ps('privs'))) {
 745                  $changed = $names;
 746                  $msg = 'author_updated';
 747              }
 748  
 749              break;
 750  
 751          case 'resetpassword':
 752  
 753              foreach ($names as $name) {
 754                  send_reset_confirmation_request($name);
 755                  $changed[] = $name;
 756              }
 757  
 758              $msg = 'password_reset_confirmation_request_sent';
 759              break;
 760  
 761          case 'resendactivation':
 762  
 763              foreach ($names as $name) {
 764                  send_account_activation($name);
 765                  $changed[] = $name;
 766              }
 767  
 768              $msg = 'resend_activation_request_sent';
 769              break;
 770      }
 771  
 772      if ($changed) {
 773          return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed)))));
 774      }
 775  
 776      author_list($msg);
 777  }
 778  
 779  /**
 780   * Legacy panel.
 781   *
 782   * @param      string|array $message
 783   * @deprecated in 4.2.0
 784   */
 785  
 786  function admin($message = '')
 787  {
 788      author_list($message);
 789  }

title

Description

title

Description

title

Description

title

title

Body