Commit c0af3189 authored by Robert Lyon's avatar Robert Lyon

Update quota notify limit alerts users if they are now over threshold

Bug 1367539

When the admin adjusts the quota notify threshold limit the system
alerts any users that are now over limit that haven't been already
alerted on previous limit

Change-Id: I1d99b88336ef3be50dfa3b1453e9e351c701d739
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 5859101b
......@@ -43,11 +43,25 @@ $quotasform = pieform(array(
function groupquotasform_submit(Pieform $form, $values) {
global $SESSION;
$oldquota = get_field('group', 'quota', 'id', $values['groupid']);
$group = new StdClass;
$group->id = $values['groupid'];
$group->quota = $values['quota'];
update_record('group', $group);
if (!empty($values['quota']) && $values['quota'] != $oldquota) {
// We need to alert group admins that the group may now be over the threshold
$quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
$sqlwhere = " ((g.quotaused / g.quota) * 100) ";
if (is_postgres()) {
$sqlwhere = " ((CAST(g.quotaused AS float) / CAST(g.quota AS float)) * 100) ";
}
if ($groups = get_records_sql_assoc("SELECT g.id, g.name, g.quota, " . $sqlwhere . " AS quotausedpercent FROM {group} g WHERE " . $sqlwhere . " >= ? AND id = ?", array($quotanotifylimit, $values['groupid']))) {
require_once(get_config('docroot') . 'artefact/file/lib.php');
ArtefactTypeFile::notify_groups_threshold_exceeded($groups);
}
}
$SESSION->add_ok_msg(get_string('groupquotaupdated', 'admin'));
redirect(get_config('wwwroot').'admin/groups/groups.php');
}
......
......@@ -348,6 +348,26 @@ function edituser_site_submit(Pieform $form, $values) {
if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
$user->quota = $values['quota'];
// check if the user has gone over the quota notify limit
$quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
$quotanotifylimit = 100;
}
$user->quotausedpercent = $user->quotaused / $user->quota * 100;
$overlimit = false;
if ($quotanotifylimit <= $user->quotausedpercent) {
$overlimit = true;
}
$notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id);
if ($overlimit && '1' !== $notified) {
require_once(get_config('docroot') . 'artefact/file/lib.php');
ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false);
// no need to email admin as we can alert them right now
$SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user)));
}
else if ($notified && !$overlimit) {
set_account_preference($user->id, 'quota_exceeded_notified', false);
}
}
$unexpire = $user->expiry && strtotime($user->expiry) < time() && (empty($values['expiry']) || $values['expiry'] > time());
......
......@@ -768,6 +768,33 @@ function institution_submit(Pieform $form, $values) {
"UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)",
array($values['defaultquota'], $institution)
);
// get all the users from the institution and make sure that they are still below
// their quota threshold
if ($users = get_records_sql_array('SELECT * FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr AND ui.institution = ?', array($institution))) {
$quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
$quotanotifylimit = 100;
}
foreach ($users as $user) {
$user->quota = $values['defaultquota'];
// check if the user has gone over the quota notify limit
$user->quotausedpercent = $user->quotaused / $user->quota * 100;
$overlimit = false;
if ($quotanotifylimit <= $user->quotausedpercent) {
$overlimit = true;
}
$notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id);
if ($overlimit && '1' !== $notified) {
require_once(get_config('docroot') . 'artefact/file/lib.php');
ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false);
// no need to email admin as we can alert them right now
$SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user)));
}
else if ($notified && !$overlimit) {
set_account_preference($user->id, 'quota_exceeded_notified', false);
}
}
}
}
$newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota'];
}
......
......@@ -389,5 +389,16 @@ function xmldb_artefact_file_upgrade($oldversion=0) {
PluginArtefactFile::set_quota_triggers();
}
if ($oldversion < 2014061000) {
// Remove the not needed quota notify on update config trigger from previous update
if (is_postgres()) {
$sql = 'DROP TRIGGER IF EXISTS {unmark_quota_exeed_notified_on_update_setting_trigger} ON {artefact_config};';
}
else {
$sql = 'DROP TRIGGER IF EXISTS {unmark_quota_exeed_notified_on_update_setting_trigger};';
}
execute_sql($sql);
}
return $status;
}
......@@ -184,12 +184,15 @@ $string['quotanotifylimitoutofbounds'] = 'The notification limit is given in per
$string['usernotificationsubject'] = 'Your file storage is almost full';
$string['usernotificationmessage'] = 'You are using %s%% of your %s quota. You should get in touch with your site administrator about having your limit increased.';
$string['adm_notificationsubject'] = 'A user has nearly reached their file quota limit';
$string['adm_notificationmessage'] = 'User %s has reached %s%% percent of their %s quota. ';
$string['adm_notificationmessage'] = 'User %s has arrived at %s%% percent of their %s quota. ';
$string['adm_group_notificationsubject'] = 'A group that you administer has nearly reached their file quota limit';
$string['adm_group_notificationmessage'] = 'Group "%s" has arrived at %s%% percent of their %s quota. ';
$string['textlinktouser'] = 'Edit profile of %s';
$string['quotanotifylimittitle1'] = 'Quota notification threshold';
$string['quotanotifylimitdescr1'] = 'When a user\'s file upload quota is filled to this percentage, they (and the site administrators) will be sent a notification to let them know they are nearing their upload limit. They can then either delete files to free up space or contact their administrator to have their quota increased.';
$string['quotanotifyadmin1'] = 'Site administrator notification';
$string['quotanotifyadmindescr1'] = 'If checked, site administrators are notified when users reach the notification threshold.';
$string['useroverquotathreshold'] = 'User %s has arrived at %s%% percent of their %s quota. ';
// File types
$string['ai'] = 'Postscript document';
......
......@@ -112,18 +112,8 @@ class PluginArtefactFile extends PluginArtefact {
// Create triggers to reset the quota notification flag
if (is_postgres()) {
db_create_trigger(
'unmark_quota_exceed_upd_set',
'AFTER', 'UPDATE', 'artefact_config', "
IF NEW.plugin = 'file'
AND NEW.field = 'quotanotifylimit' THEN
UPDATE {usr_account_preference}
SET value = 0 FROM {usr}
WHERE {usr_account_preference}.field = 'quota_exceeded_notified'
AND {usr_account_preference}.usr = {usr}.id
AND CAST({usr}.quotaused AS float)/CAST({usr}.quota AS float) < CAST(NEW.value AS float)/100;
END IF;"
);
$sql = "DROP FUNCTION IF EXISTS {unmark_quota_exeed_upd_set}() CASCADE;";
execute_sql($sql);
db_create_trigger(
'unmark_quota_exceed_upd_usr_set',
......@@ -138,18 +128,9 @@ class PluginArtefactFile extends PluginArtefact {
);
}
else {
db_create_trigger(
'unmark_quota_exceed_upd_set',
'AFTER', 'UPDATE', 'artefact_config', "
IF NEW.plugin = 'file'
AND NEW.field = 'quotanotifylimit' THEN
UPDATE {usr_account_preference}, {usr}
SET {usr_account_preference}.value = 0
WHERE {usr_account_preference}.field = 'quota_exceeded_notified'
AND {usr_account_preference}.usr = {usr}.id
AND {usr}.quotaused/{usr}.quota < NEW.value/100;
END IF;"
);
$sql = "DROP TRIGGER IF EXISTS {unmark_quota_exceed_upd_set}";
execute_sql($sql);
db_create_trigger(
'unmark_quota_exceed_upd_usr_set',
'AFTER', 'UPDATE', 'usr', "
......@@ -409,19 +390,24 @@ class PluginArtefactFile extends PluginArtefact {
* @param type $eventdata
*/
public static function eventlistener_savedeleteartefact($event, $eventdata) {
$userid = null;
$userid = $group = null;
$owner = null;
$addsize = 0;
safe_require('notification', 'internal');
$quotatypes = array('file','audio','video','image');
$filesize = 0;
$quotatypes = array('file','audio','video','image','archive','profileicon');
if (('saveartefact' === $event) && in_array($eventdata->get('artefacttype'), $quotatypes)) {
$owner = array($eventdata->get('owner'));
$addsize = $eventdata->get('size');
$group = $eventdata->get('group');
$filesize = $eventdata->get('size');
}
else if (('deleteartefact' === $event) && ('file' === $eventdata->get('artefacttype'))) {
else if (('deleteartefact' === $event) && in_array($eventdata->get('artefacttype'), $quotatypes)) {
$owner = array($eventdata->get('owner'));
$group = $eventdata->get('group');
// we want to remove the size of the file from the quota check so we make it a negative integer
$filesize = intval('-' . $eventdata->get('size'));
}
else if ('updateuser' === $event) {
$userid = $eventdata;
......@@ -444,54 +430,43 @@ class PluginArtefactFile extends PluginArtefact {
$userid = reset($owner);
}
$quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
$quotanotifylimit = 100;
}
if ($userid !== null) {
$userdata = get_user($userid);
$quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
$quotanotifylimit = 100;
}
$quotausedpercent = ($userdata->quotaused + $addsize ) / $userdata->quota * 100;
$passed = false;
if ($quotanotifylimit <= $quotausedpercent) {
$passed = true;
$userdata->quotausedpercent = ($userdata->quotaused + $filesize ) / $userdata->quota * 100;
$overlimit = false;
if ($quotanotifylimit <= $userdata->quotausedpercent) {
$overlimit = true;
}
$notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $userid);
if ($passed && '1' !== $notified) {
// notify user
$data = array(
'subject' => get_string('usernotificationsubject', 'artefact.file'),
'message' => get_string('usernotificationmessage', 'artefact.file', ceil((int)$quotausedpercent), display_size($userdata->quota)),
'users' => array($userid),
'type' => 1,
);
$activity = new ActivityTypeMaharamessage($data);
$activity->notify_users();
// notify admin
if ($overlimit && '1' !== $notified) {
$notifyadmin = get_config_plugin('artefact', 'file', 'quotanotifyadmin');
if ($notifyadmin) {
$data = array(
'subject' => get_string('adm_notificationsubject', 'artefact.file'),
'message' => get_string('adm_notificationmessage', 'artefact.file', display_name($userdata) , ceil((int)$quotausedpercent), display_size($userdata->quota)),
'users' => get_column('usr', 'id', 'admin', 1),
'url' => 'admin/users/edit.php?id=' . $userid,
'urltext' => get_string('textlinktouser', 'artefact.file', display_name($userdata)),
'type' => 1,
);
$activity = new ActivityTypeMaharamessage($data);
$activity->notify_users();
}
set_account_preference($userid, 'quota_exceeded_notified', true);
ArtefactTypeFile::notify_users_threshold_exceeded(array($userdata), $notifyadmin);
}
else if ($notified && !$passed) {
else if ($notified && !$overlimit) {
set_account_preference($userid, 'quota_exceeded_notified', false);
}
}
else if ($group !== null) {
$groupdata = get_record('group', 'id', $group);
$groupdata->quotausedpercent = ($groupdata->quotaused + $filesize ) / $groupdata->quota * 100;
$overlimit = false;
if ($quotanotifylimit <= $groupdata->quotausedpercent) {
$overlimit = true;
}
if ($overlimit) {
require_once(get_config('docroot') . 'artefact/file/lib.php');
ArtefactTypeFile::notify_groups_threshold_exceeded(array($groupdata));
}
}
}
}
......@@ -1767,11 +1742,24 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
public static function save_config_options($form, $values) {
global $USER;
$updatingquota = false;
$oldquotalimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
if ($values['updateuserquotas'] && $values['defaultquota']) {
set_field('usr', 'quota', $values['defaultquota'], 'deleted', 0);
$updatingquota = true;
}
if ($values['updategroupquotas'] && $values['defaultgroupquota']) {
set_field('group', 'quota', $values['defaultgroupquota'], 'deleted', 0);
// We need to alert group admins that the group may now be over the threshold that wasn't before
$sqlwhere = " ((g.quotaused / g.quota) * 100) ";
if (is_postgres()) {
$sqlwhere = " ((CAST(g.quotaused AS float) / CAST(g.quota AS float)) * 100) ";
}
if ($groups = get_records_sql_assoc("SELECT g.id, g.name, g.quota, " . $sqlwhere . " AS quotausedpercent FROM {group} g WHERE " . $sqlwhere . " >= ?", array($values['quotanotifylimit']))) {
ArtefactTypeFile::notify_groups_threshold_exceeded($groups);
}
}
set_config_plugin('artefact', 'file', 'defaultquota', $values['defaultquota']);
set_config_plugin('artefact', 'file', 'defaultgroupquota', $values['defaultgroupquota']);
......@@ -1789,6 +1777,23 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
set_config_plugin('artefact', 'file', 'folderdownloadkeepzipfor', $values['folderdownloadkeepzipfor']);
set_config_plugin('artefact', 'file', 'quotanotifylimit', $values['quotanotifylimit']);
set_config_plugin('artefact', 'file', 'quotanotifyadmin', $values['quotanotifyadmin']);
if (($oldquotalimit != $values['quotanotifylimit']) || $updatingquota) {
// We need to alert anyone that may now be over the threshold that wasn't before
$sqlwhere = " ((u.quotaused / u.quota) * 100) ";
if (is_postgres()) {
$sqlwhere = " ((CAST(u.quotaused AS float) / CAST(u.quota AS float)) * 100) ";
}
if ($users = get_records_sql_assoc("SELECT u.id, u.quota, " . $sqlwhere . " AS quotausedpercent FROM {usr} u WHERE " . $sqlwhere . " >= ?", array($values['quotanotifylimit']))) {
$notifyadmin = get_config_plugin('artefact', 'file', 'quotanotifyadmin');
ArtefactTypeFile::notify_users_threshold_exceeded($users, $notifyadmin);
}
else if ($users = get_records_sql_assoc("SELECT * FROM {usr} u, {usr_account_preference} uap WHERE " . $sqlwhere . " < ? AND uap.usr = u.id AND uap.field = ? AND uap.value = ?", array($values['quotanotifylimit'], 'quota_exceeded_notified', '1'))) {
foreach ($users as $user) {
set_account_preference($user->id, 'quota_exceeded_notified', false);
}
}
}
$data = new StdClass;
$data->name = 'uploadcopyright';
$data->content = $values['customagreement'];
......@@ -1807,6 +1812,81 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
}
}
/**
* Notify users if their quota is above the quota threshold.
* And notify admins if required as well
*
* @param $users array of user objects - the $user object needs to include a quotausedpercent
* that is set by: (quotaused / quota) * 100
* @param $notifyadmins bool
*/
function notify_users_threshold_exceeded($users, $notifyadmins = false) {
// if we have just been given a $user object
if (is_object($users)) {
$users[] = $users;
}
require_once(get_config('docroot') . 'lib/activity.php');
safe_require('notification', 'internal');
foreach ($users as $user) {
// check that they have not already been notified about being over the limit
if (!get_record('usr_account_preference','usr', $user->id, 'field', 'quota_exceeded_notified', 'value', '1')) {
$data = array(
'subject' => get_string('usernotificationsubject', 'artefact.file'),
'message' => get_string('usernotificationmessage', 'artefact.file', ceil((int)$user->quotausedpercent), display_size($user->quota)),
'users' => array($user->id),
'type' => 1,
);
$activity = new ActivityTypeMaharamessage($data);
$activity->notify_users();
// notify admins
if ($notifyadmins) {
$data = array(
'subject' => get_string('adm_notificationsubject', 'artefact.file'),
'message' => get_string('adm_notificationmessage', 'artefact.file', display_name($user) , ceil((int)$user->quotausedpercent), display_size($user->quota)),
'users' => get_column('usr', 'id', 'admin', 1),
'url' => 'admin/users/edit.php?id=' . $user->id,
'urltext' => get_string('textlinktouser', 'artefact.file', display_name($user)),
'type' => 1,
);
$activity = new ActivityTypeMaharamessage($data);
$activity->notify_users();
}
set_account_preference($user->id, 'quota_exceeded_notified', true);
}
}
}
/**
* Notify group admins if the group quota is above the quota threshold.
*
* @param $groups array of group objects - the $group object needs to include a quotausedpercent
* that is set by: (quotaused / quota) * 100
*/
function notify_groups_threshold_exceeded($groups) {
// if we have just been given a $group object
if (is_object($groups)) {
$groups[] = $groups;
}
require_once(get_config('docroot') . 'lib/activity.php');
safe_require('notification', 'internal');
foreach ($groups as $group) {
// find the group admins and notify them - there should be at least 1 admin for a group
if ($admins = group_get_admin_ids(array($group->id))) {
$data = array(
'subject' => get_string('adm_group_notificationsubject', 'artefact.file'),
'message' => get_string('adm_group_notificationmessage', 'artefact.file', $group->name, ceil((int)$group->quotausedpercent), display_size($group->quota)),
'users' => $admins,
'url' => 'artefact/file/groupfiles.php?group=' . $group->id,
'urltext' => get_string('textlinktouser', 'artefact.file', $group->name),
'type' => 1,
);
$activity = new ActivityTypeMaharamessage($data);
$activity->notify_users();
}
}
}
public static function short_size($bytes, $abbr=false) {
if ($bytes < 1024) {
return $bytes <= 0 ? '0' : ($bytes . ($abbr ? 'b' : (' ' . get_string('bytes', 'artefact.file'))));
......@@ -1877,7 +1957,8 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
*/
public static function is_metaartefact() {
return true;
}}
}
}
class ArtefactTypeFolder extends ArtefactTypeFileBase {
......
......@@ -12,5 +12,6 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2014060900;
$config->release = '1.2.3';
$config->version = 2014061000;
$config->release = '1.2.4';
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment