diff --git a/classes/audience.php b/classes/audience.php new file mode 100644 index 0000000..c24bb1c --- /dev/null +++ b/classes/audience.php @@ -0,0 +1,141 @@ +. + +/** + * Class for audience rules. + * + * @package block_advnotifications + * @copyright 2016 onwards LearningWorks Ltd {@link https://learningworks.co.nz/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Zander Potgieter + */ + +namespace block_advnotifications; + +defined('MOODLE_INTERNAL') || die; + +class audience { + + public static function get_cohorts_for_autocomplete($notificationid) { + global $DB; + + $cohortssql = + 'SELECT c.id, c.name, nc.id as inuse + FROM {cohort} c + LEFT JOIN {block_advnotifications_coh} nc + ON c.id = nc.cohortid AND nc.notificationid = ?'; + + $cohorts = $DB->get_records_sql($cohortssql, [$notificationid]); + + $options = []; + $values = []; + + foreach ($cohorts as $c) { + $options[$c->id] = $c->name; + if (!is_null($c->inuse)) { + $values[] = $c->id; + } + } + return [$options, $values]; + } + + public static function get_roles_for_autocomplete($notificationid) { + global $DB; + + $roles = role_get_names(); + $selectedroles = $DB->get_fieldset_select( + 'block_advnotifications_roles', + 'roleid', + 'notificationid = ?', + [$notificationid] + ); + $options = []; + $values = []; + foreach ($roles as $r) { + $options[$r->id] = $r->localname; + if (in_array($r->id, $selectedroles)) { + $values[] = $r->id; + } + } + return [$options, $values]; + } + + public static function meets_profile_requirements($notificationid, $userid) { + global $DB, $USER; + if (!$rules = $DB->get_records('block_advnotifications_field', ['notificationid' => $notificationid])) { + return true; // There is no field restriction. + } + foreach ($rules as $r) { + if (strpos($r->userfield, 'profile_field_') === false) { + $currentvalue = $USER->{$r->userfield}; + } else { + $field = substr($r->userfield, 14); + $currentvalue = $USER->profile[$field]; + } + switch ($r->operator) { + case 'equals': + if ($currentvalue !== $r->fieldvalue) { + return false; + } + break; + case 'contains': + if (strpos($currentvalue, $r->fieldvalue) === false) { + return false; + } + break; + case 'beginwith': + if (strpos($currentvalue, $r->fieldvalue) !== 0) { + return false; + } + break; + } + } + return true; + } + + public static function meets_cohorts_requirements($notificationid, $userid) { + global $DB; + if (!$DB->record_exists('block_advnotifications_coh', ['notificationid' => $notificationid])) { + return true; // There is no cohort restriction. + } + $sql = + 'SELECT 1 + FROM {block_advnotifications_coh} anc + JOIN {cohort_members} cm + ON cm.cohortid = anc.cohortid AND + anc.notificationid = ? AND + cm.userid = ?'; + return $DB->record_exists_sql($sql, [$notificationid, $userid]); + } + + public static function meets_roles_requirements($notificationid, $userid, $blockid) { + global $DB; + if (!$roles = $DB->get_records('block_advnotifications_roles', ['notificationid' => $notificationid])) { + return true; // There is no role restriction. + } + if ($blockid) { + $context = \context_block::instance($blockid); + } else { + $context = \context_system::instance(); + } + foreach ($roles as $r) { + if (!user_has_role_assignment($userid, $r->roleid, $context->id)) { + return false; + } + } + return true; + } +} diff --git a/classes/notifications_table.php b/classes/notifications_table.php index 086a1ed..4f7929b 100644 --- a/classes/notifications_table.php +++ b/classes/notifications_table.php @@ -70,7 +70,8 @@ public function col_actions($values) { - '; + + '; } } -} \ No newline at end of file +} diff --git a/classes/output/form/audience.php b/classes/output/form/audience.php new file mode 100644 index 0000000..264ded7 --- /dev/null +++ b/classes/output/form/audience.php @@ -0,0 +1,128 @@ +. + +/** + * Reports form. + * + * @package block_advnotifications + * @copyright 2020 Daniel Neis Araujo + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace block_advnotifications\output\form; +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir . '/formslib.php'); + +use moodleform; + +/** + * Audience form class. + * + * @package block_advnotifications + * @copyright 2020 Daniel Neis Araujo + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class audience extends moodleform { + + public function definition() { + + $mform = $this->_form; + + $notificationid = $this->_customdata['notificationid']; + + list($options, $values) = \block_advnotifications\audience::get_cohorts_for_autocomplete($notificationid); + + $autocomplete = $mform->addElement( + 'autocomplete', + 'cohorts', + get_string('cohorts', 'cohort' ), + $options, + ['multiple' => true] + ); + $autocomplete->setSelected($values); + + list($options, $values) = \block_advnotifications\audience::get_roles_for_autocomplete($notificationid); + $autocomplete = $mform->addElement( + 'autocomplete', + 'roles', + get_string('roles'), + $options, + ['multiple' => true] + ); + $autocomplete->setSelected($values); + + $elements = [ + $mform->createElement('select', 'userfield', '', $this->filter_options()), + $mform->createElement('select', 'operator', '', $this->operator_options()), + $mform->createElement('text', 'fieldvalue', '', ['size' => 12]), + ]; + $filters = $mform->createElement('group', 'userfieldfilters', get_string('filter_userfield', 'block_advnotifications'), $elements); + $deletebutton = $mform->createElement('submit', 'deletefieldrule', 'X', [], false); + + $rules = [ + 'userfieldfilters[userfield]' => ['type' => PARAM_TEXT], + 'userfieldfilters[operator]' => ['type' => PARAM_TEXT], + 'userfieldfilters[fieldvalue]' => ['type' => PARAM_TEXT] + ]; + + $this->repeat_elements([$filters, $deletebutton], $this->_customdata['filterscount'], $rules, + 'filterscount', 'adduserfieldfilter', 1, get_string('adduserfieldfilter', 'block_advnotifications'), + true, 'deletefieldrule'); + + $this->add_action_buttons(); + } + + protected function filter_options() { + global $DB; + + $filters = [ + '' => get_string('choosedots'), + 'id' => 'id', + 'username' => get_string('username'), + 'idnumber' => get_string('idnumber'), + 'firstname' => get_string('firstname'), + 'lastname' => get_string('lastname'), + 'fullname' => get_string('fullnameuser'), + 'email' => get_string('email'), + 'phone1' => get_string('phone1'), + 'phone2' => get_string('phone2'), + 'institution' => get_string('institution'), + 'department' => get_string('department'), + 'address' => get_string('address'), + 'city' => get_string('city'), + 'timezone' => get_string('timezone'), + 'url' => get_string('webpage'), + ]; + + if ($profilefields = $DB->get_records('user_info_field', [], 'sortorder ASC')) { + foreach ($profilefields as $f) { + $filters['profile_field_' . $f->shortname] = format_string($f->name); + } + } + + return $filters; + } + + protected function operator_options() { + return [ + '' => get_string('choosedots'), + 'beginwith' => get_string('operator_beginwith', 'block_advnotifications'), + 'contains' => get_string('operator_contains', 'block_advnotifications'), + 'equals' => get_string('operator_equals', 'block_advnotifications') + ]; + } +} diff --git a/db/install.xml b/db/install.xml old mode 100644 new mode 100755 index 9637414..46987a1 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,8 @@ - + @@ -36,5 +39,42 @@
+ + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + +
-
\ No newline at end of file +
diff --git a/db/upgrade.php b/db/upgrade.php index 171043f..2b30b89 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -102,7 +102,68 @@ function xmldb_block_advnotifications_upgrade($oldversion) { upgrade_block_savepoint(true, 2021010616, 'advnotifications'); } + if ($oldversion < 2021092901) { + + // Define table block_advnotifications_coh to be created. + $table = new xmldb_table('block_advnotifications_coh'); + + // Adding fields to table block_advnotifications_coh. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('notificationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('cohortid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table block_advnotifications_coh. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $table->add_key('notificationid', XMLDB_KEY_FOREIGN, ['notificationid'], 'block_advnotifications', ['id']); + $table->add_key('cohortid', XMLDB_KEY_FOREIGN, ['cohortid'], 'cohort', ['id']); + + // Conditionally launch create table for block_advnotifications_coh. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Define table block_advnotifications_field to be created. + $table = new xmldb_table('block_advnotifications_field'); + + // Adding fields to table block_advnotifications_field. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('notificationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('userfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); + $table->add_field('operator', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); + $table->add_field('fieldvalue', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table block_advnotifications_field. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $table->add_key('notificationid', XMLDB_KEY_FOREIGN, ['notificationid'], 'block_advnotifications', ['id']); + + // Conditionally launch create table for block_advnotifications_field. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Define table block_advnotifications_roles to be created. + $table = new xmldb_table('block_advnotifications_roles'); + + // Adding fields to table block_advnotifications_roles. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('notificationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('roleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table block_advnotifications_roles. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $table->add_key('notificationid', XMLDB_KEY_FOREIGN, ['notificationid'], 'block_advnotifications', ['id']); + $table->add_key('roleid', XMLDB_KEY_FOREIGN, ['roleid'], 'role', ['id']); + + // Conditionally launch create table for block_advnotifications_roles. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Advnotifications savepoint reached. + upgrade_block_savepoint(true, 2021092901, 'advnotifications'); + } + // Add future upgrade points here. return true; -} \ No newline at end of file +} diff --git a/lang/en/block_advnotifications.php b/lang/en/block_advnotifications.php index 6196f0d..082bebf 100644 --- a/lang/en/block_advnotifications.php +++ b/lang/en/block_advnotifications.php @@ -150,6 +150,13 @@ // Misc. $string['advnotifications_join'] = ' & '; +$string['adduserfieldfilter'] = 'Add another user field filter'; +$string['audiencesaved'] = 'Audience save successfully.'; +$string['editing_audiences'] = 'Editing audiences'; +$string['filter_userfield'] = 'User field'; +$string['operator_beginwith'] = 'Begin with'; +$string['operator_contains'] = 'Contains'; +$string['operator_equals'] = 'Equals'; // Privacy API. $string['privacy:metadata:block_advnotifications'] = 'Information about notifications the user has been exposed to and recorded interactions.'; diff --git a/locallib.php b/locallib.php index da33a2a..459bb55 100644 --- a/locallib.php +++ b/locallib.php @@ -81,6 +81,16 @@ function prep_notifications($instanceid) { $render = false; } + if ($render && !\block_advnotifications\audience::meets_profile_requirements($notif->id, $USER->id)) { + $render = false; + } + if ($render && !\block_advnotifications\audience::meets_cohorts_requirements($notif->id, $USER->id)) { + $render = false; + } + if ($render && !\block_advnotifications\audience::meets_roles_requirements($notif->id, $USER->id, $notif->blockid)) { + $render = false; + } + if ($render) { // Update how many times the user has seen the notification. if ($userseen === false) { @@ -154,4 +164,4 @@ function get_date_formats() { $formats['j F Y'] = date('j F Y'); return $formats; -} \ No newline at end of file +} diff --git a/pages/audience.php b/pages/audience.php new file mode 100644 index 0000000..b4955f5 --- /dev/null +++ b/pages/audience.php @@ -0,0 +1,111 @@ +. + +/** + * Manage notifications audiences. + * + * @package block_advnotifications + * @copyright 2021 Daniel Neis Araujo + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../../config.php'); + +$id = required_param('id', PARAM_INT); + +$notification = $DB->get_record('block_advnotifications', ['id' => $id]); + +if ($notification->blockid) { + $bcontext = context_block::instance($notification->blockid); + $ctx = $bcontext->get_course_context(false); +} +if (empty($ctx)) { + $ctx = context_system::instance(); +} + +require_login(); + +$url = new moodle_url('/blocks/advnotifications/pages/audience.php', ['id' => $id]); + +$str = get_string('editing_audiences', 'block_advnotifications'); + +$manageurl = new moodle_url('/blocks/advnotifications/pages/notifications.php'); + +$PAGE->set_context($ctx); +$PAGE->set_pagelayout('standard'); +$PAGE->set_url($url); +$PAGE->set_title($str); +$PAGE->set_heading($str); + +$PAGE->navbar->add(get_string('blocks')); +$PAGE->navbar->add(get_string('pluginname', 'block_advnotifications')); +$PAGE->navbar->add(get_string('advnotifications_table_title_short', 'block_advnotifications'), $manageurl); +$PAGE->navbar->add($str); + +$output = $PAGE->get_renderer('block_advnotifications'); + +$userfieldfilters = $DB->get_records('block_advnotifications_field', ['notificationid' => $id]); +$notification->userfieldfilters = []; +foreach ($userfieldfilters as $f) { + $notification->userfieldfilters[] = [ + 'userfield' => $f->userfield, + 'operator' => $f->operator, + 'fieldvalue' => $f->fieldvalue, + ]; +} +if ($userfieldfilters) { + $filterscount = count($userfieldfilters); +} else { + $filterscount = 1; +} +$form = new \block_advnotifications\output\form\audience($url->out(false), + ['notificationid' => $id, 'filterscount' => $filterscount]); + +if ($form->is_cancelled()) { + redirect($manageurl); +} else if ($data = $form->get_data()) { + $DB->delete_records('block_advnotifications_coh', ['notificationid' => $id]); + $DB->delete_records('block_advnotifications_field', ['notificationid' => $id]); + $DB->delete_records('block_advnotifications_roles', ['notificationid' => $id]); + $coh = (object)['notificationid' => $id]; + foreach ($data->cohorts as $c) { + $coh->cohortid = $c; + $DB->insert_record_raw('block_advnotifications_coh', $coh); + } + $field = (object)['notificationid' => $id]; + if (isset($data->userfieldfilters)) { + foreach ($data->userfieldfilters as $f) { + if (!empty($f['userfield']) && !empty($f['operator']) && !empty($f['fieldvalue'])) { + $field->userfield = $f['userfield']; + $field->operator = $f['operator']; + $field->fieldvalue = $f['fieldvalue']; + $DB->insert_record_raw('block_advnotifications_field', $field); + } + } + } + $role = (object)['notificationid' => $id]; + foreach ($data->roles as $r) { + $role->roleid = $r; + $DB->insert_record_raw('block_advnotifications_roles', $role); + } + redirect($url, get_string('audiencesaved', 'block_advnotifications')); +} +$form->set_data($notification); + +echo $output->header(), + $output->heading($notification->title), + $form->render(), + $output->footer(); diff --git a/version.php b/version.php index 7578353..36a926c 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die; $plugin->component = 'block_advnotifications'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494). -$plugin->version = 2021021012; // YYYYMMDDHH (year, month, day, 24-hr format hour). +$plugin->version = 2021092901; // YYYYMMDDHH (year, month, day, 24-hr format hour). $plugin->requires = 2018051703; // YYYYMMDDHH (Version number for Moodle v3.5.3 as at 21/01/2019). $plugin->maturity = MATURITY_STABLE; // Code maturity/stability. -$plugin->release = 'v1.4.2'; // Human-readable release version. \ No newline at end of file +$plugin->release = 'v1.4.2'; // Human-readable release version.