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(); return $plugin->is_enabled();
})); }));
$this->enabledplugincount = count(array_filter($this->plugins, function ($plugin) {
return $plugin->is_enabled();
}));
$this->setup_column_configuration(); $this->setup_column_configuration();
$this->set_filterset(new plugin_management_table_filterset()); $this->set_filterset(new plugin_management_table_filterset());
$this->setup(); $this->setup();
@ -127,7 +131,7 @@ abstract class plugin_management_table extends flexible_table implements dynamic
} else if (!$a->is_enabled() && $b->is_enabled()) { } else if (!$a->is_enabled() && $b->is_enabled()) {
return 1; return 1;
} }
return strnatcasecmp($a->displayname, $b->displayname); return strnatcasecmp($a->name, $b->name);
}); });
return $plugins; return $plugins;
@ -166,6 +170,15 @@ abstract class plugin_management_table extends flexible_table implements dynamic
return 'core_admin_set_plugin_state'; 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. * 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'); $columns['enabled'] = get_string('pluginenabled', 'core_plugin');
} }
if ($this->supports_ordering()) {
$columns['order'] = get_string('order', 'core');
}
$columns['settings'] = get_string('settings', 'core'); $columns['settings'] = get_string('settings', 'core');
$columns['uninstall'] = get_string('uninstallplugin', 'core_admin'); $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. * Show the settings column content.
* *
@ -395,4 +483,13 @@ abstract class plugin_management_table extends flexible_table implements dynamic
protected function supports_disabling(): bool { protected function supports_disabling(): bool {
return $this->plugininfoclass::plugintype_supports_disabling(); 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 <?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('../config.php');
require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir.'/tablelib.php'); require_once($CFG->libdir . '/tablelib.php');
$action = required_param('action', PARAM_ALPHANUMEXT); $action = required_param('action', PARAM_ALPHANUMEXT);
$editor = required_param('editor', PARAM_PLUGIN); $plugin = required_param('plugin', PARAM_PLUGIN);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$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()); $PAGE->set_context(context_system::instance());
require_admin(); 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 // Get currently installed and enabled auth plugins.
$available_editors = editors_get_available(); $availableeditors = editors_get_available();
if (!empty($editor) and empty($available_editors[$editor])) { if (!empty($plugin) && empty($availableeditors[$plugin])) {
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()) {
redirect($returnurl); redirect($returnurl);
} }
$return = true; $activeeditors = explode(',', $CFG->texteditors);
foreach ($activeeditors as $key => $active) {
if (empty($availableeditors[$active])) {
unset($activeeditors[$key]);
}
}
switch ($action) { switch ($action) {
case 'disable': case 'disable':
// Remove from enabled list. // Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('editor'); $class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, false); $class::enable_plugin($plugin, false);
break; break;
case 'enable': case 'enable':
// Add to enabled list. // Add to enabled list.
if (!in_array($editor, $active_editors)) { if (!in_array($plugin, $activeeditors)) {
$class = \core_plugin_manager::resolve_plugininfo_class('editor'); $class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, true); $class::enable_plugin($plugin, true);
} }
break; break;
case 'down': case 'down':
$key = array_search($editor, $active_editors); $key = array_search($plugin, $activeeditors);
// check auth plugin is valid
if ($key !== false) { if ($key !== false) {
// move down the list // Move down the list.
if ($key < (count($active_editors) - 1)) { if ($key < (count($activeeditors) - 1)) {
$fsave = $active_editors[$key]; $fsave = $activeeditors[$key];
$active_editors[$key] = $active_editors[$key + 1]; $activeeditors[$key] = $activeeditors[$key + 1];
$active_editors[$key + 1] = $fsave; $activeeditors[$key + 1] = $fsave;
add_to_config_log('editor_position', $key, $key + 1, $editor); add_to_config_log('editor_position', $key, $key + 1, $plugin);
set_config('texteditors', implode(',', $active_editors)); set_config('texteditors', implode(',', $activeeditors));
core_plugin_manager::reset_caches(); core_plugin_manager::reset_caches();
} }
} }
break; break;
case 'up': case 'up':
$key = array_search($editor, $active_editors); $key = array_search($plugin, $activeeditors);
// check auth is valid
if ($key !== false) { if ($key !== false) {
// move up the list // Move up the list.
if ($key >= 1) { if ($key >= 1) {
$fsave = $active_editors[$key]; $fsave = $activeeditors[$key];
$active_editors[$key] = $active_editors[$key - 1]; $activeeditors[$key] = $activeeditors[$key - 1];
$active_editors[$key - 1] = $fsave; $activeeditors[$key - 1] = $fsave;
add_to_config_log('editor_position', $key, $key - 1, $editor); add_to_config_log('editor_position', $key, $key - 1, $plugin);
set_config('texteditors', implode(',', $active_editors)); set_config('texteditors', implode(',', $activeeditors));
core_plugin_manager::reset_caches(); core_plugin_manager::reset_caches();
} }
} }
@ -91,6 +99,4 @@ switch ($action) {
break; break;
} }
if ($return) { redirect($returnurl);
redirect ($returnurl);
}

View File

@ -154,7 +154,12 @@ if ($hassiteconfig) {
/// Editor plugins /// Editor plugins
$ADMIN->add('modules', new admin_category('editorsettings', new lang_string('editors', 'editor'))); $ADMIN->add('modules', new admin_category('editorsettings', new lang_string('editors', 'editor')));
$temp = new admin_settingpage('manageeditors', new lang_string('editorsettings', '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); $ADMIN->add('editorsettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('editor'); $plugins = core_plugin_manager::instance()->get_plugins_of_type('editor');
core_collator::asort_objects_by_property($plugins, 'displayname'); 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. * Special class for antiviruses administration.
* *

View File

@ -7,7 +7,7 @@ Feature: An administrator can manage TinyMCE subplugins
@javascript @javascript
Scenario: An administrator can control the enabled state of TinyMCE subplugins using JavaScript Scenario: An administrator can control the enabled state of TinyMCE subplugins using JavaScript
Given I am logged in as "admin" 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" When I click on "Disable the Tiny equation editor plugin" "link"
Then I should see "The Tiny equation editor plugin has been disabled" Then I should see "The Tiny equation editor plugin has been disabled"
And "Disable the Tiny equation editor plugin" "link" should not exist 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 Scenario: An administrator can control the enabled state of TinyMCE subplugins without JavaScript
Given I am logged in as "admin" 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" When I click on "Disable the Tiny equation editor plugin" "link"
Then I should see "The Tiny equation editor plugin has been disabled" Then I should see "The Tiny equation editor plugin has been disabled"
And "Disable the Tiny equation editor plugin" "link" should not exist And "Disable the Tiny equation editor plugin" "link" should not exist