diff --git a/availability/condition/completion/tests/behat/conditional_bug.feature b/availability/condition/completion/tests/behat/conditional_bug.feature
index db2511605ee..1bc44584e78 100644
--- a/availability/condition/completion/tests/behat/conditional_bug.feature
+++ b/availability/condition/completion/tests/behat/conditional_bug.feature
@@ -44,6 +44,7 @@ Feature: Confirm that conditions on completion no longer cause a bug
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I set the field with xpath "//div[contains(concat(' ', normalize-space(@class), ' '), ' availability-item ')][preceding-sibling::div]//select[@name='cm']" to "Page2"
And I press "Save and return to course"
+ And I click on "Show more" "button" in the "#section-1 .availabilityinfo" "css_element"
Then I should see "Not available unless:" in the ".activity.glossary" "css_element"
And I should see "The activity Page1 is marked complete" in the ".activity.glossary" "css_element"
And I should see "The activity Page2 is marked complete" in the ".activity.glossary" "css_element"
diff --git a/availability/tests/behat/display_availability.feature b/availability/tests/behat/display_availability.feature
index 5998d033316..b2a5d3ed045 100644
--- a/availability/tests/behat/display_availability.feature
+++ b/availability/tests/behat/display_availability.feature
@@ -73,13 +73,17 @@ Feature: display_availability
And I should see "2013" in the "#section-1 .availabilityinfo" "css_element"
And I should see "2013" in the "#section-1 .availabilityinfo" "css_element"
And "li" "css_element" should not exist in the "#section-1 .availabilityinfo" "css_element"
+ And "Show more" "button" should not exist in the "#section-1 .availabilityinfo" "css_element"
# Page 2 should show in list format.
And "li" "css_element" should exist in the "#section-2 .availabilityinfo" "css_element"
And I should see "Not available unless:" in the "#section-2 .availabilityinfo" "css_element"
And I should see "It is before" in the "#section-2 .availabilityinfo" "css_element"
And I should see "hidden otherwise" in the "#section-2 .availabilityinfo" "css_element"
+ And I click on "Show more" "button" in the "Page 2" "activity"
And I should see "Email address" in the "#section-2 .availabilityinfo" "css_element"
+ And I click on "Show less" "button" in the "#section-2 .availabilityinfo" "css_element"
+ And I should not see "Email address" in the "#section-2 .availabilityinfo" "css_element"
# Page 3 should not have available info.
And "#section-3 .availabilityinfo" "css_element" should not exist
@@ -114,6 +118,11 @@ Feature: display_availability
And I click on "Date" "button" in the "Add restriction..." "dialogue"
And I set the field "direction" to "until"
And I set the field "x[year]" to "2013"
+ And I press "Add restriction..."
+ And I click on "User profile" "button" in the "Add restriction..." "dialogue"
+ And I set the field "User profile field" to "Email address"
+ And I set the field "Value to compare against" to "email@example.com"
+ And I set the field "Method of comparison" to "is equal to"
And I press "Save changes"
# Section 2 is the same but hidden from students
@@ -130,7 +139,7 @@ Feature: display_availability
And I am on "Course 1" course homepage
# Check display
- Then I should see "Available until" in the "#section-1 .availabilityinfo" "css_element"
+ Then I should see "Not available unless" in the "#section-1 .availabilityinfo" "css_element"
And I should see "Available until" in the "#section-2 .availabilityinfo" "css_element"
And I should see "hidden otherwise" in the "#section-2 .availabilityinfo" "css_element"
@@ -144,7 +153,11 @@ Feature: display_availability
# Section 1 should be visible and show info.
And I should see "Topic 1" in the "region-main" "region"
- And I should see "Available until" in the "#section-1 .availabilityinfo" "css_element"
+ And I should see "Not available unless" in the "#section-1 .availabilityinfo" "css_element"
+ And I click on "Show more" "button" in the "#section-1 .availabilityinfo" "css_element"
+ And I should see "Email address" in the "#section-1 .availabilityinfo" "css_element"
+ And I click on "Show less" "button" in the "#section-1 .availabilityinfo" "css_element"
+ And I should not see "Email address" in the "#section-1 .availabilityinfo" "css_element"
# Section 2 should not be available at all
And I should not see "Topic 2" in the "region-main" "region"
diff --git a/course/format/classes/output/local/content/cm/availability.php b/course/format/classes/output/local/content/cm/availability.php
index dbe249f6e01..9776c9eccfc 100644
--- a/course/format/classes/output/local/content/cm/availability.php
+++ b/course/format/classes/output/local/content/cm/availability.php
@@ -108,11 +108,7 @@ class availability extends section_avalability {
}
$info = [];
- $formattedinfo = \core_availability\info::format_info(
- $this->mod->availableinfo,
- $this->mod->get_course()
- );
- $info[] = $this->availability_info($formattedinfo, 'isrestricted');
+ $info[] = $this->get_availability_data($output, $this->mod->availableinfo, 'isrestricted');
return $info;
}
@@ -151,11 +147,7 @@ class availability extends section_avalability {
if (!$mod->visible) {
$hidinfoclass .= ' hide';
}
- $formattedinfo = info::format_info(
- $fullinfo,
- $mod->get_course()
- );
- $info[] = $this->availability_info($formattedinfo, $hidinfoclass);
+ $info[] = $this->get_availability_data($output, $fullinfo, $hidinfoclass);
return $info;
}
diff --git a/course/format/classes/output/local/content/section/availability.php b/course/format/classes/output/local/content/section/availability.php
index a183aa3eed2..2d24ff1728c 100644
--- a/course/format/classes/output/local/content/section/availability.php
+++ b/course/format/classes/output/local/content/section/availability.php
@@ -25,6 +25,7 @@
namespace core_courseformat\output\local\content\section;
use context_course;
+use core_availability_multiple_messages;
use core\output\named_templatable;
use core_availability\info;
use core_availability\info_section;
@@ -57,6 +58,9 @@ class availability implements named_templatable, renderable {
/** @var stdClass|null the instance export data */
protected $data = null;
+ /** @var int Availability excerpt text max size treshold */
+ protected const AVAILABILITY_EXCERPT_MAXSIZE = 100;
+
/**
* Constructor.
*
@@ -124,7 +128,7 @@ class availability implements named_templatable, renderable {
* are going to be unavailable etc). This logic is the same as for
* activities.
*
- * @param renderer_base $output typically, the renderer that's calling this function
+ * @param \renderer_base $output typically, the renderer that's calling this function
* @return stdclass data context for a mustache template
*/
protected function get_info(\renderer_base $output): array {
@@ -142,30 +146,115 @@ class availability implements named_templatable, renderable {
if ($section->availableinfo) {
// Note: We only get to this function if availableinfo is non-empty,
// so there is definitely something to print.
- $formattedinfo = info::format_info($section->availableinfo, $section->course);
- $info[] = $this->availability_info($formattedinfo, 'isrestricted');
+ $info[] = $this->get_availability_data($output, $section->availableinfo, 'isrestricted');
}
} else if ($canviewhidden && !empty($CFG->enableavailability)) {
// Check if there is an availability restriction.
$ci = new info_section($section);
$fullinfo = $ci->get_full_information();
if ($fullinfo) {
- $formattedinfo = info::format_info($fullinfo, $section->course);
- $info[] = $this->availability_info($formattedinfo, 'isrestricted isfullinfo');
+ $info[] = $this->get_availability_data($output, $fullinfo, 'isrestricted isfullinfo');
}
}
return $info;
}
+ /**
+ * Get the basic availability information data.
+ *
+ * @param \renderer_base $output typically, the renderer that's calling this function
+ * @param string|core_availability_multiple_messages $availabilityinfo the avalability info
+ * @param string $additionalclasses additional css classes
+ * @return stdClass the availability information data
+ */
+ protected function get_availability_data($output, $availabilityinfo, $additionalclasses = ''): stdClass {
+ // At this point, availabilityinfo is either a string or a renderable. We need to handle both cases in a different way.
+ if (is_string($availabilityinfo)) {
+ $data = $this->availability_info_from_string($output, $availabilityinfo);
+ } else {
+ $data = $this->availability_info_from_output($output, $availabilityinfo);
+ }
+
+ $data->classes = $additionalclasses;
+
+ $additionalclasses = array_filter(explode(' ', $additionalclasses));
+ if (in_array('ishidden', $additionalclasses)) {
+ $data->ishidden = 1;
+ } else if (in_array('isstealth', $additionalclasses)) {
+ $data->isstealth = 1;
+ } else if (in_array('isrestricted', $additionalclasses)) {
+ $data->isrestricted = 1;
+ if (in_array('isfullinfo', $additionalclasses)) {
+ $data->isfullinfo = 1;
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Generate the basic availability information data from a string.
+ * Just shorten availability text to generate the excerpt text.
+ *
+ * @param \renderer_base $output typically, the renderer that's calling this function
+ * @param string $availabilityinfo the avalability info
+ * @return stdClass the availability information data
+ */
+ protected function availability_info_from_string(\renderer_base $output, string $availabilityinfo): stdClass {
+ $course = $this->format->get_course();
+
+ $text = info::format_info($availabilityinfo, $course);
+ $data = ['text' => $text];
+
+ if (strlen(html_to_text($text)) > self::AVAILABILITY_EXCERPT_MAXSIZE) {
+ $data['excerpt'] = shorten_text($text, self::AVAILABILITY_EXCERPT_MAXSIZE);
+ }
+
+ return (object) $data;
+ }
+
+ /**
+ * Generate the basic availability information data from a renderable.
+ * Use the header and the first item to generate the excerpt text.
+ *
+ * @param \renderer_base $output typically, the renderer that's calling this function
+ * @param core_availability_multiple_messages $availabilityinfo the avalability info
+ * @return stdClass the availability information data
+ */
+ protected function availability_info_from_output(
+ \renderer_base $output,
+ core_availability_multiple_messages $availabilityinfo
+ ): stdClass {
+ $course = $this->format->get_course();
+
+ $renderable = new \core_availability\output\availability_info($availabilityinfo);
+ // We need to export_for_template() instead of directly render, to reuse the info for both 'text' and 'excerpt'.
+ $info = $renderable->export_for_template($output);
+
+ $text = $output->render_from_template('core_availability/availability_info', $info);
+ $data = ['text' => info::format_info($text, $course)];
+
+ if (!empty($info->items)) {
+ $excerpttext = $info->header . ' ' . $info->items[0]->header;
+ $data['excerpt'] = info::format_info($excerpttext, $course);
+ }
+
+ return (object) $data;
+ }
+
/**
* Generate the basic availability information data.
*
+ * @deprecated since Moodle 4.3 MDL-78204. Please use {@see self::get_availability_data} instead.
+ * @todo MDL-78489 This will be deleted in Moodle 4.7.
* @param string $text the formatted avalability text
* @param string $additionalclasses additional css classes
* @return stdClass the availability information data
*/
protected function availability_info($text, $additionalclasses = ''): stdClass {
+ debugging('Use of ' . __FUNCTION__ . '() have been deprecated, ' .
+ 'please use core_courseformat\output\local\content\section\availability::get_availability_data()', DEBUG_DEVELOPER);
$data = (object)[
'text' => $text,
diff --git a/course/format/templates/local/content/availability.mustache b/course/format/templates/local/content/availability.mustache
new file mode 100644
index 00000000000..1e899660226
--- /dev/null
+++ b/course/format/templates/local/content/availability.mustache
@@ -0,0 +1,43 @@
+{{!
+ 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