MDL-44342 airnotifier: Initial work, first version of the plugin

This commit is contained in:
mouneyrac
2014-04-07 12:13:07 +02:00
committed by Juan Leyva
parent 1a727e121e
commit 08ca1a5bfd
15 changed files with 1278 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Capability definitions for airnotifier.
*
* @package message_airnotifier
* @category access
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'message/airnotifier:managedevice' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_USER,
'archetypes' => array(
'user' => CAP_ALLOW
)
)
);
+38
View File
@@ -0,0 +1,38 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Airnotifier message processor installation code
*
* @package message_airnotifier
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Install the Airnotifier message processor
*/
function xmldb_message_airnotifier_install() {
global $DB;
$result = true;
$provider = new stdClass();
$provider->name = 'airnotifier';
$DB->insert_record('message_processors', $provider);
return $result;
}
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="message/output/airnotifier/db" VERSION="20120706" COMMENT="XMLDB file for airnotifier Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="airnotifier_user_devices" COMMENT="Mobile devices associated to users">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="appname"/>
<FIELD NAME="appname" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the app: mymoodle, ..." PREVIOUS="id" NEXT="devicename"/>
<FIELD NAME="devicename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="For example Jerome's iPhone" PREVIOUS="appname" NEXT="devicetype"/>
<FIELD NAME="devicetype" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="For example iPhone 4S, Google Nexus..." PREVIOUS="devicename" NEXT="deviceos"/>
<FIELD NAME="deviceos" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="For example ios, android..." PREVIOUS="devicetype" NEXT="deviceosversion"/>
<FIELD NAME="deviceosversion" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="5.1, 2.3.3..." PREVIOUS="deviceos" NEXT="devicebrand"/>
<FIELD NAME="devicebrand" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="Apple, Samsung..." PREVIOUS="deviceosversion" NEXT="devicenotificationtoken"/>
<FIELD NAME="devicenotificationtoken" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Apple give one token per device/app to be able to send push notification to the device." PREVIOUS="devicebrand" NEXT="deviceuid"/>
<FIELD NAME="deviceuid" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="A unique ID to identify the device. Freedom for the client to send whatever he wants and the plugin to manage them in concordance." PREVIOUS="devicenotificationtoken" NEXT="userid"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="the user owning the device" PREVIOUS="deviceuid" NEXT="enable"/>
<FIELD NAME="enable" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="the user can disable on of his/her device." PREVIOUS="userid"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+44
View File
@@ -0,0 +1,44 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Airnotifier external functions and service definitions.
*
* @package message_airnotifier
* @category webservice
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$functions = array(
'message_airnotifier_add_user_device' => array(
'classname' => 'message_airnotifier_external',
'methodname' => 'add_user_device',
'classpath' => 'message/output/airnotifier/externallib.php',
'description' => 'Add device to user device list',
'type' => 'write',
),
'message_airnotifier_get_access_key' => array(
'classname' => 'message_airnotifier_external',
'methodname' => 'get_access_key',
'classpath' => 'message/output/airnotifier/externallib.php',
'description' => 'Get the mobile device access key with specified permissions',
'type' => 'read',
),
);
+68
View File
@@ -0,0 +1,68 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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;
}
+150
View File
@@ -0,0 +1,150 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* external API for airnotifier web services
*
* @package message_airnotifier
* @category external
* @copyright 2012 Jerome Mouneyrac <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.4
*/
class message_airnotifier_external extends external_api {
/**
* Returns description of add_user_device() parameters
*
* @return external_function_parameters
* @since Moodle 2.4
*/
public static function add_user_device_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'
)
));
}
/**
* Add a device to the user device list
*
* @param array $device
* @return int device id
* @since Moodle 2.4
*/
public static function add_user_device($device) {
global $USER, $CFG;
$params = self::validate_parameters(self::add_user_device_parameters(),
array('device'=>$device));
// 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);
$device['userid'] = $USER->id;
require_once($CFG->dirroot . "/message/output/airnotifier/lib.php");
$airnotifiermanager = new airnotifier_manager();
$device['id'] = $airnotifiermanager->add_user_device($device);
return $device['id'];
}
/**
* 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');
}
/**
* 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()
)
));
}
/**
* 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;
$params = self::validate_parameters(self::get_access_key_parameters(),
array('permissions'=>$permissions));
// 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;
}
}
// 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;
}
/**
* Returns description of add_user_device() result value
*
* @return external_single_structure
* @since Moodle 2.4
*/
public static function get_access_key_returns() {
return new external_value( PARAM_ALPHANUMEXT, 'access key');
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'message_airnotifier', language 'en'
*
* @package message_airnotifier
* @copyright 2012 Jerome mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['airnotifieraccesskey'] = 'Airnotifier access key';
$string['airnotifierappname'] = 'Airnotifier app name';
$string['airnotifierdeviceaccesskey'] = 'Airnotifier device access key';
$string['airnotifierport'] = 'Airnotifier port';
$string['airnotifierurl'] = 'Airnotifier URL';
$string['configairnotifierurl'] = 'The server url to connect to to send push notifications.';
$string['configairnotifierport'] = 'The port to use when connecting to the airnotifier server.';
$string['configairnotifieraccesskey'] = 'The access key to use when connecting to the airnotifier server.';
$string['configairnotifierappname'] = 'The app name where Airnotifier will send notification.';
$string['configairnotifierdeviceaccesskey'] = 'The access key used by mobile devices when connecting to the airnotifier server.';
$string['deletecheckdevicename'] = 'Delete your device: {$a->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['devicetoken'] = 'Device token';
$string['nodevices'] = 'No registered devices. Devices are automatically registered when 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['showhide'] = 'Enable/disable the device.';
$string['unknowndevice'] = 'Unknown device';
+139
View File
@@ -0,0 +1,139 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Airnotifier related functions
*
* @package message_airnotifier
* @category external
* @copyright 2012 Jerome Mouneyrac <[email protected]>
* @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);
}
}
?>
+195
View File
@@ -0,0 +1,195 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
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)
*
* @package message_airnotifier
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class message_output_airnotifier extends message_output {
/**
* Processes the message and sends a notification via airnotifier
*
* @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) {
global $CFG;
if (!empty($CFG->noemailever)) {
// 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) {
return true;
}
// 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));
// 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) {
// Cut the message to the maximum possible size. -4 for the the ending 3 dots (...).
$message = 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));
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);
}
$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);
foreach ($devicetokens as $devicetoken) {
// 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);
$resp = $curl->post($serverurl, $params);
}
return true;
}
/**
* Creates necessary fields in the messaging config form.
*
* @param array $preferences An array of user preferences
*/
function config_form($preferences) {
global $CFG, $OUTPUT, $USER, $PAGE;
if (!$this->is_system_configured()) {
return get_string('notconfigured', 'message_airnotifier');
} else {
$PAGE->requires->css('/message/output/airnotifier/style.css');
$airnotifiermanager = new airnotifier_manager();
$devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifierappname, $USER->id);
if (!empty($devicetokens)) {
$output = '';
foreach ($devicetokens as $devicetoken) {
if ($devicetoken->enable) {
$hideshowiconname = 't/hide';
$dimmed = '';
} else {
$hideshowiconname = 't/show';
$dimmed = 'dimmed_text';
}
$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);
$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::end_tag('li') . "\n";
}
// Include the AJAX script to automatically trigger the action
$airnotifiermanager->include_device_ajax();
$output = html_writer::tag('ul', $output, array('id' => 'airnotifierdevices'));
} else {
$output = get_string('nodevices', 'message_airnotifier');
}
return $output;
}
}
/**
* Parses the submitted form data and saves it into preferences array.
*
* @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;
}
}
/**
* Loads the config data from database to put on the form during initial form display
*
* @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);
}
/**
* 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));
}
}
+72
View File
@@ -0,0 +1,72 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provide interface for AJAX device actions
*
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package message_airnotifier
*/
if (!defined('AJAX_SCRIPT')) {
define('AJAX_SCRIPT', true);
}
require_once(dirname(__FILE__) . '/../../../config.php');
require_once($CFG->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
$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
// 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';
}
$device = $DB->get_record('airnotifier_user_devices', array('id' => $id), '*', MUST_EXIST);
$airnotifiermanager = new airnotifier_manager();
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;
}
+45
View File
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Airnotifier configuration page
*
* @package message_airnotifier
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->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.
$settings->add(new admin_setting_configtext('airnotifierurl',
get_string('airnotifierurl', 'message_airnotifier'),
get_string('configairnotifierurl', 'message_airnotifier'), 'http://notify.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));
$settings->add(new admin_setting_configtext('airnotifierappname',
get_string('airnotifierappname', 'message_airnotifier'),
get_string('configairnotifierappname', 'message_airnotifier'), 'moodlehtml5app', PARAM_TEXT));
}
+29
View File
@@ -0,0 +1,29 @@
/**
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
Airnotifier (message output plugin) CSS
package message_airnotifier
category css
copyright 2012 Jerome Mouneyrac
license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
ul#airnotifierdevices {
list-style: none;
margin: 0em;
}
+86
View File
@@ -0,0 +1,86 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* External airnotifier functions unit tests
*
* @package message_airnotifier
* @category external
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* External airnotifier functions unit tests
*
* @package message_airnotifier
* @category external
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class message_airnotifier_external_testcase extends externallib_testcase {
/**
* Tests set up
*/
protected function setUp() {
global $CFG;
require_once($CFG->dirroot . '/lib/externallib.php');
require_once($CFG->dirroot . '/webservice/externallib.php');
}
/**
* Test add_user_device
*/
public function test_add_user_device() {
global $DB, $USER;
$this->resetAfterTest(true);
$user = self::getDataGenerator()->create_user();
self::setUser($user);
$device = array();
$device['appname'] = 'mymoodle';
$device['devicename'] = 'Jerome\'s Android';
$device['devicetype'] = 'galaxy nexus';
$device['deviceos'] = 'android';
$device['deviceosversion'] = '4.0.3';
$device['devicebrand'] = 'samsung';
$device['devicenotificationtoken'] = 'jhg576576sesgy98sd7g87sdg697sfg576df';
$device['deviceuid'] = 'is87fs64g2vuf84g378gbh378ehg98h875';
$deviceid = message_airnotifier_external::add_user_device($device);
$devicedb = $DB->get_record('user_devices', array('id' => $deviceid));
$this->assertEquals($devicedb->devicename, $device['devicename']);
$this->assertEquals($devicedb->devicetype, $device['devicetype']);
$this->assertEquals($devicedb->deviceos, $device['deviceos']);
$this->assertEquals($devicedb->deviceosversion, $device['deviceosversion']);
$this->assertEquals($devicedb->devicebrand, $device['devicebrand']);
$this->assertEquals($devicedb->devicenotificationtoken, $device['devicenotificationtoken']);
$this->assertEquals($devicedb->deviceuid, $device['deviceuid']);
$this->assertEquals($devicedb->userid, $USER->id);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Airnotifier message processor version information
*
* @package message_airnotifier
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->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)
+277
View File
@@ -0,0 +1,277 @@
YUI.add('moodle-message_airnotifier-toolboxes', function(Y) {
WAITICON = {
'pix':"i/loading_small",
'component':'moodle'
};
// The CSS selectors we use
var CSS = {
AIRNOTIFIERCONTENT : 'fieldset#messageprocessor_airnotifier',
HIDEDEVICE : 'a.hidedevice',
DELETEDEVICE : 'a.deletedevice',
DEVICELI : 'li.airnotifierdevice',
DIMCLASS : 'dimmed',
DIMMEDTEXT : 'dimmed_text',
DEVICEIDPREFIX : 'deviceid-'
};
/**
* The toolbox classes
*
* TOOLBOX is a generic class which should never be directly instantiated
* DEVICETOOLBOX is a class extending TOOLBOX containing code specific to devices
*/
var TOOLBOX = function() {
TOOLBOX.superclass.constructor.apply(this, arguments);
}
Y.extend(TOOLBOX, Y.Base, {
/**
* Replace the button click at the selector with the specified
* callback
*
* @param toolboxtarget The selector of the working area
* @param selector The 'button' to replace
* @param callback The callback to apply
* @param cursor An optional cursor style to apply
*/
replace_button : function(toolboxtarget, selector, callback, cursor) {
if (!cursor) {
// 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
button.on('click', callback, this);
return button;
},
/**
* Toggle the visibility and availability for the specified
* device show/hide button
*/
toggle_hide_device_ui : function(button) {
var element = button.ancestor(CSS.DEVICELI);
var hideicon = button.one('img');
var dimarea;
var toggle_class = CSS.DIMMEDTEXT;
var status = '';
var value;
if (element.hasClass(toggle_class)) {
status = 'hide';
value = 1;
} else {
status = 'show';
value = 0;
}
// Change the UI
element.toggleClass(toggle_class);
// 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,
'title' : newstring,
'src' : M.util.image_url('t/' + status)
});
button.set('title', newstring);
button.set('className', 'editing_'+status);
return value;
},
/**
* Send a request using the REST API
*
* @param data The data to submit
* @param statusspinner (optional) A statusspinner which may contain a section loader
* @param optionalconfig (optional) Any additional configuration to submit
* @return response responseText field from responce
*/
send_request : function(data, statusspinner, optionalconfig) {
// Default data structure
if (!data) {
data = {};
}
// Handle any variables which we must pass back through to
var pageparams = this.get('config').pageparams;
for (varname in pageparams) {
data[varname] = pageparams[varname];
}
data.sesskey = M.cfg.sesskey;
var uri = M.cfg.wwwroot + this.get('ajaxurl');
// Define the configuration to send with the request
var responsetext = [];
var config = {
method: 'POST',
data: data,
on: {
success: function(tid, response) {
try {
responsetext = Y.JSON.parse(response.responseText);
if (responsetext.error) {
new M.core.ajaxException(responsetext);
}
} catch (e) {}
if (statusspinner) {
window.setTimeout(function(e) {
statusspinner.hide();
}, 400);
}
},
failure : function(tid, response) {
if (statusspinner) {
statusspinner.hide();
}
new M.core.ajaxException(response);
}
},
context: this,
sync: true
}
// Apply optional config
if (optionalconfig) {
for (varname in optionalconfig) {
config[varname] = optionalconfig[varname];
}
}
if (statusspinner) {
statusspinner.show();
}
// Send the request
Y.io(uri, config);
return responsetext;
},
/**
* Return the module ID for the specified element
*
* @param element The <li> element to determine a module-id number for
* @return string The module ID
*/
get_element_id : function(element) {
return element.get('id').replace(CSS.DEVICEIDPREFIX, '');
}
},
{
NAME : 'device-toolbox',
ATTRS : {
ajaxurl : {
'value' : 0
},
config : {
'value' : 0
}
}
}
);
var DEVICETOOLBOX = function() {
DEVICETOOLBOX.superclass.constructor.apply(this, arguments);
}
Y.extend(DEVICETOOLBOX, TOOLBOX, {
/**
* Initialize the device toolbox
*
* Updates all span.commands with relevant handlers and other required changes
*/
initializer : function(config) {
this.setup_for_device();
},
/**
* Update any span.commands within the scope of the specified
* selector with AJAX equivelants
*
* @param baseselector The selector to limit scope to
* @return void
*/
setup_for_device : function(baseselector) {
if (!baseselector) {
var baseselector = CSS.AIRNOTIFIERCONTENT;
}
Y.all(baseselector).each(this._setup_for_device, this);
},
_setup_for_device : function(toolboxtarget) {
// Delete
this.replace_button(toolboxtarget, CSS.DELETEDEVICE, this.delete_device);
// Show/Hide
var showhide = this.replace_button(toolboxtarget, CSS.HIDEDEVICE, this.toggle_hide_device);
},
delete_device : function(e) {
// Prevent the default button action
e.preventDefault();
// 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
}
confirmstring = M.util.get_string('deletecheckdevicename', 'message_airnotifier', plugindata);
// Confirm element removal
if (!confirm(confirmstring)) {
return false;
}
// Actually remove the element
element.remove();
var data = {
'class' : 'device',
'action' : 'DELETE',
'id' : this.get_element_id(element)
};
this.send_request(data);
},
toggle_hide_device : function(e) {
// Prevent the default button action
e.preventDefault();
// 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
var data = {
'field' : 'enable',
'enable' : value,
'id' : this.get_element_id(element)
};
var spinner = M.util.add_spinner(Y, element);
this.send_request(data, spinner);
}
}, {
NAME : 'message-device-toolbox',
ATTRS : {
}
});
M.message = M.message || {};
M.message.init_device_toolbox = function(config) {
return new DEVICETOOLBOX(config);
};
},
'@VERSION@', {
requires : ['base', 'node', 'io']
}
);