Zombie users management: allow to disable old users #4652

skala
Laurent Opprecht 14 years ago
parent 34ea55889b
commit da0df39794
  1. 8
      main/inc/lib/autoload.class.php
  2. 168
      main/inc/lib/result_set.class.php
  3. 94
      main/inc/lib/zombie/zombie_manager.class.php
  4. 323
      main/inc/lib/zombie/zombie_report.class.php

@ -204,6 +204,7 @@ class Autoload
$result['Header'] = '/main/inc/lib/header.class.php'; $result['Header'] = '/main/inc/lib/header.class.php';
$result['HotSpot'] = '/main/exercice/hotspot.class.php'; $result['HotSpot'] = '/main/exercice/hotspot.class.php';
$result['HotSpotDelineation'] = '/main/exercice/hotspot.class.php'; $result['HotSpotDelineation'] = '/main/exercice/hotspot.class.php';
$result['Html'] = '/main/inc/lib/html.class.php';
$result['Html_Quickform_Rule_Date'] = '/main/inc/lib/pear/HTML/QuickForm/Rule/Date.php'; $result['Html_Quickform_Rule_Date'] = '/main/inc/lib/pear/HTML/QuickForm/Rule/Date.php';
$result['Image'] = '/main/inc/lib/image.lib.php'; $result['Image'] = '/main/inc/lib/image.lib.php';
$result['ImageWrapper'] = '/main/inc/lib/image.lib.php'; $result['ImageWrapper'] = '/main/inc/lib/image.lib.php';
@ -211,7 +212,6 @@ class Autoload
$result['Import'] = '/main/inc/lib/import.lib.php'; $result['Import'] = '/main/inc/lib/import.lib.php';
$result['IndexManager'] = '/main/inc/lib/userportal.lib.php'; $result['IndexManager'] = '/main/inc/lib/userportal.lib.php';
$result['IndexableChunk'] = '/main/inc/lib/search/IndexableChunk.class.php'; $result['IndexableChunk'] = '/main/inc/lib/search/IndexableChunk.class.php';
$result['ItemPropertyMissing'] = '/main/inc/lib/doctor/actions/item_property_missing.class.php';
$result['Javascript'] = '/main/inc/lib/javascript.class.php'; $result['Javascript'] = '/main/inc/lib/javascript.class.php';
$result['KeyAuth'] = '/main/auth/key/key_auth.class.php'; $result['KeyAuth'] = '/main/auth/key/key_auth.class.php';
$result['LearnpathLink'] = '/main/gradebook/lib/be/learnpathlink.class.php'; $result['LearnpathLink'] = '/main/gradebook/lib/be/learnpathlink.class.php';
@ -363,10 +363,8 @@ class Autoload
$result['UserTable'] = '/main/gradebook/lib/fe/usertable.class.php'; $result['UserTable'] = '/main/gradebook/lib/fe/usertable.class.php';
$result['Wiki'] = '/main/coursecopy/classes/wiki.class.php'; $result['Wiki'] = '/main/coursecopy/classes/wiki.class.php';
$result['XapianIndexer'] = '/main/inc/lib/search/xapian/XapianIndexer.class.php'; $result['XapianIndexer'] = '/main/inc/lib/search/xapian/XapianIndexer.class.php';
$result['ZombieManager'] = '/main/inc/lib/doctor/zombie/zombie_manager.class.php'; $result['ZombieManager'] = '/main/inc/lib/zombie/zombie_manager.class.php';
$result['ZombieQuery'] = '/main/inc/lib/doctor/zombie/zombie_query.class.php'; $result['ZombieReport'] = '/main/inc/lib/zombie/zombie_report.class.php';
$result['ZombieReport'] = '/main/inc/lib/doctor/zombie/zombie_report.class.php';
$result['Zombies'] = '/main/inc/lib/doctor/zombie/zombies.class.php';
$result['_Admin'] = '/main/auth/shibboleth/app/model/scaffold/admin.class.php'; $result['_Admin'] = '/main/auth/shibboleth/app/model/scaffold/admin.class.php';
$result['_AdminStore'] = '/main/auth/shibboleth/app/model/scaffold/admin.class.php'; $result['_AdminStore'] = '/main/auth/shibboleth/app/model/scaffold/admin.class.php';
$result['_IndexableChunk'] = '/main/inc/lib/search/IndexableChunk.class.php'; $result['_IndexableChunk'] = '/main/inc/lib/search/IndexableChunk.class.php';

@ -0,0 +1,168 @@
<?php
/**
* ResultSet
*
* @license see /license.txt
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
*/
class ResultSet implements Countable, Iterator
{
/**
*
* @param string $sql
* @return ResultSet
*/
static function create($sql)
{
return new self($sql);
}
protected $sql = '';
protected $handle = null;
protected $current = false;
protected $index = -1;
protected $count = false;
protected $limit_count = null;
protected $limit_offset = null;
protected $orderby_column = null;
protected $orderby_direction = null;
function __construct($sql, $limit_count = null, $limit_offset = null, $orderby_column = null, $orderby_direction = null)
{
$this->sql = $sql;
$this->limit_count = $limit_count;
$this->limit_offset = $limit_offset;
$this->orderby_column = $orderby_column;
$this->orderby_direction = $direction;
}
public function sql()
{
$sql = $this->sql;
$column = $this->orderby_column;
$direction = $this->orderby_direction;
$offset = $this->limit_offset;
$count = $this->limit_count;
if (is_null($column) && is_null($count) && is_null($offset)) {
return $sql;
}
if (strpos($sql, ' ORDER ') || strpos($sql, ' LIMIT ') || strpos($sql, ' OFFSET ')) {
$sql = "SELECT * FROM ($sql) AS dat ";
}else
{
$sql .= ' ';
}
if ($column) {
$sql .= "ORDER BY $column $direction ";
}
if ($count) {
$sql .= "LIMIT $count ";
}
if ($offset) {
$sql .= "OFFSET $offset";
}
return $sql;
}
protected function handle()
{
if (is_null($this->handle)) {
$this->handle = Database::query($this->sql());
}
return $this->handle;
}
public function count()
{
if ($this->count === false) {
$sql = $this->sql();
$sql = "SELECT COUNT(*) AS alpha FROM ($sql) AS dat ";
$rs = Database :: query($sql);
$data = Database::fetch_array($rs);
$count = $data ? $data['alpha'] : 0;
$this->count = (int) $count;
}
return $this->count;
}
/**
*
* @param int $count
* @param int $from
* @return ResultSet
*/
public function limit($count, $from = 0)
{
$result = clone($this);
$result->limit_offset = $from;
$result->limit_count = $count;
return $result;
}
/**
*
* @param int $column
* @param int $dir
* @return ResultSet
*/
public function orderby($column, $dir = 'ASC')
{
$result = clone($this);
$result->orderby_column = $column;
$result->orderby_direction = $dir;
return $result;
}
public function current()
{
return $this->current;
}
public function key()
{
return $this->index;
}
public function next()
{
$this->current = Database::fetch_assoc($this->handle());
$this->index++;
return $this->current;
}
public function rewind()
{
$this->handle = null;
$this->current = false;
$this->index = -1;
$this->next();
}
public function valid()
{
return !empty($this->current);
}
function __clone()
{
$this->reset();
}
function reset()
{
$this->handle = null;
$this->current = false;
$this->index = -1;
$this->count = false;
}
}

@ -0,0 +1,94 @@
<?php
/**
* ZombieQuery
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ZombieManager
{
static function last_year()
{
$today = time();
$day = date('j', $today);
$month = date('n', $today);
$year = date('Y', $today) - 1;
return mktime(0, 0, 0, $month, $day, $year);
}
/**
* Returns users whose last login is prior from $ceiling
*
* @param int|string $ceiling last login date
* @param bool $active_only if true returns only active users. Otherwise returns all users.
* @return ResultSet
*/
static function list_zombies($ceiling, $active_only = true)
{
$ceiling = is_numeric($ceiling) ? (int) $ceiling : strtotime($ceiling);
$ceiling = date('Y-m-d H:i:s', $ceiling);
$user_table = Database::get_main_table(TABLE_MAIN_USER);
$login_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT
user.user_id,
user.firstname,
user.lastname,
user.username,
user.auth_source,
user.email,
user.status,
user.registration_date,
user.active,
access.login_date';
global $_configuration;
if ($_configuration['multiple_access_urls']) {
$access_url_rel_user_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$current_url_id = api_get_current_access_url_id();
$sql .= " FROM $user_table as user, $login_table as access, $access_url_rel_user_table as url
WHERE
access.login_date = (SELECT MAX(a.login_date)
FROM $login_table as a
WHERE a.login_user_id = user.user_id
) AND
access.login_date <= '$ceiling' AND
user.user_id = access.login_user_id AND
url.login_user_id = user.user_id AND url.access_url_id=$current_url_id";
} else {
$sql .= " FROM $user_table as user, $login_table as access
WHERE
access.login_date = (SELECT MAX(a.login_date)
FROM $login_table as a
WHERE a.login_user_id = user.user_id
) AND
access.login_date <= '$ceiling' AND
user.user_id = access.login_user_id";
}
if($active_only)
{
$sql .= ' AND user.active = 1';
}
return ResultSet::create($sql);
}
static function deactivate_zombies($ceiling)
{
$zombies = self::list_zombies($ceiling);
$ids = array();
foreach($zombies as $zombie)
{
$ids[] = $zombie['user_id'];
}
UserManager::deactivate_users($ids);
}
}

@ -0,0 +1,323 @@
<?php
/**
* Description of zombie_report
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ZombieReport implements Countable
{
/**
* @return ZombieReport
*/
static function create($additional_parameters = array())
{
return new self($additional_parameters);
}
protected $additional_parameters = array();
function __construct($additional_parameters = array())
{
$this->additional_parameters = $additional_parameters;
}
function get_additional_parameters()
{
return $this->additional_parameters;
}
function get_parameters()
{
$result = array(
'name' => 'zombie_report_parameters',
'method' => 'GET',
'attributes' => array('class' => 'well form-horizontal form-search'),
'items' => array(
array(
'name' => 'ceiling',
'label' => get_lang('LastAccess'),
'type' => 'datepickerdate',
'default' => $this->get_ceiling(),
'rules' => array(
// array(
// 'type' => 'required',
// 'message' => get_lang('Required')
// ),
array(
'type' => 'date',
'message' => get_lang('Date')
)
)
),
array(
'name' => 'active_only',
'label' => get_lang('ActiveOnly'),
'type' => 'checkbox',
'default' => $this->get_active_only()
),
array(
'name' => 'submit_button',
'type' => 'style_submit_button',
'value' => get_lang('Search'),
'attributes' => array('class' => 'search')
)
)
);
$additional_parameters = $this->get_additional_parameters();
foreach ($additional_parameters as $key => $value) {
$result['items'][] = array(
'type' => 'hidden',
'name' => $key,
'value' => $value
);
}
return $result;
}
protected $parameters_form = null;
/**
*
* @return FormValidator
*/
function get_parameters_form()
{
$parameters = $this->get_parameters();
if (empty($parameters)) {
return null;
}
if (empty($this->parameters_form)) {
$this->parameters_form = FormValidator::create($parameters);
}
return $this->parameters_form;
}
function display_parameters($return = false)
{
$form = $this->get_parameters_form();
if (empty($form)) {
return '';
}
$result = $form->return_form();
if ($return) {
return $result;
} else {
echo $result;
}
}
function is_valid()
{
$form = $this->get_parameters_form();
if (empty($form)) {
return true;
}
return $form->isSubmitted() == false || $form->validate();
}
function get_ceiling()
{
$result = Request::get('ceiling');
$result = $result ? $result : ZombieManager::last_year();
$result = is_array($result) && count($result) == 1 ? reset($result) : $result;
$result = is_array($result) ? mktime(0, 0, 0, $result['F'], $result['d'], $result['Y']) : $result;
$result = is_numeric($result) ? (int) $result : $result;
$result = is_string($result) ? strtotime($result) : $result;
return $result;
}
function get_active_only()
{
$result = Request::get('active_only', false);
$result = $result === 'true' ? true : $result;
$result = $result === 'false' ? false : $result;
$result = (bool) $result;
return $result;
}
function get_action()
{
/**
* todo check token
*/
$check = Security::check_token('post');
Security::clear_token();
if (!$check) {
return 'display';
}
return Request::post('action', 'display');
}
function perform_action()
{
$ids = Request::post('id');
if (empty($ids)) {
return $ids;
}
$action = $this->get_action();
$f = array($this, 'action_' . $action);
if (is_callable($f)) {
return call_user_func($f, $ids);
}
return false;
}
function action_deactivate($ids)
{
return UserManager::deactivate_users($ids);
}
function action_activate($ids)
{
return UserManager::activate_users($ids);
}
function action_delete($ids)
{
return UserManager::delete_users($ids);
}
function count()
{
if (!$this->is_valid()) {
return 0;
}
$ceiling = $this->get_ceiling();
$active_only = $this->get_active_only();
$items = ZombieManager::list_zombies($ceiling, $active_only);
return count($items);
}
function get_data($from, $count, $column, $direction)
{
if (!$this->is_valid()) {
return array();
}
$ceiling = $this->get_ceiling();
$active_only = $this->get_active_only();
$items = ZombieManager::list_zombies($ceiling, $active_only)->limit($count, $from)->orderby($column, $direction);
$result = array();
foreach ($items as $item) {
$row = array();
$row[] = $item['user_id'];
$row[] = $item['code'];
$row[] = $item['firstname'];
$row[] = $item['lastname'];
$row[] = $item['username'];
$row[] = $item['email'];
$row[] = $item['status'];
$row[] = $item['auth_source'];
$row[] = api_format_date($item['registration_date'], DATE_FORMAT_SHORT);
$row[] = api_format_date($item['login_date'], DATE_FORMAT_SHORT);
$row[] = $item['active'];
$result[] = $row;
}
return $result;
}
function display_data($return = false)
{
$count = array($this, 'count');
$data = array($this, 'get_data');
$parameters = array();
$parameters['sec_token'] = Security::get_token();
$parameters['ceiling'] = $this->get_ceiling();
$parameters['active_only'] = $this->get_active_only() ? 'true' : 'false';
$additional_parameters = $this->get_additional_parameters();
$parameters = array_merge($additional_parameters, $parameters);
$table = new SortableTable('users', $count, $data, 1, 50);
$table->set_additional_parameters($parameters);
$col = 0;
$table->set_header($col++, '', false);
$table->set_header($col++, get_lang('Code'));
$table->set_header($col++, get_lang('FirstName'));
$table->set_header($col++, get_lang('LastName'));
$table->set_header($col++, get_lang('LoginName'));
$table->set_header($col++, get_lang('Email'));
$table->set_header($col++, get_lang('Profile'));
$table->set_header($col++, get_lang('Authentication'));
$table->set_header($col++, get_lang('Registered'));
$table->set_header($col++, get_lang('LastAccess'), false);
$table->set_header($col++, get_lang('Active'), false);
$table->set_column_filter(5, array($this, 'format_email'));
$table->set_column_filter(6, array($this, 'format_status'));
$table->set_column_filter(10, array($this, 'format_active'));
$table->set_form_actions(array(
'activate' => get_lang('Activate'),
'deactivate' => get_lang('Deactivate'),
'delete' => get_lang('Delete')
));
if ($return) {
return $table->return_table();
} else {
echo $table->return_table();
}
}
/**
* Table formatter for the active column.
*
* @param string $active
* @return string
*/
function format_active($active)
{
$active = ($active == '1');
if ($active) {
$image = 'accept';
$text = get_lang('Yes');
} else {
$image = 'error';
$text = get_lang('No');
}
$result = Display::return_icon($image . '.png', $text);
return $result;
}
function format_status($status)
{
$statusname = api_get_status_langvars();
return $statusname[$status];
}
function format_email($email)
{
return Display :: encrypted_mailto_link($email, $email);
}
function display($return = false)
{
$result = $this->display_parameters($return);
if ($this->perform_action()) {
if ($return) {
$result = Display::return_confirmation_message(get_lang('Done'));
} else {
Display::display_confirmation_message(get_lang('Done'));
}
}
$result = $this->display_data($return);
if ($return) {
return $result;
}
}
}
Loading…
Cancel
Save