MDL-49329 admin: Add core_plugin_manager::available_updates() method
authorDavid Mudrák <david@moodle.com>
Tue, 6 Oct 2015 11:46:00 +0000 (13:46 +0200)
committerDavid Mudrák <david@moodle.com>
Thu, 8 Oct 2015 21:32:04 +0000 (23:32 +0200)
The new method is going to be used to support the "Update all plugins"
feature.

lib/classes/plugin_manager.php
lib/tests/fixtures/testable_plugin_manager.php
lib/tests/plugin_manager_test.php

index 02bbedb..0d60610 100644 (file)
@@ -1282,6 +1282,72 @@ class core_plugin_manager {
         return $provider->get_update_info($component, array('minmaturity' => $minmaturity));
     }
 
         return $provider->get_update_info($component, array('minmaturity' => $minmaturity));
     }
 
+    /**
+     * Returns a list of all available updates to be installed.
+     *
+     * This is used when "update all plugins" action is performed at the
+     * administration UI screen.
+     *
+     * Returns array of remote info objects indexed by the plugin
+     * component. If there are multiple updates available (typically a mix of
+     * stable and non-stable ones), we pick the most mature most recent one.
+     *
+     * Plugins without explicit maturity are considered more mature than
+     * release candidates but less mature than explicit stable (this should be
+     * pretty rare case).
+     *
+     * @return array (string)component => (\core\update\info)info
+     */
+    public function available_updates() {
+
+        $updates = array();
+
+        foreach ($this->get_plugins() as $type => $plugins) {
+            foreach ($plugins as $plugin) {
+                $availableupdates = $plugin->available_updates();
+                if (empty($availableupdates)) {
+                    continue;
+                }
+                foreach ($availableupdates as $update) {
+                    if (empty($updates[$plugin->component])) {
+                        $updates[$plugin->component] = $update;
+                        continue;
+                    }
+                    $maturitycurrent = $updates[$plugin->component]->maturity;
+                    if (empty($maturitycurrent)) {
+                        $maturitycurrent = MATURITY_STABLE - 25;
+                    }
+                    $maturityremote = $update->maturity;
+                    if (empty($maturityremote)) {
+                        $maturityremote = MATURITY_STABLE - 25;
+                    }
+                    if ($maturityremote < $maturitycurrent) {
+                        continue;
+                    }
+                    if ($maturityremote > $maturitycurrent) {
+                        $updates[$plugin->component] = $update;
+                        continue;
+                    }
+                    if ($update->version > $updates[$plugin->component]->version) {
+                        $updates[$plugin->component] = $update;
+                        continue;
+                    }
+                }
+            }
+        }
+
+        foreach ($updates as $component => $update) {
+            $remoteinfo = $this->get_remote_plugin_info($component, $update->version, true);
+            if (empty($remoteinfo) or empty($remoteinfo->version)) {
+                unset($updates[$component]);
+            } else {
+                $updates[$component] = $remoteinfo;
+            }
+        }
+
+        return $updates;
+    }
+
     /**
      * Check to see if the given plugin folder can be removed by the web server process.
      *
     /**
      * Check to see if the given plugin folder can be removed by the web server process.
      *
index 1d2b5cd..8e77d35 100644 (file)
@@ -45,6 +45,11 @@ class testable_core_plugin_manager extends core_plugin_manager {
      * singleton instance.
      */
     public function inject_testable_plugininfo($type, $name, \core\plugininfo\base $plugininfo) {
      * singleton instance.
      */
     public function inject_testable_plugininfo($type, $name, \core\plugininfo\base $plugininfo) {
+
+        // Let the parent initialize the ->pluginsinfo tree.
+        parent::get_plugins();
+
+        // Inject the additional plugin info.
         $this->pluginsinfo[$type][$name] = $plugininfo;
     }
 
         $this->pluginsinfo[$type][$name] = $plugininfo;
     }
 
@@ -62,28 +67,36 @@ class testable_core_plugin_manager extends core_plugin_manager {
      *
      * This testable implementation does not actually use
      * {@link \core\update\checker}. Instead, it provides hard-coded list of
      *
      * This testable implementation does not actually use
      * {@link \core\update\checker}. Instead, it provides hard-coded list of
-     * fictional available updates for some standard plugin.
+     * fictional available updates for our foo_bar plugin.
+     *
+     * Note there is a difference in the behaviour as the actual update API
+     * does not return info of lower version than requested. To mock up well,
+     * make sure the injected foo_bar testable plugin info has version lower
+     * than the lowest one returned here.
      *
      * @param string $component
      * @return array|null array of \core\update\info objects or null
      */
     public function load_available_updates_for_plugin($component) {
 
      *
      * @param string $component
      * @return array|null array of \core\update\info objects or null
      */
     public function load_available_updates_for_plugin($component) {
 
-        if ($component === 'mod_forum') {
+        if ($component === 'foo_bar') {
             $updates = array();
 
             $updates[] = new \core\update\info($component, array(
             $updates = array();
 
             $updates[] = new \core\update\info($component, array(
-                'version' => '2002073008',
-                'release' => 'Forum 0.1',
-                'maturity' => MATURITY_ALPHA,
-                'url' => 'https://en.wikipedia.org/wiki/Moodle',
-                'download' => 'https://moodle.org/plugins/pluginversion.php?id=1',
-                'downloadmd5' => md5('I can not think of anything funny to type here'),
+                'version' => '2015093000',
+                'release' => 'Foo bar 15.09.30 beta',
+                'maturity' => MATURITY_BETA,
+            ));
+
+            $updates[] = new \core\update\info($component, array(
+                'version' => '2015100400',
+                'release' => 'Foo bar 15.10.04',
+                'maturity' => MATURITY_STABLE,
             ));
 
             $updates[] = new \core\update\info($component, array(
             ));
 
             $updates[] = new \core\update\info($component, array(
-                'version' => '2999122400',
-                'release' => 'Forum NG',
+                'version' => '2015100500',
+                'release' => 'Foo bar 15.10.05 beta',
                 'maturity' => MATURITY_BETA,
             ));
 
                 'maturity' => MATURITY_BETA,
             ));
 
index c551cb7..ae2b20c 100644 (file)
@@ -291,30 +291,66 @@ class core_plugin_manager_testcase extends advanced_testcase {
     }
 
     public function test_plugin_available_updates() {
     }
 
     public function test_plugin_available_updates() {
-
         $pluginman = testable_core_plugin_manager::instance();
 
         $pluginman = testable_core_plugin_manager::instance();
 
+        $foobar = testable_plugininfo_base::fake_plugin_instance('foo', '/dev/null', 'bar', '/dev/null/fake',
+            'testable_plugininfo_base', $pluginman);
+        $foobar->versiondb = 2015092900;
+        $foobar->versiondisk = 2015092900;
+
         foreach ($pluginman->get_plugins() as $type => $infos) {
         foreach ($pluginman->get_plugins() as $type => $infos) {
-            foreach ($infos as $name => $info) {
-                $updates = $info->available_updates();
-                if ($info->component != 'mod_forum') {
+            foreach ($infos as $name => $plugin) {
+                $updates = $plugin->available_updates();
+                if ($plugin->component != 'foo_bar') {
                     $this->assertNull($updates);
                 } else {
                     $this->assertNull($updates);
                 } else {
-                    $this->assertEquals(1, count($updates));
-                    $update = array_shift($updates);
-                    $this->assertInstanceOf('\core\update\info', $update);
-                    $this->assertEquals('mod_forum', $update->component);
-                    $this->assertEquals('2999122400', $update->version);
+                    $this->assertTrue(is_array($updates));
+                    $this->assertEquals(3, count($updates));
+                    foreach ($updates as $update) {
+                        $this->assertInstanceOf('\core\update\info', $update);
+                        $this->assertEquals($update->component, $plugin->component);
+                        $this->assertTrue($update->version > $plugin->versiondb);
+                    }
                 }
             }
         }
     }
 
                 }
             }
         }
     }
 
-    public function test_some_plugins_updatable() {
+    public function test_some_plugins_updatable_none() {
         $pluginman = testable_core_plugin_manager::instance();
         $pluginman = testable_core_plugin_manager::instance();
+        $this->assertFalse($pluginman->some_plugins_updatable());
+    }
+
+    public function test_some_plugins_updatable_some() {
+        $pluginman = testable_core_plugin_manager::instance();
+
+        $foobar = testable_plugininfo_base::fake_plugin_instance('foo', '/dev/null', 'bar', '/dev/null/fake',
+            'testable_plugininfo_base', $pluginman);
+        $foobar->versiondb = 2015092900;
+        $foobar->versiondisk = 2015092900;
+        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
+
         $this->assertTrue($pluginman->some_plugins_updatable());
     }
 
         $this->assertTrue($pluginman->some_plugins_updatable());
     }
 
+    public function test_available_updates() {
+        $pluginman = testable_core_plugin_manager::instance();
+
+        $foobar = testable_plugininfo_base::fake_plugin_instance('foo', '/dev/null', 'bar', '/dev/null/fake',
+            'testable_plugininfo_base', $pluginman);
+        $foobar->versiondb = 2015092900;
+        $foobar->versiondisk = 2015092900;
+        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
+
+        $updates = $pluginman->available_updates();
+
+        $this->assertTrue(is_array($updates));
+        $this->assertEquals(1, count($updates));
+        $update = $updates['foo_bar'];
+        $this->assertEquals('foo_bar', $update->component);
+        $this->assertEquals(2015100400, $update->version->version);
+    }
+
     public function test_get_remote_plugin_info() {
         $pluginman = testable_core_plugin_manager::instance();
 
     public function test_get_remote_plugin_info() {
         $pluginman = testable_core_plugin_manager::instance();