Changeset 25194 for trunk/admin


Ignore:
Timestamp:
Oct 28, 2013, 5:25:46 PM (10 years ago)
Author:
plg
Message:

feature 1668, in progress: redesign user manager (jQuery datatables, AJAX calls)

Location:
trunk/admin
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/themes/default/template/user_list.tpl

    r12887 r25194  
     1{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
     2
     3{combine_script id='jquery.dataTables' load='footer' path='themes/default/js/plugins/jquery.dataTables.js'}
     4{combine_css path="themes/default/js/plugins/datatables/css/jquery.dataTables.css"}
     5
     6{footer_script}
     7var selectedMessage_pattern = "{'%d of %d photos selected'|@translate}";
     8var selectedMessage_none = "{'No photo selected, %d photos in current set'|@translate}";
     9var selectedMessage_all = "{'All %d photos are selected'|@translate}";
     10var applyOnDetails_pattern = "{'on the %d selected users'|@translate}";
     11var missingConfirm = "{'You need to confirm deletion'|translate}";
     12
     13var allUsers = [{$all_users}];
     14var selection = [{$selection}];
     15{/footer_script}
     16
     17{footer_script}{literal}
     18jQuery(document).ready(function() {
     19  /* first column must be prefixed with the open/close icon */
     20  var aoColumns = [
     21    {
     22      'bVisible':false
     23    },
     24    {
     25      "mRender": function(data, type, full) {
     26        return '<label><input type="checkbox" data-user_id="'+full[0]+'"> '+data+'</label>';
     27      }
     28    }
     29  ];
     30
     31  for (i=2; i<jQuery("#userList thead tr th").length; i++) {
     32    aoColumns.push(null);
     33  }
     34
     35  var oTable = jQuery('#userList').dataTable({
     36    "iDisplayLength": 10,
     37    "bDeferRender": true,
     38    "bProcessing": true,
     39    "bServerSide": true,
     40    "sAjaxSource": "admin/user_list_backend.php",
     41    "fnDrawCallback": function( oSettings ) {
     42      jQuery("#userList input[type=checkbox]").each(function() {
     43        var user_id = jQuery(this).data("user_id");
     44        jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
     45      });
     46    },
     47    "aoColumns": aoColumns
     48  });
     49
     50  /**
     51   * Selection management
     52   */
     53  function checkSelection() {
     54    if (selection.length > 0) {
     55      jQuery("#forbidAction").hide();
     56      jQuery("#permitAction").show();
     57
     58      jQuery("#applyOnDetails").text(
     59        sprintf(
     60          applyOnDetails_pattern,
     61          selection.length
     62        )
     63      );
     64
     65      if (selection.length == allUsers.length) {
     66        jQuery("#selectedMessage").text(
     67          sprintf(
     68            selectedMessage_all,
     69            allUsers.length
     70          )
     71        );
     72      }
     73      else {
     74        jQuery("#selectedMessage").text(
     75          sprintf(
     76            selectedMessage_pattern,
     77            selection.length,
     78            allUsers.length
     79          )
     80        );
     81      }
     82    }
     83    else {
     84      jQuery("#forbidAction").show();
     85      jQuery("#permitAction").hide();
     86
     87      jQuery("#selectedMessage").text(
     88        sprintf(
     89          selectedMessage_none,
     90          allUsers.length
     91        )
     92      );
     93    }
     94
     95    jQuery("#applyActionBlock .infos").hide();
     96  }
     97
     98  jQuery(document).on('change', '#userList input[type=checkbox]',  function() {
     99    var user_id = jQuery(this).data("user_id");
     100
     101    array_delete(selection, user_id);
     102
     103    if (jQuery(this).is(":checked")) {
     104      selection.push(user_id);
     105    }
     106
     107    checkSelection();
     108  });
     109
     110  jQuery("#selectAll").click(function () {
     111    selection = allUsers;
     112    jQuery("#userList input[type=checkbox]").prop('checked', true);
     113    checkSelection();
     114    return false;
     115  });
     116
     117  jQuery("#selectNone").click(function () {
     118    selection = [];
     119    jQuery("#userList input[type=checkbox]").prop('checked', false);
     120    checkSelection();
     121    return false;
     122  });
     123
     124  jQuery("#selectInvert").click(function () {
     125    var newSelection = [];
     126    for(var i in allUsers)
     127    {
     128      if (selection.indexOf(allUsers[i]) == -1) {
     129        newSelection.push(allUsers[i]);
     130      }
     131    }
     132    selection = newSelection;
     133
     134    jQuery("#userList input[type=checkbox]").each(function() {
     135      var user_id = jQuery(this).data("user_id");
     136      jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
     137    });
     138
     139    checkSelection();
     140    return false;
     141  });
     142
     143  /**
     144   * Action management
     145   */
     146  jQuery("[id^=action_]").hide();
     147 
     148  jQuery("select[name=selectAction]").change(function () {
     149    jQuery("#applyActionBlock .infos").hide();
     150
     151    jQuery("[id^=action_]").hide();
     152
     153    jQuery("#action_"+$(this).prop("value")).show();
     154 
     155    if (jQuery(this).val() != -1) {
     156      jQuery("#applyActionBlock").show();
     157    }
     158    else {
     159      jQuery("#applyActionBlock").hide();
     160    }
     161  });
     162
     163  jQuery("#permitAction input, #permitAction select").click(function() {
     164    jQuery("#applyActionBlock .infos").hide();
     165  });
     166
     167  jQuery("#applyAction").click(function() {
     168    var action = jQuery("select[name=selectAction]").prop("value");
     169    var method = null;
     170    var data = {
     171      user_id: selection
     172    };
     173
     174    switch (action) {
     175      case 'delete':
     176        if (!jQuery("input[name=confirm_deletion]").is(':checked')) {
     177          alert(missingConfirm);
     178          return false;
     179        }
     180        method = 'pwg.users.delete';
     181        break;
     182      case 'group_associate':
     183        method = 'pwg.groups.addUser';
     184        data.group_id = jQuery("select[name=associate]").prop("value");
     185        break;
     186      case 'group_dissociate':
     187        method = 'pwg.groups.deleteUser';
     188        data.group_id = jQuery("select[name=dissociate]").prop("value");
     189        break;
     190    }
     191
     192    jQuery.ajax({
     193      url: "ws.php?format=json&method="+method,
     194      type:"POST",
     195      data: data,
     196      beforeSend: function() {
     197        jQuery("#applyActionLoading").show();
     198      },
     199      success:function(data) {
     200        oTable.fnDraw();
     201        jQuery("#applyActionLoading").hide();
     202        jQuery("#applyActionBlock .infos").show();
     203
     204        if (action == 'delete') {
     205          var allUsers_new = [];
     206          for(var i in allUsers)
     207          {
     208            if (selection.indexOf(allUsers[i]) == -1) {
     209              allUsers_new.push(allUsers[i]);
     210            }
     211          }
     212          allUsers = allUsers_new;
     213          console.log('allUsers_new.length = '+allUsers_new.length);
     214          selection = [];
     215          checkSelection();
     216        }
     217      },
     218      error:function(XMLHttpRequest, textStatus, errorThrows) {
     219        jQuery("#applyActionLoading").hide();
     220      }
     221    });
     222
     223    return false;
     224  });
     225
     226});
     227{/literal}{/footer_script}
     228
     229{literal}
     230<style>
     231.dataTables_wrapper, .dataTables_info {clear:none;}
     232table.dataTable {clear:right;padding-top:10px;}
     233.bulkAction {margin-top:10px;}
     234.actionButtons {margin-left:0;}
     235#applyActionBlock .infos {background-image:none; padding:2px 5px; margin:0;border-radius:5px;}
     236</style>
     237{/literal}
     238
    1239<div class="titrePage">
    2240  <h2>{'User list'|@translate}</h2>
    3241</div>
    4242
    5 <form class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
     243<form style="display:none" class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
    6244  <fieldset>
    7245    <legend>{'Add a user'|@translate}</legend>
     
    19257</form>
    20258
    21 <form class="filter" method="get" name="filter" action="{$F_FILTER_ACTION}">
    22 <fieldset>
    23   <legend>{'Filter'|@translate}</legend>
    24   <input type="hidden" name="page" value="user_list">
    25 
    26   <label>{'Username'|@translate} <input type="text" name="username" value="{$F_USERNAME}"></label>
    27 
    28   <label>
    29   {'status'|@translate}
    30   {html_options name=status options=$status_options selected=$status_selected}
    31   </label>
    32 
    33   <label>
    34   {'Group'|@translate}
    35   {html_options name=group options=$group_options selected=$group_selected}
    36   </label>
    37 
    38   <label>
    39   {'Sort by'|@translate}
    40   {html_options name=order_by options=$order_options selected=$order_selected}
    41   </label>
    42 
    43   <label>
    44   {'Sort order'|@translate}
    45   {html_options name=direction options=$direction_options selected=$direction_selected}
    46   </label>
    47 
    48   <label>
    49   &nbsp;
    50   <input class="submit" type="submit" value="{'Submit'|@translate}">
    51   </label>
    52 
    53 </fieldset>
    54 
    55 </form>
    56 
    57259<form method="post" name="preferences" action="">
    58260
    59 {if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
    60 
    61 <table class="table2" width="97%">
     261<table id="userList">
    62262  <thead>
    63     <tr class="throw">
    64       <td>&nbsp;</td>
    65       <td>{'Username'|@translate}</td>
    66       <td>{'User status'|@translate}</td>
    67       <td>{'Email address'|@translate}</td>
    68       <td>{'Groups'|@translate}</td>
    69       <td>{'Properties'|@translate}</td>
    70       {if not empty($plugin_user_list_column_titles)}
    71       {foreach from=$plugin_user_list_column_titles item=title}
    72       <td>{$title}</td>
    73       {/foreach}
    74       {/if}
    75       <td>{'Actions'|@translate}</td>
     263    <tr>
     264      <th>id</th>
     265      <th>{'Username'|@translate}</th>
     266      <th>{'Status'|@translate}</th>
     267      <th>{'Email address'|@translate}</th>
    76268    </tr>
    77269  </thead>
    78 
    79   {foreach from=$users item=user name=users_loop}
    80   <tr class="{if $smarty.foreach.users_loop.index is odd}row1{else}row2{/if}">
    81     <td><input type="checkbox" name="selection[]" value="{$user.ID}" {$user.CHECKED} id="selection-{$user.ID}"></td>
    82     <td><label for="selection-{$user.ID}">{$user.USERNAME}</label></td>
    83     <td>{$user.STATUS}</td>
    84     <td>{$user.EMAIL}</td>
    85     <td>{$user.GROUPS}</td>
    86     <td>{$user.PROPERTIES}</td>
    87     {foreach from=$user.plugin_columns item=data}
    88     <td>{$data}</td>
    89     {/foreach}
    90     <td style="text-align:center;">
    91       <a href="{$user.U_PERM}"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/permissions.png" style="border:none" alt="{'Permissions'|@translate}" title="{'Permissions'|@translate}"></a>
    92       <a href="{$user.U_PROFILE}"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/edit_s.png" style="border:none" alt="{'Profile'|@translate}" title="{'Profile'|@translate}"></a>
    93       {foreach from=$user.plugin_actions item=data}
    94       {$data}
    95       {/foreach}
    96       </td>
    97   </tr>
    98   {/foreach}
    99270</table>
    100271
    101 {if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
    102 
    103 {* delete the selected users ? *}
    104 <fieldset>
    105   <legend>{'Deletions'|@translate}</legend>
    106   <label><input type="checkbox" name="confirm_deletion" value="1"> {'confirm'|@translate}</label>
    107   <input class="submit" type="submit" value="{'Delete selected users'|@translate}" name="delete">
    108 </fieldset>
    109 
    110 <fieldset>
    111   <legend>{'Status'|@translate}</legend>
    112 
    113   <table>
    114     <tr>
    115       <td>{'Status'|@translate}</td>
    116       <td>
    117         <label><input type="radio" name="status_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    118         <label><input type="radio" name="status_action" value="set" id="status_action_set"> {'set to'|@translate}</label>
    119         <select onchange="document.getElementById('status_action_set').checked = true;" name="status" size="1">
    120           {html_options options=$pref_status_options selected=$pref_status_selected}
    121         </select>
    122       </td>
    123     </tr>
    124   </table>
    125 </fieldset>
    126 
    127 {* form to set properties for many users at once *}
    128 <fieldset>
    129   <legend>{'Groups'|@translate}</legend>
    130 
    131 <table>
    132 
    133   <tr>
    134     <td>{'associate to group'|@translate}</td>
    135     <td>
     272<div style="clear:right"></div>
     273
     274<p class="checkActions">
     275  {'Select:'|@translate}
     276  <a href="#" id="selectAll">{'All'|@translate}</a>,
     277  <a href="#" id="selectNone">{'None'|@translate}</a>,
     278  <a href="#" id="selectInvert">{'Invert'|@translate}</a>
     279
     280  <span id="selectedMessage"></span>
     281</p>
     282
     283<fieldset id="action">
     284  <legend>{'Action'|@translate}</legend>
     285
     286  <div id="forbidAction"{if count($selection) != 0} style="display:none"{/if}>{'No user selected, no action possible.'|@translate}</div>
     287  <div id="permitAction"{if count($selection) == 0} style="display:none"{/if}>
     288
     289    <select name="selectAction">
     290      <option value="-1">{'Choose an action'|@translate}</option>
     291      <option disabled="disabled">------------------</option>
     292      <option value="delete" class="icon-trash">{'Delete selected users'|@translate}</option>
     293      <option value="status">{'Status'|@translate}</option>
     294      <option value="group_associate">{'associate to group'|translate}</option>
     295      <option value="group_dissociate">{'dissociate from group'|@translate}</option>
     296      <option value="enabled_high">{'High definition enabled'|@translate}</option>
     297      <option value="level">{'Privacy level'|@translate}</option>
     298      <option value="nb_image_page">{'Number of photos per page'|@translate}</option>
     299      <option value="theme">{'Interface theme'|@translate}</option>
     300      <option value="language">{'Language'|@translate}</option>
     301      <option value="recent_period">{'Recent period'|@translate}</option>
     302      <option value="expand">{'Expand all albums'|@translate}</option>
     303{if $ACTIVATE_COMMENTS}
     304      <option value="show_nb_comments">{'Show number of comments'|@translate}</option>
     305{/if}
     306      <option value="show_nb_hits">{'Show number of hits'|@translate}</option>
     307    </select>
     308
     309    {* delete *}
     310    <div id="action_delete" class="bulkAction">
     311      <p><label><input type="checkbox" name="confirm_deletion" value="1"> {'Are you sure?'|@translate}</label></p>
     312    </div>
     313
     314    {* status *}
     315    <div id="action_status" class="bulkAction">
     316      <select name="status">
     317        {html_options options=$pref_status_options selected=$pref_status_selected}
     318      </select>
     319    </div>
     320
     321    {* group_associate *}
     322    <div id="action_group_associate" class="bulkAction">
    136323      {html_options name=associate options=$association_options selected=$associate_selected}
    137     </td>
    138   </tr>
    139 
    140   <tr>
    141     <td>{'dissociate from group'|@translate}</td>
    142     <td>
     324    </div>
     325
     326    {* group_dissociate *}
     327    <div id="action_group_dissociate" class="bulkAction">
    143328      {html_options name=dissociate options=$association_options selected=$dissociate_selected}
    144     </td>
    145   </tr>
    146 
    147 </table>
    148 
    149 </fieldset>
    150 
    151 {* Properties *}
    152 <fieldset>
    153   <legend>{'Properties'|@translate}</legend>
    154 
    155   <table>
    156 
    157     <tr>
    158       <td>{'High definition enabled'|@translate}</td>
    159       <td>
    160         <label><input type="radio" name="enabled_high" value="leave" checked="checked"> {'leave'|@translate}</label>
    161         / {'set to'|@translate}
    162         <label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
    163         <label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
    164       </td>
    165     </tr>
    166 
    167     <tr>
    168       <td>{'Privacy level'|@translate}</td>
    169       <td>
    170         <label><input type="radio" name="level_action" value="leave" checked="checked">{'leave'|@translate}</label>
    171         <label><input type="radio" name="level_action" value="set" id="level_action_set">{'set to'|@translate}</label>
    172         <select onchange="document.getElementById('level_action_set').checked = true;" name="level" size="1">
    173           {html_options options=$level_options selected=$level_selected}
    174         </select>
    175       </td>
    176     </tr>
    177   </table>
    178 
    179 </fieldset>
    180 
    181 {* preference *}
    182 <fieldset>
    183   <legend>{'Preferences'|@translate}</legend>
    184 
    185 <table>
    186   <tr>
    187     <td>{'Number of photos per page'|@translate}</td>
    188     <td>
    189       <label><input type="radio" name="nb_image_page_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    190       <label><input type="radio" name="nb_image_page_action" value="set" id="nb_image_page_action_set"> {'set to'|@translate}</label>
    191       <input onmousedown="document.getElementById('nb_image_page_action_set').checked = true;"
    192              size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
    193     </td>
    194   </tr>
    195 
    196   <tr>
    197     <td>{'Interface theme'|@translate}</td>
    198     <td>
    199       <label><input type="radio" name="theme_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    200       <label><input type="radio" name="theme_action" value="set" id="theme_action_set"> {'set to'|@translate}</label>
    201       <select onchange="document.getElementById('theme_action_set').checked = true;" name="theme" size="1">
     329    </div>
     330
     331    {* enabled_high *}
     332    <div id="action_enabled_high" class="bulkAction">
     333      <label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
     334      <label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
     335    </div>
     336
     337    {* level *}
     338    <div id="action_level" class="bulkAction">
     339      <select name="level" size="1">
     340        {html_options options=$level_options selected=$level_selected}
     341      </select>
     342    </div>
     343
     344    {* nb_image_page *}
     345    <div id="action_nb_image_page" class="bulkAction">
     346      <input size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
     347    </div>
     348
     349    {* theme *}
     350    <div id="action_theme" class="bulkAction">
     351      <select name="theme" size="1">
    202352        {html_options options=$theme_options selected=$theme_selected}
    203353      </select>
    204     </td>
    205   </tr>
    206 
    207   <tr>
    208     <td>{'Language'|@translate}</td>
    209     <td>
    210       <label><input type="radio" name="language_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    211       <label><input type="radio" name="language_action" value="set" id="language_action_set"> {'set to'|@translate}</label>
    212       <select onchange="document.getElementById('language_action_set').checked = true;" name="language" size="1">
     354    </div>
     355
     356    {* language *}
     357    <div id="action_language" class="bulkAction">
     358      <select name="language" size="1">
    213359        {html_options options=$language_options selected=$language_selected}
    214360      </select>
    215     </td>
    216   </tr>
    217 
    218   <tr>
    219     <td>{'Recent period'|@translate}</td>
    220     <td>
    221       <label><input type="radio" name="recent_period_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    222       <label><input type="radio" name="recent_period_action" value="set" id="recent_period_action_set"> {'set to'|@translate}</label>
    223       <input onmousedown="document.getElementById('recent_period_action_set').checked = true;"
    224              type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
    225     </td>
    226   </tr>
    227 
    228   <tr>
    229     <td>{'Expand all albums'|@translate}</td>
    230     <td>
    231       <label><input type="radio" name="expand" value="leave" checked="checked"> {'leave'|@translate}</label>
    232       / {'set to'|@translate}
     361    </div>
     362
     363    {* recent_period *}
     364    <div id="action_recent_period" class="bulkAction">
     365      <input type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
     366    </div>
     367
     368    {* expand *}
     369    <div id="action_expand" class="bulkAction">
    233370      <label><input type="radio" name="expand" value="true">{'Yes'|@translate}</label>
    234371      <label><input type="radio" name="expand" value="false">{'No'|@translate}</label>
    235     </td>
    236   </tr>
    237 
    238 {if $ACTIVATE_COMMENTS}
    239   <tr>
    240     <td>{'Show number of comments'|@translate}</td>
    241     <td>
    242       <label><input type="radio" name="show_nb_comments" value="leave" checked="checked"> {'leave'|@translate}</label>
    243       / {'set to'|@translate}
     372    </div>
     373
     374    {* show_nb_comments *}
     375    <div id="action_show_nb_comments" class="bulkAction">
    244376      <label><input type="radio" name="show_nb_comments" value="true">{'Yes'|@translate}</label>
    245377      <label><input type="radio" name="show_nb_comments" value="false">{'No'|@translate}</label>
    246     </td>
    247   </tr>
    248 {/if}
    249 
    250   <tr>
    251     <td>{'Show number of hits'|@translate}</td>
    252     <td>
    253       <label><input type="radio" name="show_nb_hits" value="leave" checked="checked"> {'leave'|@translate}</label>
    254       / {'set to'|@translate}
     378    </div>
     379
     380    {* show_nb_hits *}
     381    <div id="action_show_nb_hits" class="bulkAction">
    255382      <label><input type="radio" name="show_nb_hits" value="true">{'Yes'|@translate}</label>
    256383      <label><input type="radio" name="show_nb_hits" value="false">{'No'|@translate}</label>
    257     </td>
    258   </tr>
    259 
    260 </table>
    261 
     384    </div>
     385
     386    <p id="applyActionBlock" style="display:none" class="actionButtons">
     387      <input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit"> <span id="applyOnDetails"></span>
     388      <span id="applyActionLoading" style="display:none"><img src="themes/default/images/ajax-loader-small.gif"></span>
     389      <span class="infos" style="display:none">&#x2714; Users modified</span>
     390    </p>
     391
     392  </div> {* #permitAction *}
    262393</fieldset>
    263394
    264 <p>
    265   {'target'|@translate}
    266   <label><input type="radio" name="target" value="all"> {'all'|@translate}</label>
    267   <label><input type="radio" name="target" value="selection" checked="checked"> {'selection'|@translate}</label>
    268 </p>
    269 
    270 <p>
    271   <input class="submit" type="submit" value="{'Submit'|@translate}" name="pref_submit">
    272   <input class="submit" type="reset" value="{'Reset'|@translate}" name="pref_reset">
    273 </p>
    274 
    275 </form>
    276 
    277 <script type="text/javascript">// <![CDATA[{literal}
    278 jQuery("form:last").submit( function() {
    279         if ( jQuery("input[name=target][value=selection]:checked", this).length > 0 )
    280         if ( jQuery("input[name='selection[]']:checked", this).length == 0)
    281         {
    282                 alert( {/literal}"{'Select at least one user'|@translate|escape:javascript}"{literal} );
    283                 return false;
    284         }
    285         return true;
    286 }
    287 );{/literal}
    288 // ]]>
    289 </script>
    290  
     395</form>
  • trunk/admin/user_list.php

    r25121 r25194  
    2727
    2828// +-----------------------------------------------------------------------+
    29 // |                              functions                                |
    30 // +-----------------------------------------------------------------------+
    31 
    32 /**
    33  * returns a list of users depending on page filters (in $_GET)
    34  *
    35  * Each user comes with his related informations : id, username, mail
    36  * address, list of groups.
    37  *
    38  * @return array
    39  */
    40 function get_filtered_user_list()
    41 {
    42   global $conf, $page;
    43 
    44   $users = array();
    45 
    46   // filter
    47   $filter = array();
    48 
    49   if (isset($_GET['username']) and !empty($_GET['username']))
    50   {
    51     $username = str_replace('*', '%', $_GET['username']);
    52     $filter['username'] = pwg_db_real_escape_string($username);
    53   }
    54 
    55   if (isset($_GET['group'])
    56       and -1 != $_GET['group']
    57       and is_numeric($_GET['group']))
    58   {
    59     $filter['group'] = $_GET['group'];
    60   }
    61 
    62   if (isset($_GET['status'])
    63       and in_array($_GET['status'], get_enums(USER_INFOS_TABLE, 'status')))
    64   {
    65     $filter['status'] = $_GET['status'];
    66   }
    67 
    68   // how to order the list?
    69   $order_by = 'id';
    70   if (isset($_GET['order_by'])
    71       and in_array($_GET['order_by'], array_keys($page['order_by_items'])))
    72   {
    73     $order_by = $_GET['order_by'];
    74   }
    75 
    76   $direction = 'ASC';
    77   if (isset($_GET['direction'])
    78       and in_array($_GET['direction'], array_keys($page['direction_items'])))
    79   {
    80     $direction = strtoupper($_GET['direction']);
    81   }
    82 
    83   // search users depending on filters and order
    84   $query = '
    85 SELECT DISTINCT u.'.$conf['user_fields']['id'].' AS id,
    86                 u.'.$conf['user_fields']['username'].' AS username,
    87                 u.'.$conf['user_fields']['email'].' AS email,
    88                 ui.status,
    89                 ui.enabled_high,
    90                 ui.level
    91   FROM '.USERS_TABLE.' AS u
    92     INNER JOIN '.USER_INFOS_TABLE.' AS ui
    93       ON u.'.$conf['user_fields']['id'].' = ui.user_id
    94     LEFT JOIN '.USER_GROUP_TABLE.' AS ug
    95       ON u.'.$conf['user_fields']['id'].' = ug.user_id
    96   WHERE u.'.$conf['user_fields']['id'].' > 0';
    97   if (isset($filter['username']))
    98   {
    99     $query.= '
    100   AND u.'.$conf['user_fields']['username'].' LIKE \''.$filter['username'].'\'';
    101   }
    102   if (isset($filter['group']))
    103   {
    104     $query.= '
    105     AND ug.group_id = '.$filter['group'];
    106   }
    107   if (isset($filter['status']))
    108   {
    109     $query.= '
    110     AND ui.status = \''.$filter['status']."'";
    111   }
    112   $query.= '
    113   ORDER BY '.$order_by.' '.$direction.'
    114 ;';
    115 
    116   $result = pwg_query($query);
    117   while ($row = pwg_db_fetch_assoc($result))
    118   {
    119     $user = $row;
    120     $user['groups'] = array();
    121 
    122     $users[] = $user;
    123   }
    124 
    125   // add group lists
    126   $user_ids = array();
    127   foreach ($users as $i => $user)
    128   {
    129     $user_ids[$i] = $user['id'];
    130   }
    131   $user_nums = array_flip($user_ids);
    132 
    133   if (count($user_ids) > 0)
    134   {
    135     $query = '
    136 SELECT user_id, group_id
    137   FROM '.USER_GROUP_TABLE.'
    138   WHERE user_id IN ('.implode(',', $user_ids).')
    139 ;';
    140     $result = pwg_query($query);
    141     while ($row = pwg_db_fetch_assoc($result))
    142     {
    143       $users[ $user_nums[ $row['user_id'] ] ]['groups'][] = $row['group_id'];
    144     }
    145   }
    146 
    147   return $users;
    148 }
    149 
    150 // +-----------------------------------------------------------------------+
    151 // |                           initialization                              |
    152 // +-----------------------------------------------------------------------+
    153 
    154 if (!defined('PHPWG_ROOT_PATH'))
    155 {
    156   die('Hacking attempt!');
    157 }
    158 
    159 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
    160 
    161 // +-----------------------------------------------------------------------+
    162 // | Check Access and exit when user status is not ok                      |
    163 // +-----------------------------------------------------------------------+
    164 check_status(ACCESS_ADMINISTRATOR);
    165 
    166 $page['order_by_items'] = array(
    167   'id' => l10n('registration date'),
    168   'username' => l10n('Username'),
    169   'level' => l10n('Privacy level'),
    170   'Language' => l10n('Language'),
    171   'email' => l10n('Email address'),
    172   );
    173 
    174 $page['direction_items'] = array(
    175   'asc' => l10n('ascending'),
    176   'desc' => l10n('descending')
    177   );
    178 
    179 // +-----------------------------------------------------------------------+
    180 // |                              add a user                               |
    181 // +-----------------------------------------------------------------------+
    182 
    183 // Check for config_default var - If True : Using double password type else single password type
    184 // This feature is discussed on Piwigo's english forum
    185 if ($conf['double_password_type_in_admin'] == true)
    186 {
    187   if (isset($_POST['submit_add']))
    188   {
    189     if(empty($_POST['password']))
    190     {
    191       $page['errors'][] = l10n('Password is missing. Please enter the password.');
    192     }
    193     else if(empty($_POST['password_conf']))
    194     {
    195       $page['errors'][] = l10n('Password confirmation is missing. Please confirm the chosen password.');
    196     }
    197     else if ($_POST['password'] != $_POST['password_conf'])
    198     {
    199       $page['errors'][] = l10n('The passwords do not match');
    200     }
    201     else
    202     {
    203       register_user($_POST['login'],
    204                     $_POST['password'],
    205                     $_POST['email'],
    206                     false,
    207                     $page['errors']);
    208 
    209       if (count($page['errors']) == 0)
    210       {
    211         $page['infos'][] = l10n('user "%s" added', $_POST['login']);
    212       }
    213     }
    214   }
    215 }
    216 else if ($conf['double_password_type_in_admin'] == false)
    217 {
    218   if (isset($_POST['submit_add']))
    219   {
    220     register_user($_POST['login'],
    221                   $_POST['password'],
    222                   $_POST['email'],
    223                   false,
    224                   $page['errors']);
    225 
    226     if (count($page['errors']) == 0)
    227     {
    228       $page['infos'][] = l10n('user "%s" added', stripslashes($_POST['login']));
    229     }
    230   }
    231 }
    232 
    233 // email notification
    234 if (
    235   isset($_POST['submit_add'])
    236   and count($page['errors']) == 0 
    237   and !empty($_POST['email'])
    238   and isset($_POST['send_password_by_mail'])
    239   )
    240 {
    241   include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
    242        
    243   $keyargs_content = array(
    244     get_l10n_args('Hello %s,', $_POST['login']),
    245     get_l10n_args('Thank you for registering at %s!', $conf['gallery_title']),
    246     get_l10n_args('', ''),
    247     get_l10n_args('Here are your connection settings', ''),
    248     get_l10n_args('Username: %s', $_POST['login']),
    249     get_l10n_args('Password: %s', $_POST['password']),
    250     get_l10n_args('Email: %s', $_POST['email']),
    251     get_l10n_args('', ''),
    252     get_l10n_args('If you think you\'ve received this email in error, please contact us at %s', get_webmaster_mail_address()),
    253     );
    254    
    255   pwg_mail(
    256     $_POST['email'],
    257     array(
    258       'subject' => '['.$conf['gallery_title'].'] '.l10n('Registration'),
    259       'content' => l10n_args($keyargs_content),
    260       'content_format' => 'text/plain',
    261       )
    262     );
    263 }
    264 
    265 // +-----------------------------------------------------------------------+
    266 // |                               user list                               |
    267 // +-----------------------------------------------------------------------+
    268 
    269 $page['filtered_users'] = get_filtered_user_list();
    270 
    271 // +-----------------------------------------------------------------------+
    272 // |                            selected users                             |
    273 // +-----------------------------------------------------------------------+
    274 
    275 if (isset($_POST['delete']) or isset($_POST['pref_submit']))
    276 {
    277   $collection = array();
    278 
    279   switch ($_POST['target'])
    280   {
    281     case 'all' :
    282     {
    283       foreach($page['filtered_users'] as $local_user)
    284       {
    285         $collection[] = $local_user['id'];
    286       }
    287       break;
    288     }
    289     case 'selection' :
    290     {
    291       if (isset($_POST['selection']))
    292       {
    293         $collection = $_POST['selection'];
    294       }
    295       break;
    296     }
    297   }
    298 
    299   if (count($collection) == 0)
    300   {
    301     $page['errors'][] = l10n('Select at least one user');
    302   }
    303 }
    304 
    305 // +-----------------------------------------------------------------------+
    306 // |                             delete users                              |
    307 // +-----------------------------------------------------------------------+
    308 if (isset($_POST['delete']) and count($collection) > 0)
    309 {
    310   if (in_array($conf['guest_id'], $collection))
    311   {
    312     $page['errors'][] = l10n('Guest cannot be deleted');
    313   }
    314   if (($conf['guest_id'] != $conf['default_user_id']) and
    315       in_array($conf['default_user_id'], $collection))
    316   {
    317     $page['errors'][] = l10n('Default user cannot be deleted');
    318   }
    319   if (in_array($conf['webmaster_id'], $collection))
    320   {
    321     $page['errors'][] = l10n('Webmaster cannot be deleted');
    322   }
    323   if (in_array($user['id'], $collection))
    324   {
    325     $page['errors'][] = l10n('You cannot delete your account');
    326   }
    327 
    328   if (count($page['errors']) == 0)
    329   {
    330     if (isset($_POST['confirm_deletion']) and 1 == $_POST['confirm_deletion'])
    331     {
    332       foreach ($collection as $user_id)
    333       {
    334         delete_user($user_id);
    335       }
    336      
    337       $page['infos'][] = l10n_dec(
    338         '%d user deleted', '%d users deleted',
    339         count($collection)
    340         );
    341      
    342       foreach ($page['filtered_users'] as $filter_key => $filter_user)
    343       {
    344         if (in_array($filter_user['id'], $collection))
    345         {
    346           unset($page['filtered_users'][$filter_key]);
    347         }
    348       }
    349     }
    350     else
    351     {
    352       $page['errors'][] = l10n('You need to confirm deletion');
    353     }
    354   }
    355 }
    356 
    357 // +-----------------------------------------------------------------------+
    358 // |                       preferences form submission                     |
    359 // +-----------------------------------------------------------------------+
    360 
    361 if (isset($_POST['pref_submit']) and count($collection) > 0)
    362 {
    363   if (-1 != $_POST['associate'])
    364   {
    365     $datas = array();
    366 
    367     $query = '
    368 SELECT user_id
    369   FROM '.USER_GROUP_TABLE.'
    370   WHERE group_id = '.$_POST['associate'].'
    371 ;';
    372     $associated = array_from_query($query, 'user_id');
    373 
    374     $associable = array_diff($collection, $associated);
    375 
    376     if (count($associable) > 0)
    377     {
    378       foreach ($associable as $item)
    379       {
    380         $datas[] = array(
    381           'group_id' => $_POST['associate'],
    382           'user_id' => $item
    383           );
    384       }
    385 
    386       mass_inserts(USER_GROUP_TABLE,
    387                    array('group_id', 'user_id'),
    388                    $datas);
    389     }
    390   }
    391 
    392   if (-1 != $_POST['dissociate'])
    393   {
    394     $query = '
    395 DELETE FROM '.USER_GROUP_TABLE.'
    396   WHERE group_id = '.$_POST['dissociate'].'
    397   AND user_id IN ('.implode(',', $collection).')
    398 ';
    399     pwg_query($query);
    400   }
    401 
    402   // properties to set for the collection (a user list)
    403   $datas = array();
    404   $dbfields = array('primary' => array('user_id'), 'update' => array());
    405 
    406   $formfields = array(
    407           'nb_image_page', 'theme', 'language',
    408           'recent_period', 'expand', 'show_nb_hits',
    409           'status', 'enabled_high', 'level'
    410           );
    411  
    412   $true_false_fields = array('expand', 'show_nb_hits', 'enabled_high');
    413  
    414   if ($conf['activate_comments'])
    415   {
    416     $formfields[] = 'show_nb_comments';
    417     $true_false_fields[] = 'show_nb_comments';
    418   }
    419 
    420   foreach ($formfields as $formfield)
    421   {
    422     // special for true/false fields
    423     if (in_array($formfield, $true_false_fields))
    424     {
    425       $test = $formfield;
    426     }
    427     else
    428     {
    429       $test = $formfield.'_action';
    430     }
    431 
    432     if ($_POST[$test] != 'leave')
    433     {
    434       $dbfields['update'][] = $formfield;
    435     }
    436   }
    437 
    438   // updating elements is useful only if needed...
    439   if (count($dbfields['update']) > 0)
    440   {
    441     $datas = array();
    442 
    443     foreach ($collection as $user_id)
    444     {
    445       $data = array();
    446       $data['user_id'] = $user_id;
    447 
    448       // TODO : verify if submited values are semanticaly correct
    449       foreach ($dbfields['update'] as $dbfield)
    450       {
    451         // if the action is 'unset', the key won't be in row and
    452         // mass_updates function will set this field to NULL
    453         if (in_array($dbfield, $true_false_fields)
    454             or 'set' == $_POST[$dbfield.'_action'])
    455         {
    456           $data[$dbfield] = $_POST[$dbfield];
    457         }
    458       }
    459 
    460       // if the status is getting greater or equal to "admin", then level
    461       // automatically switches to "admin" (8), unless the level is also
    462       // defined in the same batch action.
    463       if (isset($data['status']) and in_array($data['status'], array('webmaster', 'admin')))
    464       {
    465         if (!isset($data['level']))
    466         {
    467           $data['level'] = 8;
    468           if (!in_array('level', $dbfields['update']))
    469           {
    470             $dbfields['update'][] = 'level';
    471           }
    472         }
    473       }
    474 
    475       // special users checks
    476       if
    477         (
    478           ($conf['webmaster_id'] == $user_id) or
    479           ($conf['guest_id'] == $user_id) or
    480           ($conf['default_user_id'] == $user_id)
    481         )
    482       {
    483         // status must not be changed
    484         if (isset($data['status']))
    485         {
    486           if ($conf['webmaster_id'] == $user_id)
    487           {
    488             $data['status'] = 'webmaster';
    489           }
    490           else
    491           {
    492             $data['status'] = 'guest';
    493           }
    494         }
    495       }
    496 
    497       $datas[] = $data;
    498     }
    499 
    500     mass_updates(USER_INFOS_TABLE, $dbfields, $datas);
    501   }
    502 
    503   redirect(
    504     get_root_url().
    505     'admin.php'.
    506     get_query_string_diff(array(), false)
    507     );
    508 }
    509 
    510 // +-----------------------------------------------------------------------+
    51129// |                              groups list                              |
    51230// +-----------------------------------------------------------------------+
    51331
    514 $groups[-1] = '------------';
     32$groups = array();
    51533
    51634$query = '
     
    52745
    52846// +-----------------------------------------------------------------------+
    529 // |                             template init                             |
     47// | template                                                              |
    53048// +-----------------------------------------------------------------------+
    53149
    53250$template->set_filenames(array('user_list'=>'user_list.tpl'));
    53351
    534 $base_url = PHPWG_ROOT_PATH.'admin.php?page=user_list';
     52$query = '
     53SELECT
     54    DISTINCT u.'.$conf['user_fields']['id'].' AS id,
     55    u.'.$conf['user_fields']['username'].' AS username,
     56    u.'.$conf['user_fields']['email'].' AS email,
     57    ui.status,
     58    ui.enabled_high,
     59    ui.level
     60  FROM '.USERS_TABLE.' AS u
     61    INNER JOIN '.USER_INFOS_TABLE.' AS ui ON u.'.$conf['user_fields']['id'].' = ui.user_id
     62  WHERE u.'.$conf['user_fields']['id'].' > 0
     63;';
    53564
    536 if (isset($_GET['start']) and is_numeric($_GET['start']))
     65$result = pwg_query($query);
     66while ($row = pwg_db_fetch_assoc($result))
    53767{
    538   $start = $_GET['start'];
    539 }
    540 else
    541 {
    542   $start = 0;
     68  $users[] = $row;
     69  $user_ids[] = $row['id'];
    54370}
    54471
    54572$template->assign(
    54673  array(
    547     'U_HELP' => get_root_url().'admin/popuphelp.php?page=user_list',
     74    'users' => $users,
     75    'all_users' => join(',', $user_ids),
     76    )
     77  );
    54878
    549     'F_ADD_ACTION' => $base_url,
    550     'F_USERNAME' => @htmlentities($_GET['username'], ENT_COMPAT, 'UTF-8'),
    551     'F_FILTER_ACTION' => get_root_url().'admin.php',
    552    
    553     'ACTIVATE_COMMENTS' => $conf['activate_comments'],
    554     ));
     79// echo '<pre>'; print_r($users); echo '</pre>';
    55580
    556 // Display or Hide double password type
    557 $template->assign('Double_Password', $conf['double_password_type_in_admin'] );
     81$default_user = get_default_user_info(true);
    55882
    559 // Filter status options
    560 $status_options[-1] = '------------';
    561 foreach (get_enums(USER_INFOS_TABLE, 'status') as $status)
    562 {
    563   $status_options[$status] = l10n('user_status_'.$status);
    564 }
    565 $template->assign('status_options', $status_options);
    566 $template->assign('status_selected',
    567     isset($_GET['status']) ? $_GET['status'] : '');
    568 
    569 // Filter group options
    570 $template->assign('group_options', $groups);
    571 $template->assign('group_selected',
    572     isset($_GET['group']) ? $_GET['group'] : '');
    573 
    574 // Filter order options
    575 $template->assign('order_options', $page['order_by_items']);
    576 $template->assign('order_selected',
    577     isset($_GET['order_by']) ? $_GET['order_by'] : '');
    578 
    579 // Filter direction options
    580 $template->assign('direction_options', $page['direction_items']);
    581 $template->assign('direction_selected',
    582     isset($_GET['direction']) ? $_GET['direction'] : '');
    583 
    584 
    585 if (isset($_POST['pref_submit']))
    586 {
    587   $template->assign(
    588     array(
    589       'NB_IMAGE_PAGE' => $_POST['nb_image_page'],
    590       'RECENT_PERIOD' => $_POST['recent_period'],
    591       ));
    592 }
    593 else
    594 {
    595   $default_user = get_default_user_info(true);
    596   $template->assign(
    597     array(
    598       'NB_IMAGE_PAGE' => $default_user['nb_image_page'],
    599       'RECENT_PERIOD' => $default_user['recent_period'],
    600       ));
    601 }
    602 
    603 // Template Options
    604 $template->assign('theme_options', get_pwg_themes());
    605 $template->assign('theme_selected',
    606     isset($_POST['pref_submit']) ? $_POST['theme'] : get_default_theme());
    607 
    608 // Language options
    609 $template->assign('language_options', get_languages());
    610 $template->assign('language_selected',
    611     isset($_POST['pref_submit']) ? $_POST['language'] : get_default_language());
     83$template->assign(
     84  array(
     85    'NB_IMAGE_PAGE' => $default_user['nb_image_page'],
     86    'RECENT_PERIOD' => $default_user['recent_period'],
     87    'theme_options' => get_pwg_themes(),
     88    'theme_selected' => get_default_theme(),
     89    'language_options' => get_languages(),
     90    'language_selected' => get_default_language(),
     91    'association_options' => $groups,
     92    )
     93  );
    61294
    61395// Status options
     
    621103}
    622104$template->assign('pref_status_options', $pref_status_options);
    623 $template->assign('pref_status_selected',
    624     isset($_POST['pref_submit']) ? $_POST['status'] : 'normal');
    625 
    626 // associate and dissociate options
    627 $template->assign('association_options', $groups);
    628 $template->assign('associate_selected',
    629     isset($_POST['pref_submit']) ? $_POST['associate'] : '');
    630 $template->assign('dissociate_selected',
    631     isset($_POST['pref_submit']) ? $_POST['dissociate'] : '');
    632 
     105$template->assign('pref_status_selected', 'normal');
    633106
    634107// user level options
     
    638111}
    639112$template->assign('level_options', $level_options);
    640 $template->assign('level_selected',
    641     isset($_POST['pref_submit']) ? $_POST['level'] : $default_user['level']);
     113$template->assign('level_selected', $default_user['level']);
     114
    642115
    643116// +-----------------------------------------------------------------------+
    644 // |                            navigation bar                             |
    645 // +-----------------------------------------------------------------------+
    646 
    647 $url = PHPWG_ROOT_PATH.'admin.php'.get_query_string_diff(array('start'));
    648 
    649 $navbar = create_navigation_bar(
    650   $url,
    651   count($page['filtered_users']),
    652   $start,
    653   $conf['users_page']
    654   );
    655 
    656 $template->assign('navbar', $navbar);
    657 
    658 // +-----------------------------------------------------------------------+
    659 // |                               user list                               |
    660 // +-----------------------------------------------------------------------+
    661 
    662 $profile_url = get_root_url().'admin.php?page=profile&amp;user_id=';
    663 $perm_url = get_root_url().'admin.php?page=user_perm&amp;user_id=';
    664 
    665 $visible_user_list = array();
    666 foreach ($page['filtered_users'] as $num => $local_user)
    667 {
    668   // simulate LIMIT $start, $conf['users_page']
    669   if ($num < $start)
    670   {
    671     continue;
    672   }
    673   if ($num >= $start + $conf['users_page'])
    674   {
    675     break;
    676   }
    677 
    678   $visible_user_list[] = $local_user;
    679 }
    680 
    681 // allow plugins to fill template var plugin_user_list_column_titles and
    682 // plugin_columns/plugin_actions for each user in the list
    683 $visible_user_list = trigger_event('loc_visible_user_list', $visible_user_list);
    684 
    685 foreach ($visible_user_list as $local_user)
    686 {
    687   $groups_string = preg_replace(
    688     '/(\d+)/e',
    689     "\$groups['$1']",
    690     implode(
    691       ', ',
    692       $local_user['groups']
    693       )
    694     );
    695 
    696   if (isset($_POST['pref_submit'])
    697       and isset($_POST['selection'])
    698       and in_array($local_user['id'], $_POST['selection']))
    699   {
    700     $checked = 'checked="checked"';
    701   }
    702   else
    703   {
    704     $checked = '';
    705   }
    706 
    707   $properties = array();
    708   if ( $local_user['level'] != 0 )
    709   {
    710     $properties[] = l10n( sprintf('Level %d', $local_user['level']) );
    711   }
    712   $properties[] =
    713     (isset($local_user['enabled_high']) and ($local_user['enabled_high'] == 'true'))
    714         ? l10n('High definition') : l10n('');
    715 
    716   $template->append(
    717     'users',
    718     array(
    719       'ID' => $local_user['id'],
    720       'CHECKED' => $checked,
    721       'U_PROFILE' => $profile_url.$local_user['id'],
    722       'U_PERM' => $perm_url.$local_user['id'],
    723       'USERNAME' => stripslashes($local_user['username'])
    724         .($local_user['id'] == $conf['guest_id']
    725           ? '<br>['.l10n('guest').']' : '')
    726         .($local_user['id'] == $conf['default_user_id']
    727           ? '<br>['.l10n('default values').']' : ''),
    728       'STATUS' => l10n('user_status_'.$local_user['status']),
    729       'EMAIL' => get_email_address_as_display_text($local_user['email']),
    730       'GROUPS' => $groups_string,
    731       'PROPERTIES' => implode( ', ', $properties),
    732       'plugin_columns' => isset($local_user['plugin_columns']) ? $local_user['plugin_columns'] : array(),
    733       'plugin_actions' => isset($local_user['plugin_actions']) ? $local_user['plugin_actions'] : array(),
    734       )
    735     );
    736 }
    737 
    738 // +-----------------------------------------------------------------------+
    739 // |                           html code display                           |
     117// | html code display                                                     |
    740118// +-----------------------------------------------------------------------+
    741119
Note: See TracChangeset for help on using the changeset viewer.