MDL-76867 core_admin: Migrate editors admin ui to plugin management

This commit is contained in:
Andrew Nicols 2023-02-13 22:47:19 +08:00
parent 9f1c596dbd
commit f54cc61e4b
6 changed files with 228 additions and 231 deletions

View File

@ -0,0 +1,67 @@
<?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/>.
namespace core_admin\table;
use moodle_url;
/**
* Tiny admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class editor_management_table extends \core_admin\table\plugin_management_table {
protected function get_plugintype(): string {
return 'editor';
}
public function guess_base_url(): void {
$this->define_baseurl(
new moodle_url('/admin/settings.php', ['section' => 'manageeditors'])
);
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/editors.php', $params);
}
protected function supports_ordering(): bool {
return true;
}
protected function order_plugins(array $plugins): array {
global $CFG;
// The Editor list is stored in an ordered string.
$activeeditors = explode(',', $CFG->texteditors);
$sortedplugins = [];
foreach ($activeeditors as $editor) {
if (isset($plugins[$editor])) {
$sortedplugins[$editor] = $plugins[$editor];
unset($plugins[$editor]);
}
}
$otherplugins = parent::order_plugins($plugins);
return array_merge(
$sortedplugins,
$otherplugins
);
}
}

View File

@ -65,6 +65,10 @@ abstract class plugin_management_table extends flexible_table implements dynamic
return $plugin->is_enabled();
}));
$this->enabledplugincount = count(array_filter($this->plugins, function ($plugin) {
return $plugin->is_enabled();
}));
$this->setup_column_configuration();
$this->set_filterset(new plugin_management_table_filterset());
$this->setup();
@ -127,7 +131,7 @@ abstract class plugin_management_table extends flexible_table implements dynamic
} else if (!$a->is_enabled() && $b->is_enabled()) {
return 1;
}
return strnatcasecmp($a->displayname, $b->displayname);
return strnatcasecmp($a->name, $b->name);
});
return $plugins;
@ -166,6 +170,15 @@ abstract class plugin_management_table extends flexible_table implements dynamic
return 'core_admin_set_plugin_state';
}
/**
* Get the web service method used to order plugins.
*
* @return null|string
*/
protected function get_sortorder_service(): ?string {
return null;
}
/**
* Get the ID of the table.
*
@ -189,6 +202,10 @@ abstract class plugin_management_table extends flexible_table implements dynamic
$columns['enabled'] = get_string('pluginenabled', 'core_plugin');
}
if ($this->supports_ordering()) {
$columns['order'] = get_string('order', 'core');
}
$columns['settings'] = get_string('settings', 'core');
$columns['uninstall'] = get_string('uninstallplugin', 'core_admin');
@ -302,6 +319,77 @@ abstract class plugin_management_table extends flexible_table implements dynamic
);
}
protected function col_order(stdClass $row): string {
global $OUTPUT;
if (!$this->supports_ordering()) {
return '';
}
if (!$row->plugininfo->is_enabled()) {
return '';
}
if ($this->enabledplugincount <= 1) {
// There is only one row.
return '';
}
$hasup = true;
$hasdown = true;
if (empty($this->currentrow)) {
// This is the top row.
$hasup = false;
}
if ($this->currentrow === ($this->enabledplugincount - 1)) {
// This is the last row.
$hasdown = false;
}
if ($this->get_sortorder_service()) {
$dataattributes = [
'data-method' => $this->get_sortorder_service(),
'data-action' => 'move',
'data-plugin' => $row->plugin,
];
} else {
$dataattributes = [];
}
if ($hasup) {
$upicon = html_writer::link(
$this->get_action_url([
'sesskey' => sesskey(),
'action' => 'up',
'plugin' => $row->plugininfo->name,
]),
$OUTPUT->pix_icon('t/up', get_string('moveup')),
array_merge($dataattributes, ['data-direction' => 'up']),
);
} else {
$upicon = $OUTPUT->spacer();
}
if ($hasdown) {
$downicon = html_writer::link(
$this->get_action_url([
'sesskey' => sesskey(),
'action' => 'down',
'plugin' => $row->plugininfo->name,
]),
$OUTPUT->pix_icon('t/down', get_string('movedown')),
array_merge($dataattributes, ['data-direction' => 'down']),
);
} else {
$downicon = $OUTPUT->spacer();
}
// For now just add the up/down icons.
return html_writer::span($upicon . $downicon);
}
/**
* Show the settings column content.
*
@ -395,4 +483,13 @@ abstract class plugin_management_table extends flexible_table implements dynamic
protected function supports_disabling(): bool {
return $this->plugininfoclass::plugintype_supports_disabling();
}
/**
* Whether this table should show ordering fields.
*
* @return bool
*/
protected function supports_ordering(): bool {
return false;
}
}

View File

@ -1,87 +1,95 @@
<?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/>.
/**
* Allows admin to configure editors.
* A page to manage editor plugins.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/tablelib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$editor = required_param('editor', PARAM_PLUGIN);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$action = required_param('action', PARAM_ALPHANUMEXT);
$plugin = required_param('plugin', PARAM_PLUGIN);
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
$PAGE->set_url('/admin/editors.php', ['action' => $action, 'editor' => $plugin]);
$PAGE->set_context(context_system::instance());
require_admin();
require_sesskey();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
$returnurl = new moodle_url('/admin/settings.php', ['section' => 'manageeditors']);
// get currently installed and enabled auth plugins
$available_editors = editors_get_available();
if (!empty($editor) and empty($available_editors[$editor])) {
redirect ($returnurl);
}
$active_editors = explode(',', $CFG->texteditors);
foreach ($active_editors as $key=>$active) {
if (empty($available_editors[$active])) {
unset($active_editors[$key]);
}
}
////////////////////////////////////////////////////////////////////////////////
// process actions
if (!confirm_sesskey()) {
// Get currently installed and enabled auth plugins.
$availableeditors = editors_get_available();
if (!empty($plugin) && empty($availableeditors[$plugin])) {
redirect($returnurl);
}
$return = true;
$activeeditors = explode(',', $CFG->texteditors);
foreach ($activeeditors as $key => $active) {
if (empty($availableeditors[$active])) {
unset($activeeditors[$key]);
}
}
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, false);
$class::enable_plugin($plugin, false);
break;
case 'enable':
// Add to enabled list.
if (!in_array($editor, $active_editors)) {
if (!in_array($plugin, $activeeditors)) {
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, true);
$class::enable_plugin($plugin, true);
}
break;
case 'down':
$key = array_search($editor, $active_editors);
// check auth plugin is valid
$key = array_search($plugin, $activeeditors);
if ($key !== false) {
// move down the list
if ($key < (count($active_editors) - 1)) {
$fsave = $active_editors[$key];
$active_editors[$key] = $active_editors[$key + 1];
$active_editors[$key + 1] = $fsave;
add_to_config_log('editor_position', $key, $key + 1, $editor);
set_config('texteditors', implode(',', $active_editors));
// Move down the list.
if ($key < (count($activeeditors) - 1)) {
$fsave = $activeeditors[$key];
$activeeditors[$key] = $activeeditors[$key + 1];
$activeeditors[$key + 1] = $fsave;
add_to_config_log('editor_position', $key, $key + 1, $plugin);
set_config('texteditors', implode(',', $activeeditors));
core_plugin_manager::reset_caches();
}
}
break;
case 'up':
$key = array_search($editor, $active_editors);
// check auth is valid
$key = array_search($plugin, $activeeditors);
if ($key !== false) {
// move up the list
// Move up the list.
if ($key >= 1) {
$fsave = $active_editors[$key];
$active_editors[$key] = $active_editors[$key - 1];
$active_editors[$key - 1] = $fsave;
add_to_config_log('editor_position', $key, $key - 1, $editor);
set_config('texteditors', implode(',', $active_editors));
$fsave = $activeeditors[$key];
$activeeditors[$key] = $activeeditors[$key - 1];
$activeeditors[$key - 1] = $fsave;
add_to_config_log('editor_position', $key, $key - 1, $plugin);
set_config('texteditors', implode(',', $activeeditors));
core_plugin_manager::reset_caches();
}
}
@ -91,6 +99,4 @@ switch ($action) {
break;
}
if ($return) {
redirect ($returnurl);
}
redirect($returnurl);

View File

@ -154,7 +154,12 @@ if ($hassiteconfig) {
/// Editor plugins
$ADMIN->add('modules', new admin_category('editorsettings', new lang_string('editors', 'editor')));
$temp = new admin_settingpage('manageeditors', new lang_string('editorsettings', 'editor'));
$temp->add(new admin_setting_manageeditors());
$temp->add(new \core_admin\admin\admin_setting_plugin_manager(
'editor',
\core_admin\table\editor_management_table::class,
'editorsui',
get_string('editorsettings', 'editor'),
));
$ADMIN->add('editorsettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('editor');
core_collator::asort_objects_by_property($plugins, 'displayname');

View File

@ -7239,184 +7239,6 @@ class admin_setting_manageauths extends admin_setting {
}
}
/**
* Special class for authentication administration.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_manageeditors extends admin_setting {
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
$this->nosave = true;
parent::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting() {
return true;
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting() {
return true;
}
/**
* Always returns '', does not write anything
*
* @return string Always returns ''
*/
public function write_setting($data) {
// do not write any setting
return '';
}
/**
* Checks if $query is one of the available editors
*
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function is_related($query) {
if (parent::is_related($query)) {
return true;
}
$editors_available = editors_get_available();
foreach ($editors_available as $editor=>$editorstr) {
if (strpos($editor, $query) !== false) {
return true;
}
if (strpos(core_text::strtolower($editorstr), $query) !== false) {
return true;
}
}
return false;
}
/**
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT;
// display strings
$txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
'up', 'down', 'none'));
$struninstall = get_string('uninstallplugin', 'core_admin');
$txt->updown = "$txt->up/$txt->down";
$editors_available = editors_get_available();
$active_editors = explode(',', $CFG->texteditors);
$active_editors = array_reverse($active_editors);
foreach ($active_editors as $key=>$editor) {
if (empty($editors_available[$editor])) {
unset($active_editors[$key]);
} else {
$name = $editors_available[$editor];
unset($editors_available[$editor]);
$editors_available[$editor] = $name;
}
}
if (empty($active_editors)) {
//$active_editors = array('textarea');
}
$editors_available = array_reverse($editors_available, true);
$return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
$return .= $OUTPUT->box_start('generalbox editorsui');
$table = new html_table();
$table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings, $struninstall);
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
$table->id = 'editormanagement';
$table->attributes['class'] = 'admintable generaltable';
$table->data = array();
// iterate through auth plugins and add to the display table
$updowncount = 1;
$editorcount = count($active_editors);
$url = "editors.php?sesskey=" . sesskey();
foreach ($editors_available as $editor => $name) {
// hide/show link
$class = '';
if (in_array($editor, $active_editors)) {
$hideshow = "<a href=\"$url&amp;action=disable&amp;editor=$editor\">";
$hideshow .= $OUTPUT->pix_icon('t/hide', get_string('disable')) . '</a>';
$enabled = true;
$displayname = $name;
}
else {
$hideshow = "<a href=\"$url&amp;action=enable&amp;editor=$editor\">";
$hideshow .= $OUTPUT->pix_icon('t/show', get_string('enable')) . '</a>';
$enabled = false;
$displayname = $name;
$class = 'dimmed_text';
}
// up/down link (only if auth is enabled)
$updown = '';
if ($enabled) {
if ($updowncount > 1) {
$updown .= "<a href=\"$url&amp;action=up&amp;editor=$editor\">";
$updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . '</a>&nbsp;';
}
else {
$updown .= $OUTPUT->spacer() . '&nbsp;';
}
if ($updowncount < $editorcount) {
$updown .= "<a href=\"$url&amp;action=down&amp;editor=$editor\">";
$updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . '</a>&nbsp;';
}
else {
$updown .= $OUTPUT->spacer() . '&nbsp;';
}
++ $updowncount;
}
// settings link
if (file_exists($CFG->dirroot.'/lib/editor/'.$editor.'/settings.php')) {
$eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettings'.$editor));
$settings = "<a href='$eurl'>{$txt->settings}</a>";
} else {
$settings = '';
}
$uninstall = '';
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('editor_'.$editor, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
}
// Add a row to the table.
$row = new html_table_row(array($displayname, $hideshow, $updown, $settings, $uninstall));
if ($class) {
$row->attributes['class'] = $class;
}
$table->data[] = $row;
}
$return .= html_writer::table($table);
$return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
$return .= $OUTPUT->box_end();
return highlight($query, $return);
}
}
/**
* Special class for antiviruses administration.
*

View File

@ -7,7 +7,7 @@ Feature: An administrator can manage TinyMCE subplugins
@javascript
Scenario: An administrator can control the enabled state of TinyMCE subplugins using JavaScript
Given I am logged in as "admin"
And I navigate to "Plugins > Text editors > TinyMCE > General settings" in site administration
And I navigate to "Plugins > Text editors > TinyMCE editor > General settings" in site administration
When I click on "Disable the Tiny equation editor plugin" "link"
Then I should see "The Tiny equation editor plugin has been disabled"
And "Disable the Tiny equation editor plugin" "link" should not exist
@ -19,7 +19,7 @@ Feature: An administrator can manage TinyMCE subplugins
Scenario: An administrator can control the enabled state of TinyMCE subplugins without JavaScript
Given I am logged in as "admin"
And I navigate to "Plugins > Text editors > TinyMCE > General settings" in site administration
And I navigate to "Plugins > Text editors > TinyMCE editor > General settings" in site administration
When I click on "Disable the Tiny equation editor plugin" "link"
Then I should see "The Tiny equation editor plugin has been disabled"
And "Disable the Tiny equation editor plugin" "link" should not exist