Commit 0662bd67 authored by Petr Škoda's avatar Petr Škoda
Browse files

MDL-29996 remove deprecated stuff from filter code

parent fba0abdc
......@@ -35,7 +35,7 @@
require_once($CFG->libdir . '/adminlib.php');
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$filterpath = optional_param('filterpath', '', PARAM_PATH);
$filterpath = optional_param('filterpath', '', PARAM_SAFEDIR);
require_login();
$systemcontext = context_system::instance();
......@@ -84,39 +84,22 @@
case 'down':
if (isset($filters[$filterpath])) {
$oldpos = $filters[$filterpath]->sortorder;
if ($oldpos <= count($filters)) {
filter_set_global_state($filterpath, $filters[$filterpath]->active, $oldpos + 1);
}
filter_set_global_state($filterpath, $filters[$filterpath]->active, 1);
}
break;
case 'up':
if (isset($filters[$filterpath])) {
$oldpos = $filters[$filterpath]->sortorder;
if ($oldpos >= 1) {
filter_set_global_state($filterpath, $filters[$filterpath]->active, $oldpos - 1);
}
filter_set_global_state($filterpath, $filters[$filterpath]->active, -1);
}
break;
case 'delete':
if (!empty($filternames[$filterpath])) {
$filtername = $filternames[$filterpath];
} else {
$filtername = $filterpath;
}
if (substr($filterpath, 0, 4) == 'mod/') {
$mod = basename($filterpath);
$a = new stdClass;
$a->filter = $filtername;
$a->module = get_string('modulename', $mod);
print_error('cannotdeletemodfilter', 'admin', $returnurl, $a);
}
// If not yet confirmed, display a confirmation message.
if (!optional_param('confirm', '', PARAM_BOOL)) {
$filtername = filter_get_name($filterpath);
$title = get_string('deletefilterareyousure', 'admin', $filtername);
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
......@@ -129,7 +112,7 @@
}
// Do the deletion.
$title = get_string('deletingfilter', 'admin', $filtername);
$title = get_string('deletingfilter', 'admin', $filterpath);
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
......@@ -137,8 +120,8 @@
filter_delete_all_for_filter($filterpath);
$a = new stdClass;
$a->filter = $filtername;
$a->directory = $filterpath;
$a->filter = $filterpath;
$a->directory = "$CFG->dirroot/filter/$filterpath";
echo $OUTPUT->box(get_string('deletefilterfiles', 'admin', $a), 'generalbox', 'notice');
echo $OUTPUT->continue_button($returnurl);
echo $OUTPUT->footer();
......@@ -241,7 +224,7 @@ function get_table_row($filterinfo, $isfirstrow, $islastactive, $applytostrings)
}
// Disable/off/on
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $filterinfo->active, null, 'active' . basename($filter));
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $filterinfo->active, null, 'active' . $filter);
$select->set_label(get_string('isactive', 'filters'), array('class' => 'accesshide'));
$row[] = $OUTPUT->render($select);
......@@ -263,25 +246,20 @@ function get_table_row($filterinfo, $isfirstrow, $islastactive, $applytostrings)
$row[] = $updown;
// Apply to strings.
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . basename($filter));
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
$select->set_label(get_string('applyto', 'filters'), array('class' => 'accesshide'));
$select->disabled = $filterinfo->active == TEXTFILTER_DISABLED;
$row[] = $OUTPUT->render($select);
// Settings link, if required
if (filter_has_global_settings($filter)) {
$row[] = '<a href="' . $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=filtersetting' .
str_replace('/', '',$filter) . '">' . get_string('settings') . '</a>';
$row[] = '<a href="' . $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=filtersetting' . $filter . '">' . get_string('settings') . '</a>';
} else {
$row[] = '';
}
// Delete
if (substr($filter, 0, 4) != 'mod/') {
$row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('delete') . '</a>';
} else {
$row[] = '';
}
$row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('delete') . '</a>';
return $row;
}
......@@ -1817,6 +1817,14 @@ class restore_filters_structure_step extends restore_structure_step {
$data = (object)$data;
if (strpos($data->filter, 'filter/') === 0) {
$data->filter = substr($data->filter, 7);
} else if (strpos($data->filter, '/') !== false) {
// Unsupported old filter.
return;
}
if (!filter_is_enabled($data->filter)) { // Not installed or not enabled, nothing to do
return;
}
......@@ -1827,6 +1835,14 @@ class restore_filters_structure_step extends restore_structure_step {
$data = (object)$data;
if (strpos($data->filter, 'filter/') === 0) {
$data->filter = substr($data->filter, 7);
} else if (strpos($data->filter, '/') !== false) {
// Unsupported old filter.
return;
}
if (!filter_is_enabled($data->filter)) { // Not installed or not enabled, nothing to do
return;
}
......
......@@ -26,6 +26,6 @@ function xmldb_filter_activitynames_install() {
global $CFG;
require_once("$CFG->libdir/filterlib.php");
filter_set_global_state('filter/activitynames', TEXTFILTER_ON);
filter_set_global_state('activitynames', TEXTFILTER_ON);
}
......@@ -7,7 +7,7 @@
require_once("../../config.php");
if (!filter_is_enabled('filter/algebra')) {
if (!filter_is_enabled('algebra')) {
print_error('filternotenabled');
}
......
......@@ -9,7 +9,7 @@ define('NO_MOODLE_COOKIES', true); // Because it interferes with caching
require_once('../../config.php');
if (!filter_is_enabled('filter/algebra')) {
if (!filter_is_enabled('algebra')) {
print_error('filternotenabled');
}
......
......@@ -27,7 +27,7 @@ require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
$contextid = required_param('contextid',PARAM_INT);
$forfilter = optional_param('filter', '', PARAM_SAFEPATH);
$forfilter = optional_param('filter', '', PARAM_SAFEDIR);
list($context, $course, $cm) = get_context_info_array($contextid);
......@@ -82,8 +82,8 @@ if ($forfilter) {
print_error('filterdoesnothavelocalconfig', 'error', $forfilter);
}
require_once($CFG->dirroot . '/filter/local_settings_form.php');
require_once($CFG->dirroot . '/' . $forfilter . '/filterlocalsettings.php');
$formname = basename($forfilter) . '_filter_local_settings_form';
require_once($CFG->dirroot . '/filter/' . $forfilter . '/filterlocalsettings.php');
$formname = $forfilter . '_filter_local_settings_form';
$settingsform = new $formname($CFG->wwwroot . '/filter/manage.php', $forfilter, $context);
if ($settingsform->is_cancelled()) {
redirect($baseurl);
......@@ -96,7 +96,7 @@ if ($forfilter) {
/// Process any form submission.
if ($forfilter == '' && optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
foreach ($availablefilters as $filter => $filterinfo) {
$newstate = optional_param(str_replace('/', '_', $filter), false, PARAM_INT);
$newstate = optional_param($filter, false, PARAM_INT);
if ($newstate !== false && $newstate != $filterinfo->localstate) {
filter_set_local_state($filter, $context->id, $newstate);
}
......@@ -181,9 +181,8 @@ if (empty($availablefilters)) {
} else {
$activechoices[TEXTFILTER_INHERIT] = $strdefaultoff;
}
$filtername = str_replace('/', '_', $filter);
$select = html_writer::label($filterinfo->localstate, 'menu'. $filtername, false, array('class' => 'accesshide'));
$select .= html_writer::select($activechoices, $filtername, $filterinfo->localstate, false);
$select = html_writer::label($filterinfo->localstate, 'menu'. $filter, false, array('class' => 'accesshide'));
$select .= html_writer::select($activechoices, $filter, $filterinfo->localstate, false);
$row[] = $select;
// Settings link, if required
......
......@@ -27,6 +27,6 @@ function xmldb_filter_mediaplugin_install() {
global $CFG;
require_once("$CFG->libdir/filterlib.php");
filter_set_global_state('filter/mediaplugin', TEXTFILTER_ON);
filter_set_global_state('mediaplugin', TEXTFILTER_ON);
}
......@@ -29,7 +29,7 @@ define('NO_MOODLE_COOKIES', true); // Because it interferes with caching
require('../../config.php');
if (!filter_is_enabled('filter/tex') and !filter_is_enabled('filter/algebra')) {
if (!filter_is_enabled('tex') and !filter_is_enabled('algebra')) {
print_error('filternotenabled');
}
......
......@@ -9,7 +9,7 @@ define('NO_MOODLE_COOKIES', true); // Because it interferes with caching
require_once('../../config.php');
if (!filter_is_enabled('filter/tex')) {
if (!filter_is_enabled('tex')) {
print_error('filternotenabled');
}
......
......@@ -28,7 +28,7 @@
require_once("../../config.php");
if (!filter_is_enabled('filter/tex')) {
if (!filter_is_enabled('tex')) {
print_error('filternotenabled');
}
......
This file describes API changes in core filter API and plugins,
information provided here is intended especially for developers.
=== 2.5 ===
* legacy_filter emulation was removed
* support for 'mod/*' filters was removed
* use short filter name instead of old path, ex.: 'filter/tex' ---> 'tex'
in all filter API functions and methods
=== 2.3 ===
* new setup() method added to moodle_text_filter, invoked before
......
......@@ -6092,8 +6092,7 @@ class admin_page_managefilters extends admin_externalpage {
$found = true;
break;
}
list($type, $filter) = explode('/', $path);
if (strpos($filter, $query) !== false) {
if (strpos($path, $query) !== false) {
$found = true;
break;
}
......
......@@ -456,7 +456,7 @@
<TABLE NAME="filter_active" COMMENT="Stores information about which filters are active in which contexts. Also the filter sort order. See get_active_filters in lib/filterlib.php for how this data is used." PREVIOUS="course_format_options" NEXT="filter_config">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="filter"/>
<FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'filter/tex' or 'mod/glossary'." PREVIOUS="id" NEXT="contextid"/>
<FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'tex'." PREVIOUS="id" NEXT="contextid"/>
<FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="References context.id." PREVIOUS="filter" NEXT="active"/>
<FIELD NAME="active" TYPE="int" LENGTH="4" NOTNULL="true" SEQUENCE="false" COMMENT="Whether this filter is active in this context. +1 = On, -1 = Off, no row with this contextid = inherit. As a special case, when contextid points to the system context, -9999 means this filter is completely disabled." PREVIOUS="contextid" NEXT="sortorder"/>
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Only relevant if contextid points to the system context. In other cases this field should contain 0. The order in which the filters should be applied." PREVIOUS="active"/>
......@@ -472,7 +472,7 @@
<TABLE NAME="filter_config" COMMENT="Stores per-context configuration settings for filters which have them." PREVIOUS="filter_active" NEXT="event">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="filter"/>
<FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'filter/tex' or 'mod/glossary'." PREVIOUS="id" NEXT="contextid"/>
<FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'tex'." PREVIOUS="id" NEXT="contextid"/>
<FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="References context.id." PREVIOUS="filter" NEXT="name"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The config variable name." PREVIOUS="contextid" NEXT="value"/>
<FIELD NAME="value" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The correspoding config variable value." PREVIOUS="name"/>
......
......@@ -1524,5 +1524,46 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2012120300.04);
}
if ($oldversion < 2012120300.07) {
// Purge removed module filters and all their settings.
$tables = array('filter_active', 'filter_config');
foreach ($tables as $table) {
$DB->delete_records_select($table, "filter LIKE 'mod/%'");
$filters = $DB->get_records_sql("SELECT DISTINCT filter FROM {{$table}} WHERE filter LIKE 'filter/%'");
foreach ($filters as $filter) {
$DB->set_field($table, 'filter', substr($filter->filter, 7), array('filter'=>$filter->filter));
}
}
$configs = array('stringfilters', 'filterall');
foreach ($configs as $config) {
if ($filters = get_config(null, $config)) {
$filters = explode(',', $filters);
$newfilters = array();
foreach($filters as $filter) {
if (strpos($filter, '/') === false) {
$newfilters[] = $filter;
} else if (strpos($filter, 'filter/') === 0) {
$newfilters[] = substr($filter, 7);
}
}
$filters = implode(',', $newfilters);
set_config($config, $filters);
}
}
unset($tables);
unset($table);
unset($configs);
unset($newfilters);
unset($filters);
unset($filter);
// Main savepoint reached.
upgrade_main_savepoint(true, 2012120300.07);
}
return true;
}
......@@ -33,7 +33,7 @@ class tinymce_dragmath extends editor_tinymce_plugin {
if ($this->get_config('requiretex', 1)) {
// If TeX filter is disabled, do not add button.
$filters = filter_get_active_in_context($context);
if (!array_key_exists('filter/tex', $filters)) {
if (!array_key_exists('tex', $filters)) {
return;
}
}
......
......@@ -34,7 +34,7 @@ class tinymce_moodleemoticon extends editor_tinymce_plugin {
if ($this->get_config('requireemoticon', 1)) {
// If emoticon filter is disabled, do not add button.
$filters = filter_get_active_in_context($context);
if (!array_key_exists('filter/emoticon', $filters)) {
if (!array_key_exists('emoticon', $filters)) {
return;
}
}
......
......@@ -2,6 +2,11 @@ This files describes API changes in /lib/editor/tinymce/* - TinyMCE editor,
information provided here is intended especially for developers.
=== 2.5 ===
* update filter related code to use short filter names instead
of original paths, ex.: 'filter/tex' ---> 'tex'
=== 2.4 ===
new features:
......
......@@ -2715,7 +2715,7 @@ function file_modify_html_header($text) {
}*/
$ufo = '';
if (filter_is_enabled('filter/mediaplugin')) {
if (filter_is_enabled('mediaplugin')) {
// this script is needed by most media filter plugins.
$attributes = array('type'=>'text/javascript', 'src'=>$CFG->httpswwwroot . '/lib/ufo.js');
$ufo = html_writer::tag('script', '', $attributes) . "\n";
......
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
......@@ -18,8 +17,7 @@
/**
* Library functions for managing text filter plugins.
*
* @package core
* @subpackage filter
* @package core_filter
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -50,8 +48,7 @@ define('TEXTFILTER_EXCL_SEPARATOR', '-%-');
*
* This class is a singleton.
*
* @package core
* @subpackage filter
* @package core_filter
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -115,23 +112,23 @@ class filter_manager {
}
/**
* Factory method for creating a filter
* Factory method for creating a filter.
*
* @param string $filter The filter name, for example 'filter/tex' or 'mod/glossary'.
* @param object $context context object.
* @param string $filtername The filter name, for example 'tex'.
* @param context $context context object.
* @param array $localconfig array of local configuration variables for this filter.
* @return object moodle_text_filter The filter, or null, if this type of filter is
* @return moodle_text_filter The filter, or null, if this type of filter is
* not recognised or could not be created.
*/
protected function make_filter_object($filtername, $context, $localconfig) {
global $CFG;
$path = $CFG->dirroot .'/'. $filtername .'/filter.php';
$path = $CFG->dirroot .'/filter/'. $filtername .'/filter.php';
if (!is_readable($path)) {
return null;
}
include_once($path);
$filterclassname = 'filter_' . basename($filtername);
$filterclassname = 'filter_' . $filtername;
if (class_exists($filterclassname)) {
return new $filterclassname($context, $localconfig);
}
......@@ -187,7 +184,7 @@ class filter_manager {
*/
public function filter_text($text, $context, array $options = array()) {
$text = $this->apply_filter_chain($text, $this->get_text_filters($context), $options);
/// <nolink> tags removed for XHTML compatibility
// <nolink> tags removed for XHTML compatibility
$text = str_replace(array('<nolink>', '</nolink>'), '', $text);
return $text;
}
......@@ -196,7 +193,7 @@ class filter_manager {
* Filter a piece of string
*
* @param string $string The text to filter
* @param object $context
* @param context $context
* @return string resulting string
*/
public function filter_string($string, $context) {
......@@ -205,7 +202,7 @@ class filter_manager {
/**
* @todo Document this function
* @param object $context
* @param context $context
* @return object A string filter
*/
public function text_filtering_hash($context) {
......@@ -247,8 +244,7 @@ class filter_manager {
*
* @todo Document this class
*
* @package core
* @subpackage filter
* @package core_filter
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -280,8 +276,7 @@ class null_filter_manager {
*
* @todo Document this class
*
* @package core
* @subpackage filter
* @package core_filter
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -345,8 +340,7 @@ class performance_measuring_filter_manager extends filter_manager {
* Base class for text filters. You just need to override this class and
* implement the filter method.
*
* @package core
* @subpackage filter
* @package core_filter
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
......@@ -358,9 +352,9 @@ abstract class moodle_text_filter {
/**
* Set any context-specific configuration for this filter.
* @param object $context The current course id.
* @param object $context The current context.
* @param array $config Any context-specific configuration for this filter.
*
* @param context $context The current context.
* @param array $localconfig Any context-specific configuration for this filter.
*/
public function __construct($context, array $localconfig) {
$this->context = $context;
......@@ -459,66 +453,40 @@ class filterobject {
}
/**
* Look up the name of this filter in the most appropriate location.
* If $filterlocation = 'mod' then does get_string('filtername', $filter);
* else if $filterlocation = 'filter' then does get_string('filtername', 'filter_' . $filter);
* with a fallback to get_string('filtername', $filter) for backwards compatibility.
* These are the only two options supported at the moment.
* Look up the name of this filter
*
* @param string $filter the folder name where the filter lives.
* @param string $filter the filter name
* @return string the human-readable name for this filter.
*/
function filter_get_name($filter) {
// TODO: should we be using pluginname here instead? , see MDL-29998
list($type, $filter) = explode('/', $filter);
switch ($type) {
case 'filter':
$strfiltername = get_string('filtername', 'filter_' . $filter);
if (substr($strfiltername, 0, 2) != '[[') {
// found a valid string.
return $strfiltername;
}
// Fall through to try the legacy location.
// TODO: deprecated since 2.2, will be out in 2.3, see MDL-29996
case 'mod':
$strfiltername = get_string('filtername', $filter);
if (substr($strfiltername, 0, 2) == '[[') {
$strfiltername .= ' (' . $type . '/' . $filter . ')';
}
return $strfiltername;
if (strpos($filter, 'filter/') === 0) {
debugging("Old '$filter'' parameter used in filter_get_name()");
$filter = substr($filter, 7);
} else if (strpos($filter, '/') !== false) {
throw new coding_exception('Unknown filter type ' . $filter);
}
default:
throw new coding_exception('Unknown filter type ' . $type);
if (get_string_manager()->string_exists('filtername', 'filter_' . $filter)) {
return get_string('filtername', 'filter_' . $filter);
} else {
return $filter;
}
}
/**
* Get the names of all the filters installed in this Moodle.
*
* @global object
* @return array path => filter name from the appropriate lang file. e.g.
* array('mod/glossary' => 'Glossary Auto-linking', 'filter/tex' => 'TeX Notation');
* array('tex' => 'TeX Notation');
* sorted in alphabetical order of name.
*/
function filter_get_all_installed() {
global $CFG;
$filternames = array();
// TODO: deprecated since 2.2, will be out in 2.3, see MDL-29996
$filterlocations = array('mod', 'filter');
foreach ($filterlocations as $filterlocation) {
// TODO: move get_list_of_plugins() to get_plugin_list()
$filters = get_list_of_plugins($filterlocation);
foreach ($filters as $filter) {
// MDL-29994 - Ignore mod/data and mod/glossary filters forever, this will be out in 2.3
if ($filterlocation == 'mod' && ($filter == 'data' || $filter == 'glossary')) {
continue;
}
$path = $filterlocation . '/' . $filter;
if (is_readable($CFG->dirroot . '/' . $path . '/filter.php')) {
$strfiltername = filter_get_name($path);
$filternames[$path] = $strfiltername;
}
foreach (get_list_of_plugins('filter') as $filter) {
if (is_readable("$CFG->dirroot/filter/$filter/filter.php")) {
$filternames[$filter] = filter_get_name($filter);
}
}
collatorlib::asort($filternames);
......@@ -528,17 +496,11 @@ function filter_get_all_installed() {
/**
* Set the global activated state for a text filter.
*
* @global object
* @param string $filter The filter name, for example 'filter/tex' or 'mod/glossary'.
* @param integer $state One of the values TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED.
* @param integer $sortorder (optional) a position in the sortorder to place this filter.
* If not given defaults to:
* No change in order if we are updating an existing record, and not changing to or from TEXTFILTER_DISABLED.
* Just after the last currently active filter when adding an unknown filter
* in state TEXTFILTER_ON or TEXTFILTER_OFF, or enabling/disabling an existing filter.
* Just after the very last filter when adding an unknown filter in state TEXTFILTER_DISABLED
* @param string $filtername The filter name, for example 'tex'.
* @param int $state One of the values TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED.
* @param int $move 1 means up, 0 means the same, -1 means down
*/
function filter_set_global_state($filter, $state, $sortorder = false) {
function filter_set_global_state($filtername, $state, $move = 0) {
global $DB;
// Check requested state is valid.
......@@ -547,84 +509,141 @@ function filter_set_global_state($filter, $state, $sortorder = false) {
"Must be one of TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED.");
}
// Check sortorder is valid.
if ($sortorder !== false) {
if ($sortorder < 1 || $sortorder > $DB->get_field('filter_active', 'MAX(sortorder)', array()) + 1) {
throw new coding_exception("Invalid sort order passed to filter_set_global_state.");
}
if ($move > 0) {
$move = 1;
} else if ($move < 0) {