diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index d68b6771875..b14e99f12a7 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -49,6 +49,7 @@ if ($hassiteconfig) { // message outputs $ADMIN->add('modules', new admin_category('messageoutputs', get_string('messageoutputs', 'message'))); $ADMIN->add('messageoutputs', new admin_page_managemessageoutputs()); + $ADMIN->add('messageoutputs', new admin_page_defaultmessageoutputs()); require_once($CFG->dirroot.'/message/lib.php'); $processors = get_message_processors(); foreach ($processors as $processor) { @@ -56,8 +57,8 @@ if ($hassiteconfig) { if (!$processor->available) { continue; } - $strprocessorname = get_string('pluginname', 'message_'.$processorname); - if (file_exists($CFG->dirroot.'/message/output/'.$processor->name.'/settings.php')) { + if ($processor->hassettings) { + $strprocessorname = get_string('pluginname', 'message_'.$processorname); $settings = new admin_settingpage('messagesetting'.$processorname, $strprocessorname, 'moodle/site:config', !$processor->enabled); include($CFG->dirroot.'/message/output/'.$processor->name.'/settings.php'); if ($settings) { diff --git a/lang/en/message.php b/lang/en/message.php index 590392a9fb9..be4a510ed9c 100644 --- a/lang/en/message.php +++ b/lang/en/message.php @@ -42,14 +42,18 @@ $string['contactlistempty'] = 'Your contact list is empty'; $string['contacts'] = 'Contacts'; $string['context'] = 'context'; $string['couldnotfindpreference'] = 'Could not load preference {$a}. Does the component and name you supplied to message_send() match a row in message_providers? Message providers must appear in the database so users can configure how they will be notified when they receive messages.'; +$string['defaultmessageoutputs'] = 'Default message outputs'; +$string['defaults'] = 'Defaults'; $string['deletemessagesdays'] = 'Number of days before old messages are automatically deleted'; $string['disabled'] = 'Messaging is disabled on this site'; +$string['disallowed'] = 'Disallowed'; $string['discussion'] = 'Discussion'; $string['editmymessage'] = 'Messaging'; $string['emailmessages'] = 'Email messages when I am offline'; $string['emailtagline'] = 'This is a copy of a message sent to you at "{$a->sitename}". Go to {$a->url} to reply.'; $string['emptysearchstring'] = 'You must search for something'; $string['errorcallingprocessor'] = 'Error calling defined processor'; +$string['forced'] = 'Forced'; $string['formorethan'] = 'For more than'; $string['guestnoeditmessage'] = 'Guest user can not edit messaging options'; $string['guestnoeditmessageother'] = 'Guest user can not edit other user messaging options'; @@ -98,6 +102,7 @@ $string['outputenabled'] = 'Output enabled'; $string['outputnotavailable'] = 'Not available'; $string['outputnotconfigured'] = 'Not configured'; $string['pagerefreshes'] = 'This page refreshes automatically every {$a} seconds'; +$string['permitted'] = 'Permitted'; $string['private_config'] = 'Popup message window'; $string['processortag'] = 'Destination'; $string['providers_config'] = 'Configure notification methods for incoming messages'; @@ -110,6 +115,8 @@ $string['search'] = 'Search'; $string['searchforperson'] = 'Search for a person'; $string['searchmessages'] = 'Search messages'; $string['searchcombined'] = 'Search people and messages'; +$string['sendingvia'] = 'Sending {$a->provider} via {$a->processor}'; +$string['sendingviawhen'] = 'Sending {$a->provider} via {$a->processor} when {$a->state}'; $string['sendmessage'] = 'Send message'; $string['sendmessageto'] = 'Send message to {$a}'; $string['sendmessagetopopup'] = 'Send message to {$a} - new window'; diff --git a/lib/adminlib.php b/lib/adminlib.php index 62a91ebbb20..2dacc2f79b9 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -4965,6 +4965,21 @@ class admin_page_managemessageoutputs extends admin_externalpage { } } +/** + * Default message outputs configuration + * + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_page_defaultmessageoutputs extends admin_page_managemessageoutputs { + /** + * Calls parent::__construct with specific arguments + */ + public function __construct() { + global $CFG; + admin_externalpage::__construct('defaultmessageoutputs', get_string('defaultmessageoutputs', 'message'), "$CFG->wwwroot/message/defaultoutputs.php"); + } +} + /** * Question type manage page * diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 70f05e40df5..336f36e6a81 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -445,6 +445,7 @@ class page_requirements_manager { break; case 'core_message': $module = array('name' => 'core_message', + 'requires' => array('base', 'node', 'event', 'node-event-simulate'), 'fullpath' => '/message/module.js'); break; case 'core_flashdetect': diff --git a/message/defaultoutputs.php b/message/defaultoutputs.php new file mode 100644 index 00000000000..6c23e3f665a --- /dev/null +++ b/message/defaultoutputs.php @@ -0,0 +1,115 @@ +. + +/** + * Default message outputs configuration page + * + * @package message + * @copyright 2011 Lancaster University Network Services Limited + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once(dirname(dirname(__FILE__)) . '/config.php'); +require_once(dirname(dirname(__FILE__)) . '/message/lib.php'); +require_once($CFG->libdir.'/adminlib.php'); + +// This is an admin page +admin_externalpage_setup('defaultmessageoutputs'); + +// Require site configuration capability +require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); + +// Fetch processors +$processors = get_message_processors(true); +// Fetch message providers +$providers = $DB->get_records('message_providers', null, 'name'); + +if (($form = data_submitted()) && confirm_sesskey()) { + $preferences = array(); + // Prepare default message outputs settings + foreach ( $providers as $provider) { + $componentproviderbase = $provider->component.'_'.$provider->name; + foreach (array('permitted', 'loggedin', 'loggedoff') as $setting){ + $value = null; + $componentprovidersetting = $componentproviderbase.'_'.$setting; + if ($setting == 'permitted') { + // if we deal with permitted select element, we need to create individual + // setting for each possible processor. Note that this block will + // always be processed first after entring parental foreach iteration + // so we can change form values on this stage. + foreach($processors as $processor) { + $value = ''; + if (isset($form->{$componentprovidersetting}[$processor->name])) { + $value = $form->{$componentprovidersetting}[$processor->name]; + } + // Ensure that loggedin loggedoff options are set correctly + // for this permission + if ($value == 'forced') { + $form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1; + $form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1; + } else if ($value == 'disallowed') { + // It might be better to unset them, but I can't figure out why that cause error + $form->{$componentproviderbase.'_loggedin'}[$processor->name] = 0; + $form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 0; + } + // record the site preference + $preferences[$processor->name.'_provider_'.$componentprovidersetting] = $value; + } + } else if (array_key_exists($componentprovidersetting, $form)) { + // we must be processing loggedin or loggedoff checkboxes. Store + // defained comma-separated processors as setting value. + // Using array_filter eliminates elements set to 0 above + $value = join(',', array_keys(array_filter($form->{$componentprovidersetting}))); + if (empty($value)) { + $value = null; + } + } + if ($setting != 'permitted') { + // we have already recoded site preferences for 'permitted' type + $preferences['message_provider_'.$componentprovidersetting] = $value; + } + } + } + + // Update database + $transaction = $DB->start_delegated_transaction(); + foreach ($preferences as $name => $value) { + set_config($name, $value, 'message'); + } + $transaction->allow_commit(); + + // Redirect + $url = new moodle_url('defaultoutputs.php'); + redirect($url); +} + + + +// Page settings +$PAGE->set_context(get_context_instance(CONTEXT_SYSTEM)); +$PAGE->requires->js_init_call('M.core_message.init_defaultoutputs'); + +// Grab the renderer +$renderer = $PAGE->get_renderer('core', 'message'); + +// Display the manage message outputs interface +$preferences = get_config('message'); +$messageoutputs = $renderer->manage_defaultmessageoutputs($processors, $providers, $preferences); + +// Display the page +echo $OUTPUT->header(); +echo $OUTPUT->heading(get_string('defaultmessageoutputs', 'message')); +echo $messageoutputs; +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/message/lib.php b/message/lib.php index 32f6d4cb9b8..48a35fd435a 100644 --- a/message/lib.php +++ b/message/lib.php @@ -53,6 +53,11 @@ define('MESSAGE_SEARCH_MAX_RESULTS', 200); define('MESSAGE_CONTACTS_PER_PAGE',10); define('MESSAGE_MAX_COURSE_NAME_LENGTH', 30); +/** + * Set default value for default outputs permitted setting + */ +define('MESSAGE_DEFAULT_PERMITTED_VALUE', 'disallowed'); + if (!isset($CFG->message_contacts_refresh)) { // Refresh the contacts list every 60 seconds $CFG->message_contacts_refresh = 60; } @@ -2171,30 +2176,45 @@ function message_print_heading($title, $colspan=3) { /** * Get all message processors and validate corresponding plugin existance and * configuration + * @param bool $enabled only return enabled processors * @return array $processors array of objects containing information on message processors */ -function get_message_processors() { +function get_message_processors($enabled = false) { global $DB, $CFG; - $processors = $DB->get_records('message_processors', null, 'name'); - foreach ($processors as &$processor){ - $processorfile = $CFG->dirroot. '/message/output/'.$processor->name.'/message_output_'.$processor->name.'.php'; - if (is_readable($processorfile)) { - include_once($processorfile); - $processclass = 'message_output_' . $processor->name; - if (class_exists($processclass)) { - $pclass = new $processclass(); - $processor->configured = 0; - if ($pclass->is_system_configured()) { - $processor->configured = 1; + static $processors; + + if (empty($processors)) { + $processors = $DB->get_records('message_processors', null, 'name'); + foreach ($processors as &$processor){ + $processorfile = $CFG->dirroot. '/message/output/'.$processor->name.'/message_output_'.$processor->name.'.php'; + if (is_readable($processorfile)) { + include_once($processorfile); + $processclass = 'message_output_' . $processor->name; + if (class_exists($processclass)) { + $pclass = new $processclass(); + $processor->configured = 0; + if ($pclass->is_system_configured()) { + $processor->configured = 1; + } + $processor->hassettings = 0; + if (is_readable($CFG->dirroot.'/message/output/'.$processor->name.'/settings.php')) { + $processor->hassettings = 1; + } + $processor->available = 1; + } else { + print_error('errorcallingprocessor', 'message'); } - $processor->available = 1; } else { - print_error('errorcallingprocessor', 'message'); + $processor->available = 0; } - } else { - $processor->available = 0; } } + if ($enabled) { + // Filter out enabled processors only, the reason of not doing this in + // database request is caching the result. + $processors = array_filter($processors, create_function('$a', 'return $a->enabled;')); + } + return $processors; } diff --git a/message/module.js b/message/module.js index e0627d0cc65..d92f7484b8a 100644 --- a/message/module.js +++ b/message/module.js @@ -42,4 +42,49 @@ M.core_message.init_notification = function(Y, title, content, url) { return false; }, o); }); -}; \ No newline at end of file +}; + +M.core_message.init_defaultoutputs = function(Y) { + var defaultoutputs = { + + init : function() { + Y.all('#defaultmessageoutputs select').each(function(node) { + // attach event listener + node.on('change', defaultoutputs.changeState); + // set initial layout + node.simulate("change"); + }, this); + }, + + changeState : function(e) { + var value = e.target._node.options[e.target.get('selectedIndex')].value; + var parentnode = e.target.ancestor('td'); + switch (value) { + case 'forced': + defaultoutputs.updateCheckboxes(parentnode, 1, 1); + break; + case 'disallowed': + defaultoutputs.updateCheckboxes(parentnode, 1, 0); + break; + case 'permitted': + defaultoutputs.updateCheckboxes(parentnode, 0, 0); + break; + } + }, + + updateCheckboxes : function(blocknode, disabled, checked) { + blocknode.all('input[type=checkbox]').each(function(node) { + node.removeAttribute('disabled'); + if (disabled) { + node.setAttribute('disabled', 1) + node.removeAttribute('checked'); + } + if (checked) { + node.setAttribute('checked', 1) + } + }, this); + } + } + + defaultoutputs.init(); +} \ No newline at end of file diff --git a/message/renderer.php b/message/renderer.php index 532f25ef898..7ac5f0fb6d4 100644 --- a/message/renderer.php +++ b/message/renderer.php @@ -46,8 +46,6 @@ class core_message_renderer extends plugin_renderer_base { // Display the current workflows $table = new html_table(); $table->attributes['class'] = 'generaltable'; - $table->head = array(); - $table->colclasses = array(); $table->data = array(); $table->head = array( get_string('name'), @@ -58,7 +56,7 @@ class core_message_renderer extends plugin_renderer_base { 'displayname', 'availability', 'settings', ); - foreach ( $processors as $processor ){ + foreach ($processors as $processor) { $row = new html_table_row(); $row->attributes['class'] = 'messageoutputs'; @@ -94,7 +92,7 @@ class core_message_renderer extends plugin_renderer_base { } // Settings $settings = new html_table_cell(); - if ($processor->available && file_exists($CFG->dirroot.'/message/output/'.$processor->name.'/settings.php')) { + if ($processor->available && $processor->hassettings) { $settingsurl = new moodle_url('settings.php', array('section' => 'messagesetting'.$processor->name)); $settings->text = html_writer::link($settingsurl, get_string('settings', 'message')); } @@ -104,4 +102,105 @@ class core_message_renderer extends plugin_renderer_base { } return html_writer::table($table); } + + /** + * Display the interface to manage default message outputs + * + * @param array $processors The list of message processors + * @param array $providers The list of message providers + * @param array $preferences The list of current preferences + * @return string The text to render + */ + public function manage_defaultmessageoutputs($processors, $providers, $preferences) { + global $CFG; + + // Prepare list of options for dropdown menu + $options = array(); + foreach (array('disallowed', 'permitted', 'forced') as $setting) { + $options[$setting] = get_string($setting, 'message'); + } + + $output = html_writer::start_tag('form', array('id'=>'defaultmessageoutputs', 'method'=>'post')); + $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey())); + + // Display users outputs table + $table = new html_table(); + $table->attributes['class'] = 'generaltable'; + $table->data = array(); + $table->head = array(''); + + // Populate the header row + foreach ($processors as $processor) { + $table->head[] = get_string('pluginname', 'message_'.$processor->name); + } + // Generate the matrix of settings for each provider and processor + foreach ($providers as $provider) { + $row = new html_table_row(); + $row->attributes['class'] = 'defaultmessageoutputs'; + $row->cells = array(); + + // Provider Name + $providername = get_string('messageprovider:'.$provider->name, $provider->component); + $row->cells[] = new html_table_cell($providername); + + // Settings for each processor + foreach ($processors as $processor) { + $cellcontent = ''; + foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) { + // pepare element and preference names + $elementname = $provider->component.'_'.$provider->name.'_'.$setting.'['.$processor->name.']'; + $preferencebase = $provider->component.'_'.$provider->name.'_'.$setting; + // prepare language bits + $processorname = get_string('pluginname', 'message_'.$processor->name); + $statename = get_string($setting, 'message'); + $labelparams = array( + 'provider' => $providername, + 'processor' => $processorname, + 'state' => $statename + ); + if ($setting == 'permitted') { + $label = get_string('sendingvia', 'message', $labelparams); + // determine the current setting or use default + $select = MESSAGE_DEFAULT_PERMITTED_VALUE; + $preference = $processor->name.'_provider_'.$preferencebase; + if (array_key_exists($preference, $preferences)) { + $select = $preferences->{$preference}; + } + // dropdown menu + $cellcontent = html_writer::select($options, $elementname, $select, false, array('id' => $elementname)); + $cellcontent .= html_writer::label($label, $elementname, true, array('class' => 'accesshide')); + $cellcontent .= html_writer::tag('div', get_string('defaults', 'message')); + } else { + $label = get_string('sendingviawhen', 'message', $labelparams); + // determine the current setting based on the 'permitted' setting above + $checked = false; + if ($select == 'forced') { + $checked = true; + } else if ($select == 'permitted') { + $preference = 'message_provider_'.$preferencebase; + if (array_key_exists($preference, $preferences)) { + $checked = (int)in_array($processor->name, explode(',', $preferences->{$preference})); + } + } + // generate content + $cellcontent .= html_writer::start_tag('div'); + $cellcontent .= html_writer::checkbox($elementname, 1, $checked, '', array('id' => $elementname)); + $cellcontent .= html_writer::label($label, $elementname, true, array('class' => 'accesshide')); + $cellcontent .= $statename; + $cellcontent .= html_writer::end_tag('div'); + } + } + $row->cells[] = new html_table_cell($cellcontent); + } + $table->data[] = $row; + } + + $output .= html_writer::table($table); + $output .= html_writer::start_tag('div', array('class' => 'form-buttons')); + $output .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('savechanges','admin'), 'class' => 'form-submit')); + $output .= html_writer::end_tag('div'); + $output .= html_writer::end_tag('form'); + return $output; + } + }