If the plugin has been only deployed to the disk without installing into
the database, do not allow going through the uninstallation procedure.
Not only it does not have much sense. But it can also lead to some
tricky situation due to dependencies. Better to block it and wait till
the plugin is either fully installed or removed from the disk.
The get_uninstall_url() method of all subclasses of plugininfo_base
class is now expected to always return moodle_url. Subclasses can use
the new method is_uninstall_allowed() to control the availability of the
'Uninstall' link at the Plugins overview page (previously they would do
it by get_uninstall_url() returning null). By default, URL to a new
general plugin uninstall tool is returned. Unless the plugin type needs
extra steps that can't be handled by plugininfo_xxx::uninstall() method
or xmldb_xxx_uninstall() function, this default URL should satisfy all
plugin types.
The overall logic is implemented in plugin_manager::can_install_plugin()
that respects the plugininfo class decision and vetoes it in certain
cases (typically when plugin or its subplugin is required by some other
plugin).
This patch improves and adds unit tests for the plugin_manager class.
These unit tests cover the existing functionalities. Tests for the
new features related directly with MDL-38259 will be added in a separate
commit (to make it clear what's related to it).
The caller of the mdeploy.php utility is expected to create a file in
the data directory. The name of such file and the passphrase in it are
then sent to mdeploy.php as a part of the request. The submitted and
stored values are then compared.
This class represents the communication bridge from Moodle UI to the
(standalone) mdeploy.php utility. It consists of various helper methods
useful when dealing with user interface, update confirmation etc.
The class is implemented as a singleton. This allows us easily
transfer required data from top level scripts (like /admin/index.php)
into the rendering methods deep in the stack without the need to change
the API of many methods on the way.
The expected behaviour is as follows:
* If the recently fetched data is older than 48 hours, it is considered
as outdated and the new fetch is executed
* else, if the recently fetched data is younger than 24 hours, it is
considered as fresh enough and no fetch is executed
* else, if the current time is after 01:00 AM plus a certain offset
(which is randomly generated for each site), the fetch is
executed.