Merge branch 'MDL-82571_V2' of https://github.com/lostrogit/moodle into main
This commit is contained in:
@@ -892,6 +892,49 @@ final class externallib_test extends externallib_advanced_testcase {
|
||||
'value' => userdate(1580389200),
|
||||
'valueraw' => 1580389200,
|
||||
], reset($course['customfields']));
|
||||
|
||||
// Set the multilang filter to apply to strings + reset filer caches.
|
||||
filter_set_global_state('multilang', TEXTFILTER_ON);
|
||||
filter_set_applies_to_strings('multilang', true);
|
||||
\filter_manager::reset_caches();
|
||||
|
||||
// Let's create a custom field (number), and test the placeholders/multilang display.
|
||||
/** @var core_customfield_generator $cfgenerator */
|
||||
$cfgenerator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
$numberfieldata = [
|
||||
'categoryid' => $fieldcategory->get('id'),
|
||||
'name' => 'Price',
|
||||
'shortname' => 'price',
|
||||
'type' => 'number',
|
||||
'configdata' => [
|
||||
'display' => '{value}',
|
||||
'decimalplaces' => 2,
|
||||
],
|
||||
];
|
||||
|
||||
// Create a number custom field with default display template.
|
||||
$numberfield = $cfgenerator->create_field($numberfieldata);
|
||||
$cfgenerator->add_instance_data($numberfield, $newcourse->id, 15);
|
||||
|
||||
// Create a number custom field with multilang display template.
|
||||
$numberfieldata['name'] = 'Price (multilang)';
|
||||
$numberfieldata['shortname'] = 'pricemultilang';
|
||||
$numberfieldata['configdata']['display'] = '<span lang="en" class="multilang">$ {value}</span>'
|
||||
. '<span lang="es" class="multilang">€ {value}</span>';
|
||||
$numberfield1 = $cfgenerator->create_field($numberfieldata);
|
||||
$cfgenerator->add_instance_data($numberfield1, $newcourse->id, 20);
|
||||
|
||||
$courses = external_api::clean_returnvalue(
|
||||
core_course_external::get_courses_returns(),
|
||||
core_course_external::get_courses(['ids' => [$newcourse->id]])
|
||||
);
|
||||
|
||||
$course = reset($courses);
|
||||
$this->assertCount(3, $course['customfields']);
|
||||
|
||||
// Assert the received number custom fields display placeholders correctly with multilang filter when applied.
|
||||
$this->assertEquals('15.00', $course['customfields'][1]['value']);
|
||||
$this->assertEquals('$ 20.00', $course['customfields'][2]['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,12 +120,8 @@ class data_controller extends \core_customfield\data_controller {
|
||||
* @return string|null
|
||||
*/
|
||||
public function export_value(): ?string {
|
||||
$value = $this->get_value();
|
||||
if ($this->is_empty($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$decimalplaces = (int) $this->get_field()->get_configdata_property('decimalplaces');
|
||||
return format_float((float) $value, $decimalplaces);
|
||||
/** @var field_controller $field */
|
||||
$field = $this->get_field();
|
||||
return $field->prepare_field_for_display($this->get_value(), $this->get_context());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace customfield_number;
|
||||
|
||||
use core\context\system;
|
||||
use core\context;
|
||||
use html_writer;
|
||||
use MoodleQuickForm;
|
||||
|
||||
/**
|
||||
@@ -62,6 +65,29 @@ class field_controller extends \core_customfield\field_controller {
|
||||
$mform->setDefault('configdata[decimalplaces]', 0);
|
||||
}
|
||||
$mform->setType('configdata[decimalplaces]', PARAM_INT);
|
||||
|
||||
// Display format settings.
|
||||
// TODO: Change this after MDL-82996 fixed.
|
||||
$randelname = 'str_' . random_string();
|
||||
$mform->addGroup([], $randelname, html_writer::tag('h4', get_string('headerdisplaysettings', 'customfield_number')));
|
||||
|
||||
// Display template.
|
||||
$mform->addElement('text', 'configdata[display]', get_string('display', 'customfield_number'),
|
||||
['size' => 50]);
|
||||
$mform->setType('configdata[display]', PARAM_TEXT);
|
||||
$mform->addHelpButton('configdata[display]', 'display', 'customfield_number');
|
||||
if ($this->get_configdata_property('display') === null) {
|
||||
$mform->setDefault('configdata[display]', '{value}');
|
||||
}
|
||||
|
||||
// Display when zero.
|
||||
$mform->addElement('text', 'configdata[displaywhenzero]', get_string('displaywhenzero', 'customfield_number'),
|
||||
['size' => 50]);
|
||||
$mform->setType('configdata[displaywhenzero]', PARAM_TEXT);
|
||||
$mform->addHelpButton('configdata[displaywhenzero]', 'displaywhenzero', 'customfield_number');
|
||||
if ($this->get_configdata_property('displaywhenzero') === null) {
|
||||
$mform->setDefault('configdata[displaywhenzero]', 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,6 +100,11 @@ class field_controller extends \core_customfield\field_controller {
|
||||
public function config_form_validation(array $data, $files = []): array {
|
||||
$errors = parent::config_form_validation($data, $files);
|
||||
|
||||
$display = $data['configdata']['display'];
|
||||
if (!preg_match('/\{value}/', $display)) {
|
||||
$errors['configdata[display]'] = get_string('displayvalueconfigerror', 'customfield_number');
|
||||
}
|
||||
|
||||
// Each of these configuration fields are optional.
|
||||
$defaultvalue = $data['configdata']['defaultvalue'] ?? '';
|
||||
$minimumvalue = $data['configdata']['minimumvalue'] ?? '';
|
||||
@@ -103,4 +134,29 @@ class field_controller extends \core_customfield\field_controller {
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a value for export
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param context|null $context
|
||||
* @return string|null
|
||||
*/
|
||||
public function prepare_field_for_display(mixed $value, ?context $context = null): ?string {
|
||||
if ((float)$value == 0) {
|
||||
$value = $this->get_configdata_property('displaywhenzero');
|
||||
if ((string) $value === '') {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// Let's format the value.
|
||||
$decimalplaces = (int) $this->get_configdata_property('decimalplaces');
|
||||
$value = format_float((float) $value, $decimalplaces);
|
||||
|
||||
// Apply the display format.
|
||||
$format = $this->get_configdata_property('display');
|
||||
$value = str_replace('{value}', $value, $format);
|
||||
}
|
||||
return format_string($value, true, ['context' => $context ?? system::instance()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$string['decimalplaces'] = 'Decimal places';
|
||||
$string['defaultvalueconfigerror'] = 'Default value must be between minimum and maximum';
|
||||
$string['display'] = 'Display template';
|
||||
$string['display_help'] = 'How to display the value of the field. Use the following placeholders:
|
||||
|
||||
* **{value}** - display value in a general format (float with decimals configured in the field)
|
||||
* **$ {value}** - price in dollars
|
||||
* **{value} hrs** - duration in hours';
|
||||
$string['displayvalueconfigerror'] = 'The placeholder is not invalid';
|
||||
$string['displaywhenzero'] = 'Display when zero';
|
||||
$string['displaywhenzero_help'] = 'How to display the field value when the value is "0". For example, in case of a price you can display the word "Free" but in case of the duration you may want to leave it empty since it means that the duration was not estimated.
|
||||
|
||||
Leave empty if you do not want to display anything at all when the value is set to "0".';
|
||||
$string['headerdisplaysettings'] = 'Display format';
|
||||
$string['maximumvalue'] = 'Maximum value';
|
||||
$string['maximumvalueerror'] = 'Value must be less than or equal to {$a}';
|
||||
$string['minimumvalue'] = 'Minimum value';
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
@customfield @customfield_number @javascript
|
||||
Feature: Managers can manage course custom fields number
|
||||
In order to have additional data on the course
|
||||
As a manager
|
||||
I need to create, edit, remove and display number custom fields
|
||||
|
||||
Background:
|
||||
Given the following "custom field categories" exist:
|
||||
| name | component | area | itemid |
|
||||
| Category for test | core_course | course | 0 |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Courses > Default settings > Course custom fields" in site administration
|
||||
|
||||
Scenario: Create a custom course number field
|
||||
When I click on "Add a new custom field" "link"
|
||||
And I click on "Number" "link"
|
||||
When I set the following fields to these values:
|
||||
| Name | Number field |
|
||||
| Short name | numberfield |
|
||||
| Display template | test |
|
||||
And I click on "Save changes" "button" in the "Adding a new Number" "dialogue"
|
||||
Then I should see "The placeholder is not invalid"
|
||||
And I set the following fields to these values:
|
||||
| Name | Number field |
|
||||
| Short name | numberfield |
|
||||
| Display template | {value} |
|
||||
And I click on "Save changes" "button" in the "Adding a new Number" "dialogue"
|
||||
And I should see "Number field"
|
||||
And I log out
|
||||
|
||||
Scenario: Edit a custom course number field
|
||||
When I click on "Add a new custom field" "link"
|
||||
And I click on "Number" "link"
|
||||
And I set the following fields to these values:
|
||||
| Name | Number field |
|
||||
| Short name | numberfield |
|
||||
And I click on "Save changes" "button" in the "Adding a new Number" "dialogue"
|
||||
Then I should see "Number field"
|
||||
And I click on "Edit" "link" in the "Number field" "table_row"
|
||||
And I set the following fields to these values:
|
||||
| Name | Edited number field |
|
||||
And I click on "Save changes" "button" in the "Updating Number field" "dialogue"
|
||||
Then I should see "Edited number field"
|
||||
And I log out
|
||||
|
||||
Scenario: Delete a custom course number field
|
||||
When I click on "Add a new custom field" "link"
|
||||
And I click on "Number" "link"
|
||||
And I set the following fields to these values:
|
||||
| Name | Number field |
|
||||
| Short name | numberfield |
|
||||
And I click on "Save changes" "button" in the "Adding a new Number" "dialogue"
|
||||
And I click on "Delete" "link" in the "Number field" "table_row"
|
||||
And I click on "Yes" "button" in the "Confirm" "dialogue"
|
||||
And I wait until the page is ready
|
||||
And I wait until "Number field" "text" does not exist
|
||||
Then I should not see "Number field"
|
||||
And I log out
|
||||
|
||||
Scenario Outline: A number field must shown correctly on course listing
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | Example 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And I navigate to "Courses > Default settings > Course custom fields" in site administration
|
||||
And I click on "Add a new custom field" "link"
|
||||
And I click on "Number" "link"
|
||||
When I set the following fields to these values:
|
||||
| Name | Test number |
|
||||
| Short name | testnumber |
|
||||
| Decimal places | 2 |
|
||||
| Display template | <template> |
|
||||
| Display when zero | <whenzero> |
|
||||
And I click on "Save changes" "button" in the "Adding a new Number" "dialogue"
|
||||
And I log out
|
||||
Then I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Test number | <fieldvalue> |
|
||||
And I press "Save and display"
|
||||
And I am on site homepage
|
||||
And I should see "Test number" in the ".customfields-container .customfieldname" "css_element"
|
||||
And I should see "<expectedvalue>" in the ".customfields-container .customfieldvalue" "css_element"
|
||||
Examples:
|
||||
| template | whenzero | fieldvalue | expectedvalue |
|
||||
| $ {value} | 0 | 150 | $ 150.00 |
|
||||
| {value} | Free | 0 | Free |
|
||||
@@ -121,22 +121,66 @@ final class data_controller_test extends advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exporting instance
|
||||
* Data provider for {@see test_export_value}
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function test_export_value(): void {
|
||||
public static function export_value_provider(): array {
|
||||
$template = '<span class="multilang" lang="en">$ {value}</span><span class="multilang" lang="es">€ {value}</span>';
|
||||
$whenzero = '<span class="multilang" lang="en">Unknown</span><span class="multilang" lang="es">Desconocido</span>';
|
||||
return [
|
||||
'Export float value' => [42, 42.0, [
|
||||
'decimalplaces' => 2,
|
||||
'display' => '{value}',
|
||||
'displaywhenzero' => 0],
|
||||
],
|
||||
'Export value with a prefix' => [10, '$ 10.00', [
|
||||
'decimalplaces' => 2,
|
||||
'display' => $template,
|
||||
'displaywhenzero' => 0],
|
||||
],
|
||||
'Export value when zero' => [0, 'Unknown', [
|
||||
'display' => '{value}',
|
||||
'displaywhenzero' => $whenzero],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exporting instance
|
||||
*
|
||||
* @param float|string $datavalue
|
||||
* @param float|string $expectedvalue
|
||||
* @param array $configdata
|
||||
*
|
||||
* @dataProvider export_value_provider
|
||||
*/
|
||||
public function test_export_value(
|
||||
float|string $datavalue,
|
||||
float|string $expectedvalue,
|
||||
array $configdata,
|
||||
): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// Enable multilang filter.
|
||||
filter_set_global_state('multilang', TEXTFILTER_ON);
|
||||
filter_set_applies_to_strings('multilang', true);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
/** @var core_customfield_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
|
||||
$category = $generator->create_category();
|
||||
$field = $generator->create_field(['categoryid' => $category->get('id'), 'type' => 'number']);
|
||||
$data = $generator->add_instance_data($field, (int) $course->id, 42);
|
||||
$field = $generator->create_field([
|
||||
'categoryid' => $category->get('id'),
|
||||
'type' => 'number',
|
||||
'configdata' => $configdata,
|
||||
]);
|
||||
$data = $generator->add_instance_data($field, (int) $course->id, $datavalue);
|
||||
|
||||
$result = \core_customfield\data_controller::create($data->get('id'))->export_value();
|
||||
$this->assertEquals(42.0, $result);
|
||||
$this->assertEquals($expectedvalue, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +55,13 @@ final class field_controller_test extends advanced_testcase {
|
||||
*/
|
||||
public static function form_definition_provider(): array {
|
||||
return [
|
||||
'Defaults' => ['', '', '', true],
|
||||
'Minimum greater than maximum' => ['', 12, 10, false],
|
||||
'Default value less than minimum' => [1, 10, 12, false],
|
||||
'Default value greater than maximum' => [13, 10, 12, false],
|
||||
'Valid' => [11, 10, 12, true],
|
||||
'Defaults' => ['', '', '', '{value}', true],
|
||||
'Minimum greater than maximum' => ['', 12, 10, '{value}', false],
|
||||
'Default value less than minimum' => [1, 10, 12, '{value}', false],
|
||||
'Default value greater than maximum' => [13, 10, 12, '{value}', false],
|
||||
'Valid' => [11, 10, 12, '{value}', true],
|
||||
'Display valid single placeholder' => ['', '', '', '{value}', true],
|
||||
'Display invalid single placeholder' => ['', '', '', '111', false],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -69,6 +71,7 @@ final class field_controller_test extends advanced_testcase {
|
||||
* @param float|string $defaultvalue
|
||||
* @param float|string $minimumvalue
|
||||
* @param float|string $maximumvalue
|
||||
* @param string $display
|
||||
* @param bool $expected
|
||||
*
|
||||
* @dataProvider form_definition_provider
|
||||
@@ -77,6 +80,7 @@ final class field_controller_test extends advanced_testcase {
|
||||
float|string $defaultvalue,
|
||||
float|string $minimumvalue,
|
||||
float|string $maximumvalue,
|
||||
string $display,
|
||||
bool $expected,
|
||||
): void {
|
||||
$this->resetAfterTest();
|
||||
@@ -93,6 +97,7 @@ final class field_controller_test extends advanced_testcase {
|
||||
'defaultvalue' => $defaultvalue,
|
||||
'minimumvalue' => $minimumvalue,
|
||||
'maximumvalue' => $maximumvalue,
|
||||
'display' => $display,
|
||||
]);
|
||||
|
||||
$formdata = field_config_form::mock_ajax_submit($submitdata);
|
||||
|
||||
Reference in New Issue
Block a user