MDL-72339 core_availability: Unsafe to use format_string in description

The availability condition get_description method is called while
gathering data for the modinfo object. As such it is not safe to
call other functions which might rely on modinfo, such as format_string
(if using filters which access modinfo).

This change provides a mechanism to call format_string later, and also
a general callback to do other stuff later as well if needed. It uses
the same approach already taken to make activity names work correctly
in the availability_condition class.
This commit is contained in:
sam marshall
2021-10-06 11:27:42 +01:00
parent 278c3dfb4d
commit ca7b088d44
16 changed files with 275 additions and 19 deletions
+78 -8
View File
@@ -108,6 +108,64 @@ abstract class condition extends tree_node {
return preg_replace('~^availability_(.*?)\\\\condition$~', '$1', get_class($this));
}
/**
* Returns a marker indicating that an activity name should be placed in a description.
*
* Gets placeholder text which will be decoded by info::format_info later when we can safely
* display names.
*
* @param int $cmid Course-module id
* @return string Placeholder text
* @since Moodle 3.10.7
*/
public static function description_cm_name(int $cmid): string {
return '<AVAILABILITY_CMNAME_' . $cmid . '/>';
}
/**
* Returns a marker indicating that formatted text should be placed in a description.
*
* Gets placeholder text which will be decoded by info::format_info later when we can safely
* call format_string.
*
* @param string $str Text to be processed with format_string
* @return string Placeholder text
* @since Moodle 3.10.7
*/
public static function description_format_string(string $str): string {
return '<AVAILABILITY_FORMAT_STRING>' . htmlspecialchars($str, ENT_NOQUOTES) .
'</AVAILABILITY_FORMAT_STRING>';
}
/**
* Returns a marker indicating that some of the description text should be computed at display
* time.
*
* This will result in a call to the get_description_callback_value static function within
* the condition class.
*
* Gets placeholder text which will be decoded by info::format_info later when we can safely
* call most Moodle functions.
*
* @param string[] $params Array of arbitrary parameters
* @return string Placeholder text
* @since Moodle 3.10.7
*/
public function description_callback(array $params): string {
$out = '<AVAILABILITY_CALLBACK type="' . $this->get_type() . '">';
$first = true;
foreach ($params as $param) {
if ($first) {
$first = false;
} else {
$out .= '<P/>';
}
$out .= htmlspecialchars($param, ENT_NOQUOTES);
}
$out .= '</AVAILABILITY_CALLBACK>';
return $out;
}
/**
* Obtains a string describing this restriction (whether or not
* it actually applies). Used to obtain information that is displayed to
@@ -119,11 +177,17 @@ abstract class condition extends tree_node {
* (when displaying only conditions they don't meet).
*
* If implementations require a course or modinfo, they should use
* the get methods in $info.
* the get methods in $info. They should not use any other functions that
* might rely on modinfo, such as format_string.
*
* The special string <AVAILABILITY_CMNAME_123/> can be returned, where
* 123 is any number. It will be replaced with the correctly-formatted
* name for that activity.
* To work around this limitation, use the functions:
*
* description_cm_name()
* description_format_string()
* description_callback()
*
* These return special markers which will be added to the string and processed
* later after modinfo is complete.
*
* @param bool $full Set true if this is the 'full information' view
* @param bool $not Set true if we are inverting the condition
@@ -142,11 +206,17 @@ abstract class condition extends tree_node {
* the list, in front of the standard get_description call.
*
* If implementations require a course or modinfo, they should use
* the get methods in $info.
* the get methods in $info. They should not use any other functions that
* might rely on modinfo, such as format_string.
*
* The special string <AVAILABILITY_CMNAME_123/> can be returned, where
* 123 is any number. It will be replaced with the correctly-formatted
* name for that activity.
* To work around this limitation, use the functions:
*
* description_cm_name()
* description_format_string()
* description_callback()
*
* These return special markers which will be added to the string and processed
* later after modinfo is complete.
*
* @param bool $full Set true if this is the 'full information' view
* @param bool $not Set true if we are inverting the condition