diff --git a/lib/db/install.xml b/lib/db/install.xml
index b29a3f84417..ff92a464eaa 100644
--- a/lib/db/install.xml
+++ b/lib/db/install.xml
@@ -2535,6 +2535,7 @@
+
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index ea198d8cb3e..fc8ba43a926 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -1451,5 +1451,18 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2016030103.00);
}
+ if ($oldversion < 2016030400.01) {
+ // Add the new services field.
+ $table = new xmldb_table('external_functions');
+ $field = new xmldb_field('services', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'capabilities');
+
+ // Conditionally launch add field services.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2016030400.01);
+ }
+
return true;
}
diff --git a/lib/upgradelib.php b/lib/upgradelib.php
index 4f96d38b370..b3c92a20fe7 100644
--- a/lib/upgradelib.php
+++ b/lib/upgradelib.php
@@ -1080,6 +1080,28 @@ function external_update_descriptions($component) {
$dbfunction->capabilities = $functioncapabilities;
$update = true;
}
+
+ if (isset($function['services']) and is_array($function['services'])) {
+ sort($function['services']);
+ $functionservices = implode(',', $function['services']);
+ } else {
+ // Force null values in the DB.
+ $functionservices = null;
+ }
+
+ if ($dbfunction->services != $functionservices) {
+ // Now, we need to check if services were removed, in that case we need to remove the function from them.
+ $servicesremoved = array_diff(explode(",", $dbfunction->services), explode(",", $functionservices));
+ foreach ($servicesremoved as $removedshortname) {
+ if ($externalserviceid = $DB->get_field('external_services', 'id', array("shortname" => $removedshortname))) {
+ $DB->delete_records('external_services_functions', array('functionname' => $dbfunction->name,
+ 'externalserviceid' => $externalserviceid));
+ }
+ }
+
+ $dbfunction->services = $functionservices;
+ $update = true;
+ }
if ($update) {
$DB->update_record('external_functions', $dbfunction);
}
@@ -1092,6 +1114,15 @@ function external_update_descriptions($component) {
$dbfunction->classpath = empty($function['classpath']) ? null : $function['classpath'];
$dbfunction->component = $component;
$dbfunction->capabilities = array_key_exists('capabilities', $function)?$function['capabilities']:'';
+
+ if (isset($function['services']) and is_array($function['services'])) {
+ sort($function['services']);
+ $dbfunction->services = implode(',', $function['services']);
+ } else {
+ // Force null values in the DB.
+ $dbfunction->services = null;
+ }
+
$dbfunction->id = $DB->insert_record('external_functions', $dbfunction);
}
unset($functions);
@@ -1200,6 +1231,52 @@ function external_update_descriptions($component) {
}
}
+/**
+ * Allow plugins to add external functions to other plugins or core services.
+ * This function is executed just after all the plugins have been updated.
+ */
+function external_update_services() {
+ global $DB;
+
+ // Look for external functions that want to be added in existing services.
+ $functions = $DB->get_records_select('external_functions', 'services IS NOT NULL');
+
+ $servicescache = array();
+ foreach ($functions as $function) {
+ // Prevent edge cases.
+ if (empty($function->services)) {
+ continue;
+ }
+ $services = explode(',', $function->services);
+
+ foreach ($services as $serviceshortname) {
+ // Get the service id by shortname.
+ if (!empty($servicescache[$serviceshortname])) {
+ $serviceid = $servicescache[$serviceshortname];
+ } else if ($service = $DB->get_record('external_services', array('shortname' => $serviceshortname))) {
+ // If the component is empty, it means that is not a built-in service.
+ // We don't allow functions to inject themselves in services created by an user in Moodle.
+ if (empty($service->component)) {
+ continue;
+ }
+ $serviceid = $service->id;
+ $servicescache[$serviceshortname] = $serviceid;
+ } else {
+ // Service not found.
+ continue;
+ }
+ // Finally add the function to the service.
+ $newf = new stdClass();
+ $newf->externalserviceid = $serviceid;
+ $newf->functionname = $function->name;
+
+ if (!$DB->record_exists('external_services_functions', (array)$newf)) {
+ $DB->insert_record('external_services_functions', $newf);
+ }
+ }
+ }
+}
+
/**
* upgrade logging functions
*/
@@ -1657,6 +1734,9 @@ function upgrade_noncore($verbose) {
foreach ($plugintypes as $type=>$location) {
upgrade_plugins($type, 'print_upgrade_part_start', 'print_upgrade_part_end', $verbose);
}
+ // Upgrade services. This function gives plugins a chance to add functions to existing core or non-core services.
+ external_update_services();
+
// Update cache definitions. Involves scanning each plugin for any changes.
cache_helper::update_definitions();
// Mark the site as upgraded.
diff --git a/version.php b/version.php
index 725a10533b1..90fc4b020fa 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2016030400.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2016030400.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.