diff --git a/message/output/airnotifier/classes/manager.php b/message/output/airnotifier/classes/manager.php new file mode 100755 index 00000000000..bbb7b0f77a5 --- /dev/null +++ b/message/output/airnotifier/classes/manager.php @@ -0,0 +1,198 @@ +. + +/** + * Airnotifier manager class + * + * @package message_airnotifier + * @category external + * @copyright 2012 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.7 + */ + + +/** + * Airnotifier helper manager class + * + * @copyright 2012 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class message_airnotifier_manager { + + /** + * Include the relevant javascript and language strings for the device + * toolbox YUI module + * + * @return bool + */ + public function include_device_ajax() { + global $PAGE, $CFG; + + if (!$CFG->enableajax) { + return false; + } + + $config = new stdClass(); + + // The URL to use for resource changes. + if (!isset($config->resturl)) { + $config->resturl = '/message/output/airnotifier/rest.php'; + } + + // Any additional parameters which need to be included on page submission. + if (!isset($config->pageparams)) { + $config->pageparams = array(); + } + + // Include toolboxes. + $PAGE->requires->yui_module('moodle-message_airnotifier-toolboxes', 'M.message.init_device_toolbox', array(array( + 'ajaxurl' => $config->resturl, + 'config' => $config, + )) + ); + + // Required strings for the javascript. + $PAGE->requires->strings_for_js(array('deletecheckdevicename'), 'message_airnotifier'); + $PAGE->requires->strings_for_js(array('show', 'hide'), 'moodle'); + + return true; + } + + /** + * Return the user devices for a specific app. + * + * @param string $appname the app name . + * @param int $userid if empty take the current user. + * @return array all the devices + */ + public function get_user_devices($appname, $userid = null) { + global $USER, $DB; + + if (empty($userid)) { + $userid = $USER->id; + } + + $devices = array(); + + $params = array('appid' => $appname, 'userid' => $userid); + + // First, we look all the devices registered for this user in the Moodle core. + // We are going to allow only ios devices (since these are the ones that supports PUSH notifications). + if ($userdevices = $DB->get_records('user_devices', $params)) { + foreach ($userdevices as $device) { + if (core_text::strtolower($device->platform) == 'ios') { + // Check if the device is known by airnotifier. + if (!$airnotifierdev = $DB->get_record('message_airnotifier_devices', array('userdeviceid' => $device->id))) { + // We have to create the device token in airnotifier. + + if (! $this->create_token($device->pushid)) { + continue; + } + + $airnotifierdev = new stdClass; + $airnotifierdev->userdeviceid = $device->id; + $airnotifierdev->enable = 1; + $airnotifierdev->id = $DB->insert_record('message_airnotifier_devices', $airnotifierdev); + } + $device->id = $airnotifierdev->id; + $device->enable = $airnotifierdev->enable; + $devices[] = $device; + } + } + } + return $devices; + } + + /** + * Request and access key to Airnotifier + * + * @return mixed The access key or false in case of error + */ + public function request_accesskey() { + global $CFG, $USER; + + require_once($CFG->libdir . '/filelib.php'); + + // Sending the request access key request to Airnotifier. + $serverurl = $CFG->airnotifierurl . ':' . $CFG->airnotifierport . '/accesskeys/'; + // We use an APP Key "none", it can be anything. + $header = array('Accept: application/json', 'X-AN-APP-NAME: ' . $CFG->airnotifierappname, + 'X-AN-APP-KEY: none'); + $curl = new curl(); + $curl->setHeader($header); + + // Site ids are stored as secrets in md5 in the Moodle public hub. + $params = array( + 'url' => $CFG->wwwroot, + 'siteid' => md5($CFG->siteidentifier), + 'contact' => $USER->email, + 'description' => $CFG->wwwroot + ); + $resp = $curl->post($serverurl, $params); + + if ($key = json_decode($resp, true)) { + if (!empty($key['accesskey'])) { + return $key['accesskey']; + } + } + return false; + } + + /** + * Create a device token in the Airnotifier instance + * @param string $token The token to be created + * @return bool True if all was right + */ + private function create_token($token) { + global $CFG; + + if (!$this->is_system_configured()) { + return false; + } + + require_once($CFG->libdir . '/filelib.php'); + + $serverurl = $CFG->airnotifierurl . ':' . $CFG->airnotifierport . '/tokens/' . $token; + $header = array('Accept: application/json', 'X-AN-APP-NAME: ' . $CFG->airnotifierappname, + 'X-AN-APP-KEY: ' . $CFG->airnotifieraccesskey); + $curl = new curl; + $curl->setHeader($header); + $params = array(); + $resp = $curl->post($serverurl, $params); + + if ($resp = json_decode($resp, true)) { + if (!empty($resp['status'])) { + return $resp['status'] == 'ok' || $resp['status'] == 'token exists'; + } + } + return false; + } + + /** + * Tests whether the airnotifier settings have been configured + * @return boolean true if airnotifier is configured + */ + public function is_system_configured() { + global $CFG; + + return (!empty($CFG->airnotifierurl) && !empty($CFG->airnotifierport) && + !empty($CFG->airnotifieraccesskey) && !empty($CFG->airnotifierappname) && + !empty($CFG->airnotifiermobileappname)); + } + +} + diff --git a/message/output/airnotifier/db/install.php b/message/output/airnotifier/db/install.php index 6e439ba4cdd..433698b5fd1 100755 --- a/message/output/airnotifier/db/install.php +++ b/message/output/airnotifier/db/install.php @@ -1,5 +1,4 @@ name = 'airnotifier'; $DB->insert_record('message_processors', $provider); + return $result; } diff --git a/message/output/airnotifier/db/install.xml b/message/output/airnotifier/db/install.xml index e4df629034a..ec529ff0924 100755 --- a/message/output/airnotifier/db/install.xml +++ b/message/output/airnotifier/db/install.xml @@ -1,25 +1,18 @@ - - +
- - - - - - - - - - - + + + +
diff --git a/message/output/airnotifier/db/services.php b/message/output/airnotifier/db/services.php index 47c3c45aaca..f7fa49ec9c1 100755 --- a/message/output/airnotifier/db/services.php +++ b/message/output/airnotifier/db/services.php @@ -25,20 +25,19 @@ */ $functions = array( - 'message_airnotifier_add_user_device' => array( + 'message_airnotifier_is_system_configured' => array( 'classname' => 'message_airnotifier_external', - 'methodname' => 'add_user_device', + 'methodname' => 'is_system_configured', 'classpath' => 'message/output/airnotifier/externallib.php', - 'description' => 'Add device to user device list', - 'type' => 'write', + 'description' => 'Check whether the airnotifier settings have been configured', + 'type' => 'read', ), - 'message_airnotifier_get_access_key' => array( + 'message_airnotifier_are_notification_preferences_configured' => array( 'classname' => 'message_airnotifier_external', - 'methodname' => 'get_access_key', + 'methodname' => 'are_notification_preferences_configured', 'classpath' => 'message/output/airnotifier/externallib.php', - 'description' => 'Get the mobile device access key with specified permissions', + 'description' => 'Check if the users have notification preferences configured yet', 'type' => 'read', ), ); - diff --git a/message/output/airnotifier/db/upgrade.php b/message/output/airnotifier/db/upgrade.php deleted file mode 100755 index acee7891e9a..00000000000 --- a/message/output/airnotifier/db/upgrade.php +++ /dev/null @@ -1,68 +0,0 @@ -. - -/** - * Upgrade code for airnotifier message processor - * - * @package message_airnotifier - * @copyright 2012 Jerome Mouneyrac - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Upgrade code for the airnotifier message processor - * - * @param int $oldversion The version that we are upgrading from - */ -function xmldb_message_airnotifier_upgrade($oldversion) { - global $CFG, $DB; - - $dbman = $DB->get_manager(); - - - if ($oldversion < 2012070500.05) { - - // Define table user_devices to be created - $table = new xmldb_table('airnotifier_user_devices'); - - // Adding fields to table user_devices - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('appname', XMLDB_TYPE_CHAR, '100', null, null, null, null); - $table->add_field('devicename', XMLDB_TYPE_CHAR, '255', null, null, null, null); - $table->add_field('devicetype', XMLDB_TYPE_CHAR, '100', null, null, null, null); - $table->add_field('deviceos', XMLDB_TYPE_CHAR, '100', null, null, null, null); - $table->add_field('deviceosversion', XMLDB_TYPE_CHAR, '100', null, null, null, null); - $table->add_field('devicebrand', XMLDB_TYPE_CHAR, '100', null, null, null, null); - $table->add_field('devicenotificationtoken', XMLDB_TYPE_CHAR, '255', null, null, null, null); - $table->add_field('deviceuid', XMLDB_TYPE_CHAR, '255', null, null, null, null); - $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); - $table->add_field('enable', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1'); - - // Adding keys to table user_devices - $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - - // Conditionally launch create table for user_devices - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - // Main savepoint reached - upgrade_plugin_savepoint(true, 2012070500.05); - } - - return true; -} - diff --git a/message/output/airnotifier/externallib.php b/message/output/airnotifier/externallib.php index 6f52b8a2425..3be2313e71e 100755 --- a/message/output/airnotifier/externallib.php +++ b/message/output/airnotifier/externallib.php @@ -15,136 +15,163 @@ // along with Moodle. If not, see . /** - * external API for airnotifier web services + * External functions * * @package message_airnotifier * @category external * @copyright 2012 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 2.4 + * @since Moodle 2.7 + */ + + +/** + * External API for airnotifier web services + * + * @package message_airnotifier + * @category external + * @copyright 2012 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.7 */ class message_airnotifier_external extends external_api { /** - * Returns description of add_user_device() parameters + * Returns description of method parameters * - * @return external_function_parameters - * @since Moodle 2.4 + * @since Moodle 2.7 */ - public static function add_user_device_parameters() { + public static function is_system_configured_parameters() { + return new external_function_parameters( + array() + ); + } + + /** + * Tests whether the airnotifier settings have been configured + * + * @since Moodle 2.7 + */ + public static function is_system_configured() { + + $manager = new message_airnotifier_manager(); + return (int) $manager->is_system_configured(); + } + + /** + * Returns description of method result value + * + * @return external_single_structure + * @since Moodle 2.7 + */ + public static function is_system_configured_returns() { + return new external_value( PARAM_INT, '0 if the system is not configured, 1 otherwise'); + } + + /** + * Returns description of method parameters + * + * @since Moodle 2.7 + */ + public static function are_notification_preferences_configured_parameters() { return new external_function_parameters( - array('device' => new external_single_structure( array( - 'appname' => new external_value( PARAM_TEXT, 'the app name'), - 'devicename' => new external_value( PARAM_TEXT, 'Device name: "Jerome\'s iPhone"', VALUE_OPTIONAL), - 'devicetype' => new external_value( PARAM_TEXT, 'iPhone 3GS, Google Nexus S, ...', VALUE_OPTIONAL), - 'deviceos' => new external_value( PARAM_TEXT, 'iOS, Android, ...', VALUE_OPTIONAL), - 'deviceosversion' => new external_value( PARAM_TEXT, 'OS version number', VALUE_OPTIONAL), - 'devicebrand' => new external_value( PARAM_TEXT, 'the device brand (Apple, Samsung, ...)', VALUE_OPTIONAL), - 'devicenotificationtoken' => new external_value( PARAM_RAW, 'the device token used to send notification for the specified app'), - 'deviceuid' => new external_value( PARAM_RAW, 'the device unique device id if it exists', VALUE_OPTIONAL), - ), 'the device information - Important: type, os, osversion and brand will be saved in lowercase for fast searching' - ) - )); + 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user ID')), + ) + ); } /** - * Add a device to the user device list + * Check if the users have notification preferences configured for the airnotifier plugin * - * @param array $device - * @return int device id - * @since Moodle 2.4 + * @param array $userids Array of user ids + * @since Moodle 2.7 */ - public static function add_user_device($device) { - global $USER, $CFG; + public static function are_notification_preferences_configured($userids) { + global $CFG, $USER, $DB; - $params = self::validate_parameters(self::add_user_device_parameters(), - array('device'=>$device)); + require_once($CFG->dirroot . '/message/lib.php'); + $params = self::validate_parameters(self::are_notification_preferences_configured_parameters(), + array('userids' => $userids)); - // Ensure the current user is allowed to run this function - $context = context_user::instance($USER->id); - self::validate_context($context); - require_capability('message/airnotifier:managedevice', $context); + list($sqluserids, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); + $uselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); + $ujoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)"; + $params['contextlevel'] = CONTEXT_USER; + $usersql = "SELECT u.* $uselect + FROM {user} u $ujoin + WHERE u.id $sqluserids"; + $users = $DB->get_recordset_sql($usersql, $params); - $device['userid'] = $USER->id; + $result = array(); + $hasuserupdatecap = has_capability('moodle/user:update', context_system::instance()); + foreach ($users as $user) { - require_once($CFG->dirroot . "/message/output/airnotifier/lib.php"); - $airnotifiermanager = new airnotifier_manager(); - $device['id'] = $airnotifiermanager->add_user_device($device); + $currentuser = ($user->id == $USER->id); - return $device['id']; - } + if ($currentuser or $hasuserupdatecap) { - /** - * Returns description of add_user_device() result value - * - * @return external_single_structure - * @since Moodle 2.4 - */ - public static function add_user_device_returns() { - return new external_value( PARAM_INT, 'Device id in the Moodle database'); - } + if (!empty($user->deleted)) { + $result['warnings'][] = "User $user->id was deleted"; + continue; + } - /** - * Returns description of get_access_key() parameters - * - * @return external_function_parameters - * @since Moodle 2.4 - */ - public static function get_access_key_parameters() { - return new external_function_parameters( - array('permissions' => new external_multiple_structure( - new external_value( PARAM_ALPHA, 'the permission'), - 'Allowed permissions: createtoken (not yet implemented: deletetoken, accessobjects, - sendnotification, sendbroadcast)', - VALUE_DEFAULT, array() - ) - )); - } + $preferences = array(); + $preferences['userid'] = $user->id; + $preferences['configured'] = 0; - /** - * Get access key with specified permissions - * - * @param array $permissions the permission that the access key should - * @return string access key - * @since Moodle 2.4 - */ - public static function get_access_key($permissions = array()) { - global $CFG; + // Now we get for all the providers and all the states + // the user preferences to check if at least one is enabled for airnotifier plugin. + $providers = message_get_providers_for_user($user->id); + foreach ($providers as $provider) { + foreach (array('loggedin', 'loggedoff') as $state) { + $prefname = 'message_provider_'.$provider->component.'_'.$provider->name.'_'.$state; + $linepref = get_user_preferences($prefname, '', $user->id); + if ($linepref == '') { + continue; + } + $lineprefarray = explode(',', $linepref); - $params = self::validate_parameters(self::get_access_key_parameters(), - array('permissions'=>$permissions)); + foreach ($lineprefarray as $pref) { + if ($pref == 'airnotifier') { + $preferences['configured'] = 1; + break 2; + } + } + } + } - // Check that user can use the requested permission. - foreach ($params['permissions'] as $perm) { - switch ($perm) { - case 'createtoken': - // Any mobile device / user should have this permission. - // No need to check anything for this permission. - - break; - - default: - throw new moodle_exception('permissionnotimplemented'); - break; + $result['users'][] = $preferences; + } else if (!$hasuserupdatecap) { + $result['warnings'][] = "You don't have permissions for view user $user->id preferences"; } + } + $users->close(); - // Look for access key that have exactly the same permissions. - // TODO: This mobile device access key should be retrieve by web service from - // moodle.org or airnotifer when the admin enables mobile on Moodle. - $accesskey = $CFG->airnotifierdeviceaccesskey; - - return $accesskey; + return $result; } /** - * Returns description of add_user_device() result value + * Returns description of method result value * * @return external_single_structure - * @since Moodle 2.4 + * @since Moodle 2.7 */ - public static function get_access_key_returns() { - return new external_value( PARAM_ALPHANUMEXT, 'access key'); + public static function are_notification_preferences_configured_returns() { + return new external_single_structure( + array( + 'users' => new external_multiple_structure( + new external_single_structure( + array ( + 'userid' => new external_value(PARAM_INT, 'userid id'), + 'configured' => new external_value(PARAM_INT, '1 is the user preferences have been configured and 0 if not') + ) + ), + 'list of preferences by user'), + 'warnings' => new external_warnings() + ) + ); } -} + +} \ No newline at end of file diff --git a/message/output/airnotifier/lang/en/message_airnotifier.php b/message/output/airnotifier/lang/en/message_airnotifier.php index 9f94a3599fe..2c8c5c019ad 100755 --- a/message/output/airnotifier/lang/en/message_airnotifier.php +++ b/message/output/airnotifier/lang/en/message_airnotifier.php @@ -1,5 +1,4 @@ name}'; -$string['deletedevice'] = 'Delete the device. Note that it will not forbid an app to register it again. If the device keep reappearing, disable it.'; +$string['deletedevice'] = 'Delete the device. Note that an app can register the device again. If the device keeps reappearing, disable it.'; $string['devicetoken'] = 'Device token'; -$string['nodevices'] = 'No registered devices. Devices are automatically registered when you allow a Moodle iOS app to receive push notifications.'; +$string['errorretrievingkey'] = 'An error occurred while retrieving key. Your Moodle site must be registered with Moodle.org to use this service. You may need to re-register to update your details there.'; +$string['keyretrievedsuccessfully'] = 'Key retrieved successfully'; +$string['nodevices'] = 'No registered devices. Devices will automatically register after you allow a Moodle iOS app to receive push notifications.'; $string['notconfigured'] = 'The Airnotifier server hasn\'t been configured so Airnotifier messages cannot be sent'; -$string['pluginname'] = 'iPhone/iPad'; +$string['pluginname'] = 'Mobile notifications'; +$string['sitemustberegistered'] = 'In order to use the public Airnotifier instance you must register your site with Moodle.org'; $string['showhide'] = 'Enable/disable the device.'; +$string['requestaccesskey'] = 'Request access key'; $string['unknowndevice'] = 'Unknown device'; diff --git a/message/output/airnotifier/lib.php b/message/output/airnotifier/lib.php deleted file mode 100755 index 57c2d41348d..00000000000 --- a/message/output/airnotifier/lib.php +++ /dev/null @@ -1,139 +0,0 @@ -. - -/** - * Airnotifier related functions - * - * @package message_airnotifier - * @category external - * @copyright 2012 Jerome Mouneyrac - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 2.4 - */ -class airnotifier_manager { - - /** - * Include the relevant javascript and language strings for the device - * toolbox YUI module - * - * @return bool - */ - function include_device_ajax() { - global $PAGE, $CFG; - - if (!$CFG->enableajax) { - return false; - } - - $config = new stdClass(); - - // The URL to use for resource changes - if (!isset($config->resturl)) { - $config->resturl = '/message/output/airnotifier/rest.php'; - } - - // Any additional parameters which need to be included on page submission - if (!isset($config->pageparams)) { - $config->pageparams = array(); - } - - // Include toolboxes - $PAGE->requires->yui_module('moodle-message_airnotifier-toolboxes', 'M.message.init_device_toolbox', array(array( - 'ajaxurl' => $config->resturl, - 'config' => $config, - )) - ); - - // Required strings for the javascript - $PAGE->requires->strings_for_js(array('deletecheckdevicename'), 'message_airnotifier'); - $PAGE->requires->strings_for_js(array('show','hide'), 'moodle'); - - return true; - } - - /** - * Add device to the user device list. - * - * @param object $device - * @param int $userid if empty take the current user - * @return int device id (in Moodle database) - */ - public function add_user_device($device, $userid = null) { - global $DB, $USER; - - if (empty($user)) { - $userid = $USER->id; - } - - $device = (object) $device; - - // Check if the device token already exist - Note that we look for user in case several users use the same device - $existingdevice = $DB->get_record('airnotifier_user_devices', array('appname' => $device->appname, - 'devicenotificationtoken' => $device->devicenotificationtoken, 'userid' => $userid)); - - // trim the data (some field should be in lowercase to make the search on them quickly) - $attributstolower = array('devicetype', 'deviceos', 'deviceosversion', 'devicebrand'); - if ($existingdevice) { - foreach ($device as $attributname => $value) { - if (in_array($attributname, $attributstolower)) { - $existingdevice->{$attributname} = strtolower($value); - } else { - $existingdevice->{$attributname} = $value; - } - } - } else { - foreach ($attributstolower as $attribut) { - if (!empty($device->{$attribut})) { - $device->{$attribut} = strtolower($device->{$attribut}); - } - } - } - - if ($existingdevice) { - $DB->update_record('airnotifier_user_devices', $existingdevice); - return $existingdevice->id; - } else { - return $DB->insert_record('airnotifier_user_devices', $device); - } - } - - /** - * Return the user devices for a specific app. - * - * @param string $appname the app name . - * @param int $userid if empty take the current user. - * @param int $enabled if 1 returned only enabled devices, if 0 only disabled devices, if null all devices. - * @return array all the devices - */ - public function get_user_devices($appname, $userid = null, $enabled = null) { - global $USER, $DB; - - if (empty($userid)) { - $userid = $USER->id; - } - - $params = array('appname' => $appname, 'userid' => $userid); - if ($enabled !== null) { - $params['enable'] = $enabled; - } - - return $DB->get_records('airnotifier_user_devices', $params); - } - -} - -?> diff --git a/message/output/airnotifier/message_output_airnotifier.php b/message/output/airnotifier/message_output_airnotifier.php index 202cfcaaf48..299e4ad6397 100755 --- a/message/output/airnotifier/message_output_airnotifier.php +++ b/message/output/airnotifier/message_output_airnotifier.php @@ -1,5 +1,4 @@ . +/** + * Airnotifier message processor to send messages to the APNS provider: airnotfier. (https://github.com/dongsheng/airnotifier) + * + * @package message_airnotifier + * @category external + * @copyright 2012 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.7 + */ + + require_once($CFG->dirroot . '/message/output/lib.php'); -require_once($CFG->dirroot . '/message/output/airnotifier/lib.php'); /** - * Airnotifier message processor to send messages to the APNS provider: airnotfier. - * (https://github.com/dongsheng/airnotifier) + * Message processor class * * @package message_airnotifier * @copyright 2012 Jerome Mouneyrac @@ -34,66 +42,76 @@ class message_output_airnotifier extends message_output { * @param stdClass $eventdata the event data submitted by the message sender plus $eventdata->savedmessageid * @return true if ok, false if error */ - function send_message($eventdata) { + public function send_message($eventdata) { global $CFG; if (!empty($CFG->noemailever)) { - // hidden setting for development sites, set in config.php if needed + // Hidden setting for development sites, set in config.php if needed. debugging('$CFG->noemailever active, no airnotifier message sent.', DEBUG_MINIMAL); return true; } - // skip any messaging suspended and deleted users - if ($eventdata->userto->auth === 'nologin' or $eventdata->userto->suspended or - $eventdata->userto->deleted) { + // Skip any messaging suspended and deleted users. + if ($eventdata->userto->auth === 'nologin' or + $eventdata->userto->suspended or + $eventdata->userto->deleted) { return true; } + // Site id, to map with Moodle Mobile stored sites. + $siteid = md5($CFG->wwwroot . $eventdata->userto->username); + // Mandatory notification data that need to be sent in the payload. They have variable length. // We need to take them in consideration to calculate the maximum message size. - $notificationdata = array("urlparams" => $eventdata->urlparams, "id" => $eventdata->savedmessageid, - "type" => $eventdata->component . '_' . $eventdata->name, "userfrom" => fullname($eventdata->userfrom)); + $notificationdata = array( + "site" => $siteid, + "type" => $eventdata->component . '_' . $eventdata->name, + "userfrom" => fullname($eventdata->userfrom)); // Calculate the size of the message knowing Apple payload must be lower than 256 bytes. // Airnotifier using few bytes of the payload, we must limit our message to even less characters. - $maxmsgsize = 205 - strlen(json_encode($notificationdata)); - $message = $eventdata->smallmessage; - // If the message size is too big make it shorter - if (strlen($message) >= $maxmsgsize) { + $maxmsgsize = 205 - core_text::strlen(json_encode($notificationdata)); + $message = s($eventdata->smallmessage); + // If the message size is too big make it shorter. + if (core_text::strlen($message) >= $maxmsgsize) { // Cut the message to the maximum possible size. -4 for the the ending 3 dots (...). - $message = substr($message, 0 , $maxmsgsize - 4); + $message = core_text::substr($message, 0 , $maxmsgsize - 4); // We need to check when the message is "escaped" then the message is not too long. - $encodedmsgsize = strlen(json_encode($message)); + $encodedmsgsize = core_text::strlen(json_encode($message)); if ($encodedmsgsize > $maxmsgsize) { - $totalescapedchar = $encodedmsgsize - strlen($message); - // Cut the message to the maximum possible size (taking the escaped character in account) - $message = substr($message, 0 , $maxmsgsize - 4 - $totalescapedchar); + $totalescapedchar = $encodedmsgsize - core_text::strlen($message); + // Cut the message to the maximum possible size (taking the escaped character in account). + $message = core_text::substr($message, 0 , $maxmsgsize - 4 - $totalescapedchar); } $message = $message . '...'; } - // We are sending to message to all devices - $airnotifiermanager = new airnotifier_manager(); - $devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifierappname, $eventdata->userto->id, true); + // We are sending to message to all devices. + $airnotifiermanager = new message_airnotifier_manager(); + $devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifiermobileappname, $eventdata->userto->id); foreach ($devicetokens as $devicetoken) { - // Sending the message to the device + if (!$devicetoken->enable) { + continue; + } + + // Sending the message to the device. $serverurl = $CFG->airnotifierurl . ':' . $CFG->airnotifierport . '/notification/'; $header = array('Accept: application/json', 'X-AN-APP-NAME: ' . $CFG->airnotifierappname, 'X-AN-APP-KEY: ' . $CFG->airnotifieraccesskey); $curl = new curl; $curl->setHeader($header); - $params = array('alert' => $message, - 'date' => $eventdata->timecreated, - 'urlparams' => json_encode($eventdata->urlparams), - 'type' => $eventdata->component . '_' . $eventdata->name, - 'userfrom' => fullname($eventdata->userfrom), - 'id' => $eventdata->savedmessageid, - 'token' => $devicetoken->devicenotificationtoken); + $params = array( + 'alert' => $message, + 'date' => $eventdata->timecreated, + 'site' => $siteid, + 'type' => $eventdata->component . '_' . $eventdata->name, + 'userfrom' => fullname($eventdata->userfrom), + 'token' => $devicetoken->pushid); $resp = $curl->post($serverurl, $params); } @@ -105,7 +123,7 @@ class message_output_airnotifier extends message_output { * * @param array $preferences An array of user preferences */ - function config_form($preferences) { + public function config_form($preferences) { global $CFG, $OUTPUT, $USER, $PAGE; if (!$this->is_system_configured()) { @@ -114,8 +132,8 @@ class message_output_airnotifier extends message_output { $PAGE->requires->css('/message/output/airnotifier/style.css'); - $airnotifiermanager = new airnotifier_manager(); - $devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifierappname, $USER->id); + $airnotifiermanager = new message_airnotifier_manager(); + $devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifiermobileappname, $USER->id); if (!empty($devicetokens)) { $output = ''; @@ -131,23 +149,19 @@ class message_output_airnotifier extends message_output { } $hideshowicon = $OUTPUT->pix_icon($hideshowiconname, get_string('showhide', 'message_airnotifier')); - $deleteicon = $OUTPUT->pix_icon('t/delete', get_string('deletedevice', 'message_airnotifier')); - $devicename = empty($devicetoken->devicename) ? get_string('unknowndevice', 'message_airnotifier') : s($devicetoken->devicename); + $name = "{$devicetoken->name} {$devicetoken->model} {$devicetoken->platform} {$devicetoken->version}"; $hideurl = new moodle_url('message/output/airnotifier/action.php', array('hide' => !$devicetoken->enable, 'deviceid' => $devicetoken->id, 'sesskey' => sesskey())); - $deleteurl = new moodle_url('message/output/airnotifier/action.php', - array('delete' => true, 'deviceid' => $devicetoken->id, - 'sesskey' => sesskey())); - $output .= html_writer::start_tag('li', array('id' => $devicetoken->id, 'class' => 'airnotifierdevice ' . $dimmed)) . "\n"; - $output .= html_writer::label($devicename, 'deviceid-' . $devicetoken->id, array('class' => 'devicelabel ')) . ' ' . - html_writer::link($hideurl, $hideshowicon, array('class' => 'hidedevice', 'alt' => 'show/hide')) . '' . - html_writer::link($deleteurl, $deleteicon, array('class' => 'deletedevice', 'alt' => 'delete')) . "\n"; + $output .= html_writer::start_tag('li', array('id' => $devicetoken->id, + 'class' => 'airnotifierdevice ' . $dimmed)) . "\n"; + $output .= html_writer::label($name, 'deviceid-' . $devicetoken->id, array('class' => 'devicelabel ')) . ' ' . + html_writer::link($hideurl, $hideshowicon, array('class' => 'hidedevice', 'alt' => 'show/hide')) . "\n"; $output .= html_writer::end_tag('li') . "\n"; } - // Include the AJAX script to automatically trigger the action + // Include the AJAX script to automatically trigger the action. $airnotifiermanager->include_device_ajax(); $output = html_writer::tag('ul', $output, array('id' => 'airnotifierdevices')); @@ -164,10 +178,8 @@ class message_output_airnotifier extends message_output { * @param stdClass $form preferences form class * @param array $preferences preferences array */ - function process_form($form, &$preferences) { - if (isset($form->airnotifier_devicetoken) && !empty($form->airnotifier_devicetoken)) { - $preferences['message_processor_airnotifier_devicetoken'] = $form->airnotifier_devicetoken; - } + public function process_form($form, &$preferences) { + return true; } /** @@ -176,20 +188,17 @@ class message_output_airnotifier extends message_output { * @param array $preferences preferences array * @param int $userid the user id */ - function load_data(&$preferences, $userid) { - $preferences->airnotifier_devicetoken = - get_user_preferences('message_processor_airnotifier_devicetoken', '', $userid); + public function load_data(&$preferences, $userid) { + return true; } /** * Tests whether the airnotifier settings have been configured * @return boolean true if airnotifier is configured */ - function is_system_configured() { - global $CFG; - return (!empty($CFG->airnotifierurl) && !empty($CFG->airnotifierport) && - !empty($CFG->airnotifieraccesskey) && !empty($CFG->airnotifierdeviceaccesskey) && - !empty($CFG->airnotifierappname)); + public function is_system_configured() { + $airnotifiermanager = new message_airnotifier_manager(); + return $airnotifiermanager->is_system_configured(); } } diff --git a/message/output/airnotifier/requestaccesskey.php b/message/output/airnotifier/requestaccesskey.php new file mode 100755 index 00000000000..96cf544a688 --- /dev/null +++ b/message/output/airnotifier/requestaccesskey.php @@ -0,0 +1,77 @@ +. + +/** + * Request access key to AirNotifier + * + * @package message_airnotifier + * @copyright 2012 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../../../config.php'); +require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php'); + +define('AIRNOTIFIER_PUBLICURL', 'http://messages.moodle.net'); + +$PAGE->set_url(new moodle_url('/message/output/airnotifier/requestaccesskey.php')); +$PAGE->set_context(context_system::instance()); + +require_login(); +require_capability('moodle/site:config', context_system::instance()); + +$strheading = get_string('requestaccesskey', 'message_airnotifier'); +$PAGE->navbar->add(get_string('administrationsite')); +$PAGE->navbar->add(get_string('plugins', 'admin')); +$PAGE->navbar->add(get_string('messageoutputs', 'message')); +$returl = new moodle_url('/admin/settings.php', array('section' => 'messagesettingairnotifier')); +$PAGE->navbar->add(get_string('pluginname', 'message_airnotifier'), $returl); +$PAGE->navbar->add($strheading); + +$PAGE->set_heading($strheading); +$PAGE->set_title($strheading); + +$msg = ""; + +// If we are requesting a key to the official message system, verify first that this site is registered. +// This check is also done in Airnotifier. +if (strpos($CFG->airnotifierurl, AIRNOTIFIER_PUBLICURL) !== false ) { + $registrationmanager = new registration_manager(); + if (!$registrationmanager->get_registeredhub(HUB_MOODLEORGHUBURL)) { + $msg = get_string('sitemustberegistered', 'message_airnotifier'); + $msg .= $OUTPUT->continue_button($returl); + + echo $OUTPUT->header(); + echo $OUTPUT->box($msg, 'generalbox'); + echo $OUTPUT->footer(); + die; + } +} + +$manager = new message_airnotifier_manager(); + +if ($key = $manager->request_accesskey()) { + set_config('airnotifieraccesskey', $key); + $msg = get_string('keyretrievedsuccessfully', 'message_airnotifier'); +} else { + $msg = get_string('errorretrievingkey', 'message_airnotifier'); +} + +$msg .= $OUTPUT->continue_button($returl); + +echo $OUTPUT->header(); +echo $OUTPUT->box($msg, 'generalbox '); +echo $OUTPUT->footer(); diff --git a/message/output/airnotifier/rest.php b/message/output/airnotifier/rest.php index 982830648f9..9a981f8951b 100755 --- a/message/output/airnotifier/rest.php +++ b/message/output/airnotifier/rest.php @@ -1,5 +1,4 @@ dirroot.'/message/output/airnotifier/lib.php'); // Initialise ALL the incoming parameters here, up front. -$field = optional_param('field', '', PARAM_ALPHA); $id = required_param('id', PARAM_INT); -$pageaction = optional_param('action', '', PARAM_ALPHA); // Used to simulate a DELETE command +$enable = required_param('enable', PARAM_BOOL); + +require_login(); +require_sesskey(); $usercontext = context_user::instance($USER->id); $PAGE->set_url('/message/output/airnotifier/rest.php'); $PAGE->set_context($usercontext); -require_login(); -require_sesskey(); -echo $OUTPUT->header(); // send headers +require_capability('message/airnotifier:managedevice', $usercontext); -// OK, now let's process the parameters and do stuff -// MDL-10221 the DELETE method is not allowed on some web servers, so we simulate it with the action URL param -$requestmethod = $_SERVER['REQUEST_METHOD']; -if ($pageaction == 'DELETE') { - $requestmethod = 'DELETE'; -} +echo $OUTPUT->header(); -$device = $DB->get_record('airnotifier_user_devices', array('id' => $id), '*', MUST_EXIST); +$device = $DB->get_record('message_airnotifier_devices', array('id' => $id), '*', MUST_EXIST); -$airnotifiermanager = new airnotifier_manager(); +$device->enable = required_param('enable', PARAM_BOOL); +$DB->update_record('message_airnotifier_devices', $device); -switch($requestmethod) { - case 'POST': - switch ($field) { - case 'enable': - require_capability('message/airnotifier:managedevice', $usercontext); - $device->enable = required_param('enable', PARAM_BOOL); - $DB->update_record('airnotifier_user_devices', $device); - break; - } - break; - - case 'DELETE': - require_capability('message/airnotifier:managedevice', $usercontext); - $DB->delete_records('airnotifier_user_devices', array('id' => $id)); - break; -} diff --git a/message/output/airnotifier/settings.php b/message/output/airnotifier/settings.php index f9a8c0191d5..977a17be2c1 100755 --- a/message/output/airnotifier/settings.php +++ b/message/output/airnotifier/settings.php @@ -1,5 +1,4 @@ fulltree) { - //TODO: It will be better for these settings to be automatically retrieved by web service from moodle.org when enabling mobile. - // The processor should be enabled by the same enable mobile setting. + // The processor should be enabled by the same enable mobile setting. $settings->add(new admin_setting_configtext('airnotifierurl', get_string('airnotifierurl', 'message_airnotifier'), - get_string('configairnotifierurl', 'message_airnotifier'), 'http://notify.moodle.net', PARAM_URL)); + get_string('configairnotifierurl', 'message_airnotifier'), 'http://messages.moodle.net', PARAM_URL)); $settings->add(new admin_setting_configtext('airnotifierport', get_string('airnotifierport', 'message_airnotifier'), - get_string('configairnotifierport', 'message_airnotifier'), '8801', PARAM_INT)); - $settings->add(new admin_setting_configtext('airnotifieraccesskey', - get_string('airnotifieraccesskey', 'message_airnotifier'), - get_string('configairnotifieraccesskey', 'message_airnotifier'), '34220428981805c610cacc22aa6635fb', PARAM_ALPHANUMEXT)); - $settings->add(new admin_setting_configtext('airnotifierdeviceaccesskey', - get_string('airnotifierdeviceaccesskey', 'message_airnotifier'), - get_string('configairnotifierdeviceaccesskey', 'message_airnotifier'), 'e6b15c1ac0606980c46f87c476c9f28e', PARAM_ALPHANUMEXT)); + get_string('configairnotifierport', 'message_airnotifier'), '80', PARAM_INT)); + $settings->add(new admin_setting_configtext('airnotifiermobileappname', + get_string('airnotifiermobileappname', 'message_airnotifier'), + get_string('configairnotifiermobileappname', 'message_airnotifier'), 'com.moodle.moodlemobile', PARAM_TEXT)); $settings->add(new admin_setting_configtext('airnotifierappname', get_string('airnotifierappname', 'message_airnotifier'), - get_string('configairnotifierappname', 'message_airnotifier'), 'moodlehtml5app', PARAM_TEXT)); + get_string('configairnotifierappname', 'message_airnotifier'), 'commoodlemoodlemobile', PARAM_TEXT)); + $settings->add(new admin_setting_configtext('airnotifieraccesskey', + get_string('airnotifieraccesskey', 'message_airnotifier'), + get_string('configairnotifieraccesskey', 'message_airnotifier'), '', PARAM_ALPHANUMEXT)); + + $url = new moodle_url('/message/output/airnotifier/requestaccesskey.php'); + $link = html_writer::link($url, get_string('requestaccesskey', 'message_airnotifier')); + $settings->add(new admin_setting_heading('requestaccesskey', '', $link)); } diff --git a/message/output/airnotifier/style.css b/message/output/airnotifier/style.css index cb030449778..46b41d16a33 100755 --- a/message/output/airnotifier/style.css +++ b/message/output/airnotifier/style.css @@ -19,7 +19,7 @@ package message_airnotifier category css - copyright 2012 Jerome Mouneyrac + copyright 2012/2014 Jerome Mouneyrac / Juan Leyva license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/message/output/airnotifier/version.php b/message/output/airnotifier/version.php index 64545d1a2af..ef1b91cc05a 100755 --- a/message/output/airnotifier/version.php +++ b/message/output/airnotifier/version.php @@ -1,5 +1,4 @@ version = 2012070500.05; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2012110101.01; // Requires this Moodle version -$plugin->component = 'message_airnotifier'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2014012800; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2013111800; // Requires this Moodle version. +$plugin->component = 'message_airnotifier'; // Full name of the plugin (used for diagnostics). diff --git a/message/output/airnotifier/yui/toolboxes/toolboxes.js b/message/output/airnotifier/yui/toolboxes/toolboxes.js index 8a6e824974c..a3650da9aba 100755 --- a/message/output/airnotifier/yui/toolboxes/toolboxes.js +++ b/message/output/airnotifier/yui/toolboxes/toolboxes.js @@ -3,7 +3,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { 'pix':"i/loading_small", 'component':'moodle' }; - // The CSS selectors we use + // The CSS selectors we use. var CSS = { AIRNOTIFIERCONTENT : 'fieldset#messageprocessor_airnotifier', HIDEDEVICE : 'a.hidedevice', @@ -36,14 +36,13 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { */ replace_button : function(toolboxtarget, selector, callback, cursor) { if (!cursor) { - // Set the default cursor type to pointer to match the - // anchor + // Set the default cursor type to pointer to match the anchor. cursor = 'pointer'; } var button = Y.one(toolboxtarget).all(selector) .setStyle('cursor', cursor); - // on isn't chainable and will return an event + // On isn't chainable and will return an event. button.on('click', callback, this); return button; @@ -70,10 +69,9 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { value = 0; } - // Change the UI + // Change the UI. element.toggleClass(toggle_class); - // We need to toggle dimming on the description too - // element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT); + // We need to toggle dimming on the description too element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT);. var newstring = M.util.get_string(status, 'moodle'); hideicon.setAttrs({ 'alt' : newstring, @@ -81,7 +79,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { 'src' : M.util.image_url('t/' + status) }); button.set('title', newstring); - button.set('className', 'editing_'+status); + button.set('className', 'editing_' + status); return value; }, @@ -98,7 +96,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { if (!data) { data = {}; } - // Handle any variables which we must pass back through to + // Handle any variables which we must pass back through to. var pageparams = this.get('config').pageparams; for (varname in pageparams) { data[varname] = pageparams[varname]; @@ -108,7 +106,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { var uri = M.cfg.wwwroot + this.get('ajaxurl'); - // Define the configuration to send with the request + // Define the configuration to send with the request. var responsetext = []; var config = { method: 'POST', @@ -138,7 +136,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { sync: true } - // Apply optional config + // Apply optional config. if (optionalconfig) { for (varname in optionalconfig) { config[varname] = optionalconfig[varname]; @@ -149,7 +147,7 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { statusspinner.show(); } - // Send the request + // Send the request. Y.io(uri, config); return responsetext; }, @@ -205,31 +203,31 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { Y.all(baseselector).each(this._setup_for_device, this); }, _setup_for_device : function(toolboxtarget) { - // Delete + // Delete. this.replace_button(toolboxtarget, CSS.DELETEDEVICE, this.delete_device); - // Show/Hide + // Show/Hide. var showhide = this.replace_button(toolboxtarget, CSS.HIDEDEVICE, this.toggle_hide_device); }, delete_device : function(e) { - // Prevent the default button action + // Prevent the default button action. e.preventDefault(); - // Get the element we're working on + // Get the element we're working on. var element = e.target.ancestor(CSS.DEVICELI); var confirmstring = ''; var plugindata = { - name : element.one('*').getHTML() //get the label + name : element.one('*').getHTML() // Get the label. } confirmstring = M.util.get_string('deletecheckdevicename', 'message_airnotifier', plugindata); - // Confirm element removal + // Confirm element removal. if (!confirm(confirmstring)) { return false; } - // Actually remove the element + // Actually remove the element. element.remove(); var data = { 'class' : 'device', @@ -239,17 +237,17 @@ YUI.add('moodle-message_airnotifier-toolboxes', function(Y) { this.send_request(data); }, toggle_hide_device : function(e) { - // Prevent the default button action + // Prevent the default button action. e.preventDefault(); - // Get the element we're working on + // Get the element we're working on. var element = e.target.ancestor(CSS.DEVICELI); var button = e.target.ancestor('a', true); var value = this.toggle_hide_device_ui(button); - // Send the request + // Send the request. var data = { 'field' : 'enable', 'enable' : value,