Skip to content

Commit

Permalink
Merge branch 'MDL-82571_V2' of https://github.com/lostrogit/moodle in…
Browse files Browse the repository at this point in the history
…to main
  • Loading branch information
paulholden committed Sep 4, 2024
2 parents 445fe37 + 241fa42 commit cbcb9d0
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 16 deletions.
43 changes: 43 additions & 0 deletions course/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,49 @@ public function test_get_courses_customfields(): void {
'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']);
}

/**
Expand Down
10 changes: 3 additions & 7 deletions customfield/field/number/classes/data_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,8 @@ public function get_default_value(): ?float {
* @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());
}
}
56 changes: 56 additions & 0 deletions customfield/field/number/classes/field_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

namespace customfield_number;

use core\context\system;
use core\context;
use html_writer;
use MoodleQuickForm;

/**
Expand Down Expand Up @@ -62,6 +65,29 @@ public function config_form_definition(MoodleQuickForm $mform): void {
$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);
}
}

/**
Expand All @@ -74,6 +100,11 @@ public function config_form_definition(MoodleQuickForm $mform): void {
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'] ?? '';
Expand Down Expand Up @@ -103,4 +134,29 @@ public function config_form_validation(array $data, $files = []): array {

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()]);
}
}
12 changes: 12 additions & 0 deletions customfield/field/number/lang/en/customfield_number.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@

$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';
Expand Down
93 changes: 93 additions & 0 deletions customfield/field/number/tests/behat/field.feature
Original file line number Diff line number Diff line change
@@ -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 |
52 changes: 48 additions & 4 deletions customfield/field/number/tests/data_controller_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,67 @@ public function test_form_save(): void {
$category->get_handler()->instance_form_save($formsubmission);
}

/**
* Data provider for {@see test_export_value}
*
* @return array[]
*/
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(): void {
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);
}
}
15 changes: 10 additions & 5 deletions customfield/field/number/tests/field_controller_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ public function test_create(): void {
*/
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],
];
}

Expand All @@ -69,6 +71,7 @@ public static function form_definition_provider(): array {
* @param float|string $defaultvalue
* @param float|string $minimumvalue
* @param float|string $maximumvalue
* @param string $display
* @param bool $expected
*
* @dataProvider form_definition_provider
Expand All @@ -77,6 +80,7 @@ public function test_form_definition(
float|string $defaultvalue,
float|string $minimumvalue,
float|string $maximumvalue,
string $display,
bool $expected,
): void {
$this->resetAfterTest();
Expand All @@ -93,6 +97,7 @@ public function test_form_definition(
'defaultvalue' => $defaultvalue,
'minimumvalue' => $minimumvalue,
'maximumvalue' => $maximumvalue,
'display' => $display,
]);

$formdata = field_config_form::mock_ajax_submit($submitdata);
Expand Down

0 comments on commit cbcb9d0

Please sign in to comment.