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

git-svn-id: http://piwigo.org/svn/trunk@25194 68402e56-0260-453c-a942-63ccdbb3a9ee
This commit is contained in:
plegall
2013-10-28 16:25:46 +00:00
parent 7367858be8
commit 2fdcfdddfe
4 changed files with 585 additions and 894 deletions

View File

@@ -0,0 +1,50 @@
function array_delete(arr, item) {
var i = arr.indexOf(item);
if (i != -1) arr.splice(i, 1);
}
function sprintf() {
var i = 0, a, f = arguments[i++], o = [], m, p, c, x, s = '';
while (f) {
if (m = /^[^\x25]+/.exec(f)) {
o.push(m[0]);
}
else if (m = /^\x25{2}/.exec(f)) {
o.push('%');
}
else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) {
throw('Too few arguments.');
}
if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) {
throw('Expecting number but found ' + typeof(a));
}
switch (m[7]) {
case 'b': a = a.toString(2); break;
case 'c': a = String.fromCharCode(a); break;
case 'd': a = parseInt(a); break;
case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
case 'o': a = a.toString(8); break;
case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
case 'u': a = Math.abs(a); break;
case 'x': a = a.toString(16); break;
case 'X': a = a.toString(16).toUpperCase(); break;
}
a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a);
c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
x = m[5] - String(a).length - s.length;
p = m[5] ? str_repeat(c, x) : '';
o.push(s + (m[4] ? a + p : p + a));
}
else {
throw('Huh ?!');
}
f = f.substring(m[0].length);
}
return o.join('');
}

View File

@@ -1,8 +1,246 @@
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
{combine_script id='jquery.dataTables' load='footer' path='themes/default/js/plugins/jquery.dataTables.js'}
{combine_css path="themes/default/js/plugins/datatables/css/jquery.dataTables.css"}
{footer_script}
var selectedMessage_pattern = "{'%d of %d photos selected'|@translate}";
var selectedMessage_none = "{'No photo selected, %d photos in current set'|@translate}";
var selectedMessage_all = "{'All %d photos are selected'|@translate}";
var applyOnDetails_pattern = "{'on the %d selected users'|@translate}";
var missingConfirm = "{'You need to confirm deletion'|translate}";
var allUsers = [{$all_users}];
var selection = [{$selection}];
{/footer_script}
{footer_script}{literal}
jQuery(document).ready(function() {
/* first column must be prefixed with the open/close icon */
var aoColumns = [
{
'bVisible':false
},
{
"mRender": function(data, type, full) {
return '<label><input type="checkbox" data-user_id="'+full[0]+'"> '+data+'</label>';
}
}
];
for (i=2; i<jQuery("#userList thead tr th").length; i++) {
aoColumns.push(null);
}
var oTable = jQuery('#userList').dataTable({
"iDisplayLength": 10,
"bDeferRender": true,
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "admin/user_list_backend.php",
"fnDrawCallback": function( oSettings ) {
jQuery("#userList input[type=checkbox]").each(function() {
var user_id = jQuery(this).data("user_id");
jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
});
},
"aoColumns": aoColumns
});
/**
* Selection management
*/
function checkSelection() {
if (selection.length > 0) {
jQuery("#forbidAction").hide();
jQuery("#permitAction").show();
jQuery("#applyOnDetails").text(
sprintf(
applyOnDetails_pattern,
selection.length
)
);
if (selection.length == allUsers.length) {
jQuery("#selectedMessage").text(
sprintf(
selectedMessage_all,
allUsers.length
)
);
}
else {
jQuery("#selectedMessage").text(
sprintf(
selectedMessage_pattern,
selection.length,
allUsers.length
)
);
}
}
else {
jQuery("#forbidAction").show();
jQuery("#permitAction").hide();
jQuery("#selectedMessage").text(
sprintf(
selectedMessage_none,
allUsers.length
)
);
}
jQuery("#applyActionBlock .infos").hide();
}
jQuery(document).on('change', '#userList input[type=checkbox]', function() {
var user_id = jQuery(this).data("user_id");
array_delete(selection, user_id);
if (jQuery(this).is(":checked")) {
selection.push(user_id);
}
checkSelection();
});
jQuery("#selectAll").click(function () {
selection = allUsers;
jQuery("#userList input[type=checkbox]").prop('checked', true);
checkSelection();
return false;
});
jQuery("#selectNone").click(function () {
selection = [];
jQuery("#userList input[type=checkbox]").prop('checked', false);
checkSelection();
return false;
});
jQuery("#selectInvert").click(function () {
var newSelection = [];
for(var i in allUsers)
{
if (selection.indexOf(allUsers[i]) == -1) {
newSelection.push(allUsers[i]);
}
}
selection = newSelection;
jQuery("#userList input[type=checkbox]").each(function() {
var user_id = jQuery(this).data("user_id");
jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
});
checkSelection();
return false;
});
/**
* Action management
*/
jQuery("[id^=action_]").hide();
jQuery("select[name=selectAction]").change(function () {
jQuery("#applyActionBlock .infos").hide();
jQuery("[id^=action_]").hide();
jQuery("#action_"+$(this).prop("value")).show();
if (jQuery(this).val() != -1) {
jQuery("#applyActionBlock").show();
}
else {
jQuery("#applyActionBlock").hide();
}
});
jQuery("#permitAction input, #permitAction select").click(function() {
jQuery("#applyActionBlock .infos").hide();
});
jQuery("#applyAction").click(function() {
var action = jQuery("select[name=selectAction]").prop("value");
var method = null;
var data = {
user_id: selection
};
switch (action) {
case 'delete':
if (!jQuery("input[name=confirm_deletion]").is(':checked')) {
alert(missingConfirm);
return false;
}
method = 'pwg.users.delete';
break;
case 'group_associate':
method = 'pwg.groups.addUser';
data.group_id = jQuery("select[name=associate]").prop("value");
break;
case 'group_dissociate':
method = 'pwg.groups.deleteUser';
data.group_id = jQuery("select[name=dissociate]").prop("value");
break;
}
jQuery.ajax({
url: "ws.php?format=json&method="+method,
type:"POST",
data: data,
beforeSend: function() {
jQuery("#applyActionLoading").show();
},
success:function(data) {
oTable.fnDraw();
jQuery("#applyActionLoading").hide();
jQuery("#applyActionBlock .infos").show();
if (action == 'delete') {
var allUsers_new = [];
for(var i in allUsers)
{
if (selection.indexOf(allUsers[i]) == -1) {
allUsers_new.push(allUsers[i]);
}
}
allUsers = allUsers_new;
console.log('allUsers_new.length = '+allUsers_new.length);
selection = [];
checkSelection();
}
},
error:function(XMLHttpRequest, textStatus, errorThrows) {
jQuery("#applyActionLoading").hide();
}
});
return false;
});
});
{/literal}{/footer_script}
{literal}
<style>
.dataTables_wrapper, .dataTables_info {clear:none;}
table.dataTable {clear:right;padding-top:10px;}
.bulkAction {margin-top:10px;}
.actionButtons {margin-left:0;}
#applyActionBlock .infos {background-image:none; padding:2px 5px; margin:0;border-radius:5px;}
</style>
{/literal}
<div class="titrePage">
<h2>{'User list'|@translate}</h2>
</div>
<form class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
<form style="display:none" class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
<fieldset>
<legend>{'Add a user'|@translate}</legend>
<label>{'Username'|@translate} <input type="text" name="login" maxlength="50" size="20"></label>
@@ -18,273 +256,140 @@
</fieldset>
</form>
<form class="filter" method="get" name="filter" action="{$F_FILTER_ACTION}">
<fieldset>
<legend>{'Filter'|@translate}</legend>
<input type="hidden" name="page" value="user_list">
<label>{'Username'|@translate} <input type="text" name="username" value="{$F_USERNAME}"></label>
<label>
{'status'|@translate}
{html_options name=status options=$status_options selected=$status_selected}
</label>
<label>
{'Group'|@translate}
{html_options name=group options=$group_options selected=$group_selected}
</label>
<label>
{'Sort by'|@translate}
{html_options name=order_by options=$order_options selected=$order_selected}
</label>
<label>
{'Sort order'|@translate}
{html_options name=direction options=$direction_options selected=$direction_selected}
</label>
<label>
&nbsp;
<input class="submit" type="submit" value="{'Submit'|@translate}">
</label>
</fieldset>
</form>
<form method="post" name="preferences" action="">
{if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
<table class="table2" width="97%">
<table id="userList">
<thead>
<tr class="throw">
<td>&nbsp;</td>
<td>{'Username'|@translate}</td>
<td>{'User status'|@translate}</td>
<td>{'Email address'|@translate}</td>
<td>{'Groups'|@translate}</td>
<td>{'Properties'|@translate}</td>
{if not empty($plugin_user_list_column_titles)}
{foreach from=$plugin_user_list_column_titles item=title}
<td>{$title}</td>
{/foreach}
{/if}
<td>{'Actions'|@translate}</td>
<tr>
<th>id</th>
<th>{'Username'|@translate}</th>
<th>{'Status'|@translate}</th>
<th>{'Email address'|@translate}</th>
</tr>
</thead>
{foreach from=$users item=user name=users_loop}
<tr class="{if $smarty.foreach.users_loop.index is odd}row1{else}row2{/if}">
<td><input type="checkbox" name="selection[]" value="{$user.ID}" {$user.CHECKED} id="selection-{$user.ID}"></td>
<td><label for="selection-{$user.ID}">{$user.USERNAME}</label></td>
<td>{$user.STATUS}</td>
<td>{$user.EMAIL}</td>
<td>{$user.GROUPS}</td>
<td>{$user.PROPERTIES}</td>
{foreach from=$user.plugin_columns item=data}
<td>{$data}</td>
{/foreach}
<td style="text-align:center;">
<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>
<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>
{foreach from=$user.plugin_actions item=data}
{$data}
{/foreach}
</td>
</tr>
{/foreach}
</table>
{if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
<div style="clear:right"></div>
{* delete the selected users ? *}
<fieldset>
<legend>{'Deletions'|@translate}</legend>
<label><input type="checkbox" name="confirm_deletion" value="1"> {'confirm'|@translate}</label>
<input class="submit" type="submit" value="{'Delete selected users'|@translate}" name="delete">
</fieldset>
<p class="checkActions">
{'Select:'|@translate}
<a href="#" id="selectAll">{'All'|@translate}</a>,
<a href="#" id="selectNone">{'None'|@translate}</a>,
<a href="#" id="selectInvert">{'Invert'|@translate}</a>
<fieldset>
<legend>{'Status'|@translate}</legend>
<span id="selectedMessage"></span>
</p>
<table>
<tr>
<td>{'Status'|@translate}</td>
<td>
<label><input type="radio" name="status_action" value="leave" checked="checked"> {'leave'|@translate}</label>
<label><input type="radio" name="status_action" value="set" id="status_action_set"> {'set to'|@translate}</label>
<select onchange="document.getElementById('status_action_set').checked = true;" name="status" size="1">
{html_options options=$pref_status_options selected=$pref_status_selected}
</select>
</td>
</tr>
</table>
</fieldset>
<fieldset id="action">
<legend>{'Action'|@translate}</legend>
{* form to set properties for many users at once *}
<fieldset>
<legend>{'Groups'|@translate}</legend>
<div id="forbidAction"{if count($selection) != 0} style="display:none"{/if}>{'No user selected, no action possible.'|@translate}</div>
<div id="permitAction"{if count($selection) == 0} style="display:none"{/if}>
<table>
<select name="selectAction">
<option value="-1">{'Choose an action'|@translate}</option>
<option disabled="disabled">------------------</option>
<option value="delete" class="icon-trash">{'Delete selected users'|@translate}</option>
<option value="status">{'Status'|@translate}</option>
<option value="group_associate">{'associate to group'|translate}</option>
<option value="group_dissociate">{'dissociate from group'|@translate}</option>
<option value="enabled_high">{'High definition enabled'|@translate}</option>
<option value="level">{'Privacy level'|@translate}</option>
<option value="nb_image_page">{'Number of photos per page'|@translate}</option>
<option value="theme">{'Interface theme'|@translate}</option>
<option value="language">{'Language'|@translate}</option>
<option value="recent_period">{'Recent period'|@translate}</option>
<option value="expand">{'Expand all albums'|@translate}</option>
{if $ACTIVATE_COMMENTS}
<option value="show_nb_comments">{'Show number of comments'|@translate}</option>
{/if}
<option value="show_nb_hits">{'Show number of hits'|@translate}</option>
</select>
<tr>
<td>{'associate to group'|@translate}</td>
<td>
{* delete *}
<div id="action_delete" class="bulkAction">
<p><label><input type="checkbox" name="confirm_deletion" value="1"> {'Are you sure?'|@translate}</label></p>
</div>
{* status *}
<div id="action_status" class="bulkAction">
<select name="status">
{html_options options=$pref_status_options selected=$pref_status_selected}
</select>
</div>
{* group_associate *}
<div id="action_group_associate" class="bulkAction">
{html_options name=associate options=$association_options selected=$associate_selected}
</td>
</tr>
</div>
<tr>
<td>{'dissociate from group'|@translate}</td>
<td>
{* group_dissociate *}
<div id="action_group_dissociate" class="bulkAction">
{html_options name=dissociate options=$association_options selected=$dissociate_selected}
</td>
</tr>
</div>
</table>
{* enabled_high *}
<div id="action_enabled_high" class="bulkAction">
<label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
<label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
</div>
</fieldset>
{* level *}
<div id="action_level" class="bulkAction">
<select name="level" size="1">
{html_options options=$level_options selected=$level_selected}
</select>
</div>
{* Properties *}
<fieldset>
<legend>{'Properties'|@translate}</legend>
{* nb_image_page *}
<div id="action_nb_image_page" class="bulkAction">
<input size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
</div>
<table>
<tr>
<td>{'High definition enabled'|@translate}</td>
<td>
<label><input type="radio" name="enabled_high" value="leave" checked="checked"> {'leave'|@translate}</label>
/ {'set to'|@translate}
<label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
<label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
</td>
</tr>
<tr>
<td>{'Privacy level'|@translate}</td>
<td>
<label><input type="radio" name="level_action" value="leave" checked="checked">{'leave'|@translate}</label>
<label><input type="radio" name="level_action" value="set" id="level_action_set">{'set to'|@translate}</label>
<select onchange="document.getElementById('level_action_set').checked = true;" name="level" size="1">
{html_options options=$level_options selected=$level_selected}
</select>
</td>
</tr>
</table>
</fieldset>
{* preference *}
<fieldset>
<legend>{'Preferences'|@translate}</legend>
<table>
<tr>
<td>{'Number of photos per page'|@translate}</td>
<td>
<label><input type="radio" name="nb_image_page_action" value="leave" checked="checked"> {'leave'|@translate}</label>
<label><input type="radio" name="nb_image_page_action" value="set" id="nb_image_page_action_set"> {'set to'|@translate}</label>
<input onmousedown="document.getElementById('nb_image_page_action_set').checked = true;"
size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
</td>
</tr>
<tr>
<td>{'Interface theme'|@translate}</td>
<td>
<label><input type="radio" name="theme_action" value="leave" checked="checked"> {'leave'|@translate}</label>
<label><input type="radio" name="theme_action" value="set" id="theme_action_set"> {'set to'|@translate}</label>
<select onchange="document.getElementById('theme_action_set').checked = true;" name="theme" size="1">
{* theme *}
<div id="action_theme" class="bulkAction">
<select name="theme" size="1">
{html_options options=$theme_options selected=$theme_selected}
</select>
</td>
</tr>
</div>
<tr>
<td>{'Language'|@translate}</td>
<td>
<label><input type="radio" name="language_action" value="leave" checked="checked"> {'leave'|@translate}</label>
<label><input type="radio" name="language_action" value="set" id="language_action_set"> {'set to'|@translate}</label>
<select onchange="document.getElementById('language_action_set').checked = true;" name="language" size="1">
{* language *}
<div id="action_language" class="bulkAction">
<select name="language" size="1">
{html_options options=$language_options selected=$language_selected}
</select>
</td>
</tr>
</div>
<tr>
<td>{'Recent period'|@translate}</td>
<td>
<label><input type="radio" name="recent_period_action" value="leave" checked="checked"> {'leave'|@translate}</label>
<label><input type="radio" name="recent_period_action" value="set" id="recent_period_action_set"> {'set to'|@translate}</label>
<input onmousedown="document.getElementById('recent_period_action_set').checked = true;"
type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
</td>
</tr>
{* recent_period *}
<div id="action_recent_period" class="bulkAction">
<input type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
</div>
<tr>
<td>{'Expand all albums'|@translate}</td>
<td>
<label><input type="radio" name="expand" value="leave" checked="checked"> {'leave'|@translate}</label>
/ {'set to'|@translate}
{* expand *}
<div id="action_expand" class="bulkAction">
<label><input type="radio" name="expand" value="true">{'Yes'|@translate}</label>
<label><input type="radio" name="expand" value="false">{'No'|@translate}</label>
</td>
</tr>
</div>
{if $ACTIVATE_COMMENTS}
<tr>
<td>{'Show number of comments'|@translate}</td>
<td>
<label><input type="radio" name="show_nb_comments" value="leave" checked="checked"> {'leave'|@translate}</label>
/ {'set to'|@translate}
{* show_nb_comments *}
<div id="action_show_nb_comments" class="bulkAction">
<label><input type="radio" name="show_nb_comments" value="true">{'Yes'|@translate}</label>
<label><input type="radio" name="show_nb_comments" value="false">{'No'|@translate}</label>
</td>
</tr>
{/if}
</div>
<tr>
<td>{'Show number of hits'|@translate}</td>
<td>
<label><input type="radio" name="show_nb_hits" value="leave" checked="checked"> {'leave'|@translate}</label>
/ {'set to'|@translate}
{* show_nb_hits *}
<div id="action_show_nb_hits" class="bulkAction">
<label><input type="radio" name="show_nb_hits" value="true">{'Yes'|@translate}</label>
<label><input type="radio" name="show_nb_hits" value="false">{'No'|@translate}</label>
</td>
</tr>
</div>
</table>
<p id="applyActionBlock" style="display:none" class="actionButtons">
<input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit"> <span id="applyOnDetails"></span>
<span id="applyActionLoading" style="display:none"><img src="themes/default/images/ajax-loader-small.gif"></span>
<span class="infos" style="display:none">&#x2714; Users modified</span>
</p>
</div> {* #permitAction *}
</fieldset>
<p>
{'target'|@translate}
<label><input type="radio" name="target" value="all"> {'all'|@translate}</label>
<label><input type="radio" name="target" value="selection" checked="checked"> {'selection'|@translate}</label>
</p>
<p>
<input class="submit" type="submit" value="{'Submit'|@translate}" name="pref_submit">
<input class="submit" type="reset" value="{'Reset'|@translate}" name="pref_reset">
</p>
</form>
<script type="text/javascript">// <![CDATA[{literal}
jQuery("form:last").submit( function() {
if ( jQuery("input[name=target][value=selection]:checked", this).length > 0 )
if ( jQuery("input[name='selection[]']:checked", this).length == 0)
{
alert( {/literal}"{'Select at least one user'|@translate|escape:javascript}"{literal} );
return false;
}
return true;
}
);{/literal}
// ]]>
</script>
</form>

View File

@@ -25,493 +25,11 @@
* Add users and manage users list
*/
// +-----------------------------------------------------------------------+
// | functions |
// +-----------------------------------------------------------------------+
/**
* returns a list of users depending on page filters (in $_GET)
*
* Each user comes with his related informations : id, username, mail
* address, list of groups.
*
* @return array
*/
function get_filtered_user_list()
{
global $conf, $page;
$users = array();
// filter
$filter = array();
if (isset($_GET['username']) and !empty($_GET['username']))
{
$username = str_replace('*', '%', $_GET['username']);
$filter['username'] = pwg_db_real_escape_string($username);
}
if (isset($_GET['group'])
and -1 != $_GET['group']
and is_numeric($_GET['group']))
{
$filter['group'] = $_GET['group'];
}
if (isset($_GET['status'])
and in_array($_GET['status'], get_enums(USER_INFOS_TABLE, 'status')))
{
$filter['status'] = $_GET['status'];
}
// how to order the list?
$order_by = 'id';
if (isset($_GET['order_by'])
and in_array($_GET['order_by'], array_keys($page['order_by_items'])))
{
$order_by = $_GET['order_by'];
}
$direction = 'ASC';
if (isset($_GET['direction'])
and in_array($_GET['direction'], array_keys($page['direction_items'])))
{
$direction = strtoupper($_GET['direction']);
}
// search users depending on filters and order
$query = '
SELECT DISTINCT u.'.$conf['user_fields']['id'].' AS id,
u.'.$conf['user_fields']['username'].' AS username,
u.'.$conf['user_fields']['email'].' AS email,
ui.status,
ui.enabled_high,
ui.level
FROM '.USERS_TABLE.' AS u
INNER JOIN '.USER_INFOS_TABLE.' AS ui
ON u.'.$conf['user_fields']['id'].' = ui.user_id
LEFT JOIN '.USER_GROUP_TABLE.' AS ug
ON u.'.$conf['user_fields']['id'].' = ug.user_id
WHERE u.'.$conf['user_fields']['id'].' > 0';
if (isset($filter['username']))
{
$query.= '
AND u.'.$conf['user_fields']['username'].' LIKE \''.$filter['username'].'\'';
}
if (isset($filter['group']))
{
$query.= '
AND ug.group_id = '.$filter['group'];
}
if (isset($filter['status']))
{
$query.= '
AND ui.status = \''.$filter['status']."'";
}
$query.= '
ORDER BY '.$order_by.' '.$direction.'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$user = $row;
$user['groups'] = array();
$users[] = $user;
}
// add group lists
$user_ids = array();
foreach ($users as $i => $user)
{
$user_ids[$i] = $user['id'];
}
$user_nums = array_flip($user_ids);
if (count($user_ids) > 0)
{
$query = '
SELECT user_id, group_id
FROM '.USER_GROUP_TABLE.'
WHERE user_id IN ('.implode(',', $user_ids).')
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$users[ $user_nums[ $row['user_id'] ] ]['groups'][] = $row['group_id'];
}
}
return $users;
}
// +-----------------------------------------------------------------------+
// | initialization |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
$page['order_by_items'] = array(
'id' => l10n('registration date'),
'username' => l10n('Username'),
'level' => l10n('Privacy level'),
'Language' => l10n('Language'),
'email' => l10n('Email address'),
);
$page['direction_items'] = array(
'asc' => l10n('ascending'),
'desc' => l10n('descending')
);
// +-----------------------------------------------------------------------+
// | add a user |
// +-----------------------------------------------------------------------+
// Check for config_default var - If True : Using double password type else single password type
// This feature is discussed on Piwigo's english forum
if ($conf['double_password_type_in_admin'] == true)
{
if (isset($_POST['submit_add']))
{
if(empty($_POST['password']))
{
$page['errors'][] = l10n('Password is missing. Please enter the password.');
}
else if(empty($_POST['password_conf']))
{
$page['errors'][] = l10n('Password confirmation is missing. Please confirm the chosen password.');
}
else if ($_POST['password'] != $_POST['password_conf'])
{
$page['errors'][] = l10n('The passwords do not match');
}
else
{
register_user($_POST['login'],
$_POST['password'],
$_POST['email'],
false,
$page['errors']);
if (count($page['errors']) == 0)
{
$page['infos'][] = l10n('user "%s" added', $_POST['login']);
}
}
}
}
else if ($conf['double_password_type_in_admin'] == false)
{
if (isset($_POST['submit_add']))
{
register_user($_POST['login'],
$_POST['password'],
$_POST['email'],
false,
$page['errors']);
if (count($page['errors']) == 0)
{
$page['infos'][] = l10n('user "%s" added', stripslashes($_POST['login']));
}
}
}
// email notification
if (
isset($_POST['submit_add'])
and count($page['errors']) == 0
and !empty($_POST['email'])
and isset($_POST['send_password_by_mail'])
)
{
include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
$keyargs_content = array(
get_l10n_args('Hello %s,', $_POST['login']),
get_l10n_args('Thank you for registering at %s!', $conf['gallery_title']),
get_l10n_args('', ''),
get_l10n_args('Here are your connection settings', ''),
get_l10n_args('Username: %s', $_POST['login']),
get_l10n_args('Password: %s', $_POST['password']),
get_l10n_args('Email: %s', $_POST['email']),
get_l10n_args('', ''),
get_l10n_args('If you think you\'ve received this email in error, please contact us at %s', get_webmaster_mail_address()),
);
pwg_mail(
$_POST['email'],
array(
'subject' => '['.$conf['gallery_title'].'] '.l10n('Registration'),
'content' => l10n_args($keyargs_content),
'content_format' => 'text/plain',
)
);
}
// +-----------------------------------------------------------------------+
// | user list |
// +-----------------------------------------------------------------------+
$page['filtered_users'] = get_filtered_user_list();
// +-----------------------------------------------------------------------+
// | selected users |
// +-----------------------------------------------------------------------+
if (isset($_POST['delete']) or isset($_POST['pref_submit']))
{
$collection = array();
switch ($_POST['target'])
{
case 'all' :
{
foreach($page['filtered_users'] as $local_user)
{
$collection[] = $local_user['id'];
}
break;
}
case 'selection' :
{
if (isset($_POST['selection']))
{
$collection = $_POST['selection'];
}
break;
}
}
if (count($collection) == 0)
{
$page['errors'][] = l10n('Select at least one user');
}
}
// +-----------------------------------------------------------------------+
// | delete users |
// +-----------------------------------------------------------------------+
if (isset($_POST['delete']) and count($collection) > 0)
{
if (in_array($conf['guest_id'], $collection))
{
$page['errors'][] = l10n('Guest cannot be deleted');
}
if (($conf['guest_id'] != $conf['default_user_id']) and
in_array($conf['default_user_id'], $collection))
{
$page['errors'][] = l10n('Default user cannot be deleted');
}
if (in_array($conf['webmaster_id'], $collection))
{
$page['errors'][] = l10n('Webmaster cannot be deleted');
}
if (in_array($user['id'], $collection))
{
$page['errors'][] = l10n('You cannot delete your account');
}
if (count($page['errors']) == 0)
{
if (isset($_POST['confirm_deletion']) and 1 == $_POST['confirm_deletion'])
{
foreach ($collection as $user_id)
{
delete_user($user_id);
}
$page['infos'][] = l10n_dec(
'%d user deleted', '%d users deleted',
count($collection)
);
foreach ($page['filtered_users'] as $filter_key => $filter_user)
{
if (in_array($filter_user['id'], $collection))
{
unset($page['filtered_users'][$filter_key]);
}
}
}
else
{
$page['errors'][] = l10n('You need to confirm deletion');
}
}
}
// +-----------------------------------------------------------------------+
// | preferences form submission |
// +-----------------------------------------------------------------------+
if (isset($_POST['pref_submit']) and count($collection) > 0)
{
if (-1 != $_POST['associate'])
{
$datas = array();
$query = '
SELECT user_id
FROM '.USER_GROUP_TABLE.'
WHERE group_id = '.$_POST['associate'].'
;';
$associated = array_from_query($query, 'user_id');
$associable = array_diff($collection, $associated);
if (count($associable) > 0)
{
foreach ($associable as $item)
{
$datas[] = array(
'group_id' => $_POST['associate'],
'user_id' => $item
);
}
mass_inserts(USER_GROUP_TABLE,
array('group_id', 'user_id'),
$datas);
}
}
if (-1 != $_POST['dissociate'])
{
$query = '
DELETE FROM '.USER_GROUP_TABLE.'
WHERE group_id = '.$_POST['dissociate'].'
AND user_id IN ('.implode(',', $collection).')
';
pwg_query($query);
}
// properties to set for the collection (a user list)
$datas = array();
$dbfields = array('primary' => array('user_id'), 'update' => array());
$formfields = array(
'nb_image_page', 'theme', 'language',
'recent_period', 'expand', 'show_nb_hits',
'status', 'enabled_high', 'level'
);
$true_false_fields = array('expand', 'show_nb_hits', 'enabled_high');
if ($conf['activate_comments'])
{
$formfields[] = 'show_nb_comments';
$true_false_fields[] = 'show_nb_comments';
}
foreach ($formfields as $formfield)
{
// special for true/false fields
if (in_array($formfield, $true_false_fields))
{
$test = $formfield;
}
else
{
$test = $formfield.'_action';
}
if ($_POST[$test] != 'leave')
{
$dbfields['update'][] = $formfield;
}
}
// updating elements is useful only if needed...
if (count($dbfields['update']) > 0)
{
$datas = array();
foreach ($collection as $user_id)
{
$data = array();
$data['user_id'] = $user_id;
// TODO : verify if submited values are semanticaly correct
foreach ($dbfields['update'] as $dbfield)
{
// if the action is 'unset', the key won't be in row and
// mass_updates function will set this field to NULL
if (in_array($dbfield, $true_false_fields)
or 'set' == $_POST[$dbfield.'_action'])
{
$data[$dbfield] = $_POST[$dbfield];
}
}
// if the status is getting greater or equal to "admin", then level
// automatically switches to "admin" (8), unless the level is also
// defined in the same batch action.
if (isset($data['status']) and in_array($data['status'], array('webmaster', 'admin')))
{
if (!isset($data['level']))
{
$data['level'] = 8;
if (!in_array('level', $dbfields['update']))
{
$dbfields['update'][] = 'level';
}
}
}
// special users checks
if
(
($conf['webmaster_id'] == $user_id) or
($conf['guest_id'] == $user_id) or
($conf['default_user_id'] == $user_id)
)
{
// status must not be changed
if (isset($data['status']))
{
if ($conf['webmaster_id'] == $user_id)
{
$data['status'] = 'webmaster';
}
else
{
$data['status'] = 'guest';
}
}
}
$datas[] = $data;
}
mass_updates(USER_INFOS_TABLE, $dbfields, $datas);
}
redirect(
get_root_url().
'admin.php'.
get_query_string_diff(array(), false)
);
}
// +-----------------------------------------------------------------------+
// | groups list |
// +-----------------------------------------------------------------------+
$groups[-1] = '------------';
$groups = array();
$query = '
SELECT id, name
@@ -526,89 +44,53 @@ while ($row = pwg_db_fetch_assoc($result))
}
// +-----------------------------------------------------------------------+
// | template init |
// | template |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('user_list'=>'user_list.tpl'));
$base_url = PHPWG_ROOT_PATH.'admin.php?page=user_list';
$query = '
SELECT
DISTINCT u.'.$conf['user_fields']['id'].' AS id,
u.'.$conf['user_fields']['username'].' AS username,
u.'.$conf['user_fields']['email'].' AS email,
ui.status,
ui.enabled_high,
ui.level
FROM '.USERS_TABLE.' AS u
INNER JOIN '.USER_INFOS_TABLE.' AS ui ON u.'.$conf['user_fields']['id'].' = ui.user_id
WHERE u.'.$conf['user_fields']['id'].' > 0
;';
if (isset($_GET['start']) and is_numeric($_GET['start']))
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$start = $_GET['start'];
}
else
{
$start = 0;
$users[] = $row;
$user_ids[] = $row['id'];
}
$template->assign(
array(
'U_HELP' => get_root_url().'admin/popuphelp.php?page=user_list',
'users' => $users,
'all_users' => join(',', $user_ids),
)
);
'F_ADD_ACTION' => $base_url,
'F_USERNAME' => @htmlentities($_GET['username'], ENT_COMPAT, 'UTF-8'),
'F_FILTER_ACTION' => get_root_url().'admin.php',
'ACTIVATE_COMMENTS' => $conf['activate_comments'],
));
// echo '<pre>'; print_r($users); echo '</pre>';
// Display or Hide double password type
$template->assign('Double_Password', $conf['double_password_type_in_admin'] );
$default_user = get_default_user_info(true);
// Filter status options
$status_options[-1] = '------------';
foreach (get_enums(USER_INFOS_TABLE, 'status') as $status)
{
$status_options[$status] = l10n('user_status_'.$status);
}
$template->assign('status_options', $status_options);
$template->assign('status_selected',
isset($_GET['status']) ? $_GET['status'] : '');
// Filter group options
$template->assign('group_options', $groups);
$template->assign('group_selected',
isset($_GET['group']) ? $_GET['group'] : '');
// Filter order options
$template->assign('order_options', $page['order_by_items']);
$template->assign('order_selected',
isset($_GET['order_by']) ? $_GET['order_by'] : '');
// Filter direction options
$template->assign('direction_options', $page['direction_items']);
$template->assign('direction_selected',
isset($_GET['direction']) ? $_GET['direction'] : '');
if (isset($_POST['pref_submit']))
{
$template->assign(
array(
'NB_IMAGE_PAGE' => $_POST['nb_image_page'],
'RECENT_PERIOD' => $_POST['recent_period'],
));
}
else
{
$default_user = get_default_user_info(true);
$template->assign(
array(
'NB_IMAGE_PAGE' => $default_user['nb_image_page'],
'RECENT_PERIOD' => $default_user['recent_period'],
));
}
// Template Options
$template->assign('theme_options', get_pwg_themes());
$template->assign('theme_selected',
isset($_POST['pref_submit']) ? $_POST['theme'] : get_default_theme());
// Language options
$template->assign('language_options', get_languages());
$template->assign('language_selected',
isset($_POST['pref_submit']) ? $_POST['language'] : get_default_language());
$template->assign(
array(
'NB_IMAGE_PAGE' => $default_user['nb_image_page'],
'RECENT_PERIOD' => $default_user['recent_period'],
'theme_options' => get_pwg_themes(),
'theme_selected' => get_default_theme(),
'language_options' => get_languages(),
'language_selected' => get_default_language(),
'association_options' => $groups,
)
);
// Status options
foreach (get_enums(USER_INFOS_TABLE, 'status') as $status)
@@ -620,16 +102,7 @@ foreach (get_enums(USER_INFOS_TABLE, 'status') as $status)
}
}
$template->assign('pref_status_options', $pref_status_options);
$template->assign('pref_status_selected',
isset($_POST['pref_submit']) ? $_POST['status'] : 'normal');
// associate and dissociate options
$template->assign('association_options', $groups);
$template->assign('associate_selected',
isset($_POST['pref_submit']) ? $_POST['associate'] : '');
$template->assign('dissociate_selected',
isset($_POST['pref_submit']) ? $_POST['dissociate'] : '');
$template->assign('pref_status_selected', 'normal');
// user level options
foreach ($conf['available_permission_levels'] as $level)
@@ -637,107 +110,12 @@ foreach ($conf['available_permission_levels'] as $level)
$level_options[$level] = l10n(sprintf('Level %d', $level));
}
$template->assign('level_options', $level_options);
$template->assign('level_selected',
isset($_POST['pref_submit']) ? $_POST['level'] : $default_user['level']);
$template->assign('level_selected', $default_user['level']);
// +-----------------------------------------------------------------------+
// | navigation bar |
// +-----------------------------------------------------------------------+
$url = PHPWG_ROOT_PATH.'admin.php'.get_query_string_diff(array('start'));
$navbar = create_navigation_bar(
$url,
count($page['filtered_users']),
$start,
$conf['users_page']
);
$template->assign('navbar', $navbar);
// +-----------------------------------------------------------------------+
// | user list |
// +-----------------------------------------------------------------------+
$profile_url = get_root_url().'admin.php?page=profile&amp;user_id=';
$perm_url = get_root_url().'admin.php?page=user_perm&amp;user_id=';
$visible_user_list = array();
foreach ($page['filtered_users'] as $num => $local_user)
{
// simulate LIMIT $start, $conf['users_page']
if ($num < $start)
{
continue;
}
if ($num >= $start + $conf['users_page'])
{
break;
}
$visible_user_list[] = $local_user;
}
// allow plugins to fill template var plugin_user_list_column_titles and
// plugin_columns/plugin_actions for each user in the list
$visible_user_list = trigger_event('loc_visible_user_list', $visible_user_list);
foreach ($visible_user_list as $local_user)
{
$groups_string = preg_replace(
'/(\d+)/e',
"\$groups['$1']",
implode(
', ',
$local_user['groups']
)
);
if (isset($_POST['pref_submit'])
and isset($_POST['selection'])
and in_array($local_user['id'], $_POST['selection']))
{
$checked = 'checked="checked"';
}
else
{
$checked = '';
}
$properties = array();
if ( $local_user['level'] != 0 )
{
$properties[] = l10n( sprintf('Level %d', $local_user['level']) );
}
$properties[] =
(isset($local_user['enabled_high']) and ($local_user['enabled_high'] == 'true'))
? l10n('High definition') : l10n('');
$template->append(
'users',
array(
'ID' => $local_user['id'],
'CHECKED' => $checked,
'U_PROFILE' => $profile_url.$local_user['id'],
'U_PERM' => $perm_url.$local_user['id'],
'USERNAME' => stripslashes($local_user['username'])
.($local_user['id'] == $conf['guest_id']
? '<br>['.l10n('guest').']' : '')
.($local_user['id'] == $conf['default_user_id']
? '<br>['.l10n('default values').']' : ''),
'STATUS' => l10n('user_status_'.$local_user['status']),
'EMAIL' => get_email_address_as_display_text($local_user['email']),
'GROUPS' => $groups_string,
'PROPERTIES' => implode( ', ', $properties),
'plugin_columns' => isset($local_user['plugin_columns']) ? $local_user['plugin_columns'] : array(),
'plugin_actions' => isset($local_user['plugin_actions']) ? $local_user['plugin_actions'] : array(),
)
);
}
// +-----------------------------------------------------------------------+
// | html code display |
// | html code display |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'user_list');
?>
?>

158
admin/user_list_backend.php Normal file
View File

@@ -0,0 +1,158 @@
<?php
define('PHPWG_ROOT_PATH','../');
define('IN_ADMIN', true);
include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Easy set variables
*/
/* Array of database columns which should be read and sent back to DataTables. Use a space where
* you want to insert a non-database field (for example a counter or static image)
*/
$aColumns = array('id', 'username', 'status', 'mail_address');
/* Indexed column (used for fast and accurate table cardinality) */
$sIndexColumn = "id";
/* DB table to use */
$sTable = USERS_TABLE.' INNER JOIN '.USER_INFOS_TABLE.' AS ui ON id = ui.user_id';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP server-side, there is
* no need to edit below this line
*/
/*
* Paging
*/
$sLimit = "";
if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' )
{
$sLimit = "LIMIT ".pwg_db_real_escape_string( $_GET['iDisplayStart'] ).", ".
pwg_db_real_escape_string( $_GET['iDisplayLength'] );
}
/*
* Ordering
*/
if ( isset( $_GET['iSortCol_0'] ) )
{
$sOrder = "ORDER BY ";
for ( $i=0 ; $i<intval( $_GET['iSortingCols'] ) ; $i++ )
{
if ( $_GET[ 'bSortable_'.intval($_GET['iSortCol_'.$i]) ] == "true" )
{
$sOrder .= $aColumns[ intval( $_GET['iSortCol_'.$i] ) ]."
".pwg_db_real_escape_string( $_GET['sSortDir_'.$i] ) .", ";
}
}
$sOrder = substr_replace( $sOrder, "", -2 );
if ( $sOrder == "ORDER BY" )
{
$sOrder = "";
}
}
/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
* word by word on any field. It's possible to do here, but concerned about efficiency
* on very large tables, and MySQL's regex functionality is very limited
*/
$sWhere = "";
if ( $_GET['sSearch'] != "" )
{
$sWhere = "WHERE (";
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
$sWhere .= $aColumns[$i]." LIKE '%".pwg_db_real_escape_string( $_GET['sSearch'] )."%' OR ";
}
$sWhere = substr_replace( $sWhere, "", -3 );
$sWhere .= ')';
}
/* Individual column filtering */
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if ( $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' )
{
if ( $sWhere == "" )
{
$sWhere = "WHERE ";
}
else
{
$sWhere .= " AND ";
}
$sWhere .= $aColumns[$i]." LIKE '%".pwg_db_real_escape_string($_GET['sSearch_'.$i])."%' ";
}
}
/*
* SQL queries
* Get data to display
*/
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM $sTable
$sWhere
$sOrder
$sLimit
";
$rResult = pwg_query($sQuery);
/* Data set length after filtering */
$sQuery = "
SELECT FOUND_ROWS()
";
$rResultFilterTotal = pwg_query($sQuery);
$aResultFilterTotal = pwg_db_fetch_array($rResultFilterTotal);
$iFilteredTotal = $aResultFilterTotal[0];
/* Total data set length */
$sQuery = "
SELECT COUNT(".$sIndexColumn.")
FROM $sTable
";
$rResultTotal = pwg_query($sQuery);
$aResultTotal = pwg_db_fetch_array($rResultTotal);
$iTotal = $aResultTotal[0];
/*
* Output
*/
$output = array(
"sEcho" => intval($_GET['sEcho']),
"iTotalRecords" => $iTotal,
"iTotalDisplayRecords" => $iFilteredTotal,
"aaData" => array()
);
while ( $aRow = pwg_db_fetch_array( $rResult ) )
{
$row = array();
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if ( $aColumns[$i] == "version" )
{
/* Special output formatting for 'version' column */
$row[] = ($aRow[ $aColumns[$i] ]=="0") ? '-' : $aRow[ $aColumns[$i] ];
}
else if ( $aColumns[$i] != ' ' )
{
/* General output */
$row[] = $aRow[ $aColumns[$i] ];
}
}
$output['aaData'][] = $row;
}
echo json_encode( $output );
?>