Merge branch 'MDL-64337-master' of git://github.com/jleyva/moodle

This commit is contained in:
Sara Arjona
2019-03-26 14:55:09 +01:00
5 changed files with 153 additions and 10 deletions
@@ -86,6 +86,7 @@ $string['mobilesettings'] = 'Mobile settings';
$string['offlineuse'] = 'Offline use';
$string['pluginname'] = 'Moodle app tools';
$string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
$string['readingthisemailgettheapp'] = 'Reading this in your e-mail? <a href="{$a}">Download the mobile app and receive notifications on your mobile devices</a>.';
$string['remoteaddons'] = 'Remote add-ons';
$string['selfsignedoruntrustedcertificatewarning'] = 'It seems that the HTTPS certificate is self-signed or not trusted. The mobile app will only work with trusted sites.';
$string['setuplink'] = 'App download page';
+60 -8
View File
@@ -86,6 +86,25 @@ function tool_mobile_create_app_download_url() {
return $downloadurl;
}
/**
* Checks if the given user has a mobile token (has used recently the app).
*
* @param int $userid the user to check
* @return bool true if the user has a token, false otherwise.
*/
function tool_mobile_user_has_token($userid) {
global $DB;
$sql = "SELECT 1
FROM {external_tokens} t, {external_services} s
WHERE t.externalserviceid = s.id
AND s.enabled = 1
AND s.shortname IN ('moodle_mobile_app', 'local_mobile')
AND t.userid = ?";
return $DB->record_exists_sql($sql, [$userid]);
}
/**
* User profile page callback.
*
@@ -97,7 +116,7 @@ function tool_mobile_create_app_download_url() {
* @return void Return if the mobile web services setting is disabled or if not the current user.
*/
function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree, $user, $iscurrentuser) {
global $CFG, $DB;
global $CFG;
if (empty($CFG->enablemobilewebservice)) {
return;
@@ -111,13 +130,7 @@ function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree
return;
}
$sql = "SELECT 1
FROM {external_tokens} t, {external_services} s
WHERE t.externalserviceid = s.id
AND s.enabled = 1
AND s.shortname IN ('moodle_mobile_app', 'local_mobile')
AND t.userid = ?";
$userhastoken = $DB->record_exists_sql($sql, [$user->id]);
$userhastoken = tool_mobile_user_has_token($user->id);
$mobilecategory = new core_user\output\myprofile\category('mobile', get_string('mobileapp', 'tool_mobile'),
'loginactivity');
@@ -147,3 +160,42 @@ function tool_mobile_standard_footer_html() {
}
return $output;
}
/**
* Callback to be able to change a message/notification data per processor.
*
* @param str $procname processor name
* @param stdClass $data message or notification data
*/
function tool_mobile_pre_processor_message_send($procname, $data) {
global $CFG;
if (empty($CFG->enablemobilewebservice)) {
return;
}
if (empty($data->userto)) {
return;
}
// Only hack email.
if ($procname == 'email') {
// Send a message only when there is an HTML version of the email, mobile services are enabled,
// the user receiving the message has not used the app and there is an app download URL set.
if (empty($data->fullmessagehtml)) {
return;
}
if (!$url = tool_mobile_create_app_download_url()) {
return;
}
$userto = is_object($data->userto) ? $data->userto->id : $data->userto;
if (tool_mobile_user_has_token($userto)) {
return;
}
$data->fullmessagehtml .= html_writer::tag('p', get_string('readingthisemailgettheapp', 'tool_mobile', $url->out()));
}
}
+76
View File
@@ -94,4 +94,80 @@ class tool_mobile_api_testcase extends externallib_advanced_testcase {
$this->assertTrue(in_array($issue[0], $expectedissues));
}
}
/**
* Test pre_processor_message_send callback.
*/
public function test_pre_processor_message_send_callback() {
global $DB, $CFG;
require_once($CFG->libdir . '/externallib.php');
$this->preventResetByRollback();
$this->resetAfterTest();
// Enable mobile services and required configuration.
$CFG->enablewebservices = 1;
$CFG->enablemobilewebservice = 1;
$mobileappdownloadpage = 'htt://mobileappdownloadpage';
set_config('setuplink', $mobileappdownloadpage, 'tool_mobile');
$user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
$user2 = $this->getDataGenerator()->create_user();
set_config('allowedemaildomains', 'example.com');
$DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email'");
set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
// Extra content for all types of messages.
$message = new \core\message\message();
$message->courseid = 1;
$message->component = 'moodle';
$message->name = 'instantmessage';
$message->userfrom = $user1;
$message->userto = $user2;
$message->subject = 'message subject 1';
$message->fullmessage = 'message body';
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = '<p>message body</p>';
$message->smallmessage = 'small message';
$message->notification = '0';
$content = array('*' => array('header' => ' test ', 'footer' => ' test '));
$message->set_additional_content('email', $content);
$sink = $this->redirectEmails();
$messageid = message_send($message);
$emails = $sink->get_messages();
$this->assertCount(1, $emails);
$email = reset($emails);
// Check we got the promotion text.
$this->assertContains($mobileappdownloadpage, quoted_printable_decode($email->body));
$sink->clear();
// Disable mobile so we don't get mobile promotions.
$CFG->enablemobilewebservice = 0;
$messageid = message_send($message);
$emails = $sink->get_messages();
$this->assertCount(1, $emails);
$email = reset($emails);
// Check we don't get the promotion text.
$this->assertNotContains($mobileappdownloadpage, quoted_printable_decode($email->body));
$sink->clear();
// Enable mobile again and set current user mobile token so we don't get mobile promotions.
$CFG->enablemobilewebservice = 1;
$user3 = $this->getDataGenerator()->create_user();
$this->setUser($user3);
$service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
$token = external_generate_token_for_current_user($service);
$message->userto = $user3;
$messageid = message_send($message);
$emails = $sink->get_messages();
$this->assertCount(1, $emails);
$email = reset($emails);
// Check we don't get the promotion text.
$this->assertNotContains($mobileappdownloadpage, quoted_printable_decode($email->body));
$sink->clear();
$sink->close();
}
}
+12
View File
@@ -473,9 +473,21 @@ class manager {
* @param array $processorlist the list of processors for a single user.
*/
protected static function call_processors(message $eventdata, array $processorlist) {
// Allow plugins to change the message/notification data before sending it.
$pluginsfunction = get_plugins_with_function('pre_processor_message_send');
foreach ($processorlist as $procname) {
// Let new messaging class add custom content based on the processor.
$proceventdata = ($eventdata instanceof message) ? $eventdata->get_eventobject_for_processor($procname) : $eventdata;
if ($pluginsfunction) {
foreach ($pluginsfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginfunction) {
$pluginfunction($procname, $proceventdata);
}
}
}
$stdproc = new \stdClass();
$stdproc->name = $procname;
$processor = \core_message\api::get_processed_processor_object($stdproc);
+4 -2
View File
@@ -24,6 +24,8 @@ attribute on forms to avoid collisions in forms loaded in AJAX requests.
and get_reduced_timeout(). These allow for timeouts to be increased by a setting in config.php.
* The $draftitemid parameter of file_save_draft_area_files() function now supports the constant IGNORE_FILE_MERGE:
When the parameter is set to that constant, the function won't process file merging, keeping the original state of the file area.
* Introduced new callback for plugin developers '<component>_pre_processor_message_send($procname, $proceventdata)':
This will allow any plugin to manipulate messages or notifications before they are sent by a processor (email, mobile...)
=== 3.6 ===
@@ -639,13 +641,13 @@ the groupid field.
$OUTPUT->download_dataformat_selector() instead.
when building Xpath, or pass the unescaped value when using the named selector.
* Add new file_is_executable(), to consistently check for executables even in Windows (PHP bug #41062).
* Introduced new hooks for plugin developers.
* Introduced new callbacks for plugin developers.
- <component>_pre_course_category_delete($category)
- <component>_pre_course_delete($course)
- <component>_pre_course_module_delete($cm)
- <component>_pre_block_delete($instance)
- <component>_pre_user_delete($user)
These hooks allow developers to use the item in question before it is deleted by core. For example, if your plugin is
These callbacks allow developers to use the item in question before it is deleted by core. For example, if your plugin is
a module (plugins located in the mod folder) called 'xxx' and you wish to interact with the user object before it is
deleted then the function to create would be mod_xxx_pre_user_delete($user) in mod/xxx/lib.php.
* pear::Net::GeoIP has been removed.