From 96968f80b1b6f7cc7db5a950a9582bbb911e0aed Mon Sep 17 00:00:00 2001 From: Kordan Date: Tue, 12 Mar 2024 16:04:12 +0100 Subject: [PATCH 1/2] This PR contains the content of three major improvements achieved in the last two months. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those three improvements can be described as follows: 1. translation of the content and content_format fields from the item plugin specific tables (surveypro(field|format)_itemplugin) to the parent table (surveypro_item). This first result is described in the content_among_basics branch (https://github.com/kordan/moodle-mod_surveypro/tree/content_among_basics). I have never created a pull request for this branch because I have never been able to perform a rebase that satisfied me. In practice: the method, named in master "item_add_mandatory_base_fields" was renamed in the branch to "item_add_defaults_for_base_fields". By rebasing content_among_basics on master the rename of the method was discarded so, after the rebase, I still found the original name. I spent a few days trying to understand the reason for this behavior. I asked my colleagues and then abandoned the problem. 2. translation of the most frequent properties (among all item plugins) from the specific item plugin tables (surveypro(field|format)_itemplugin) to the parent table (surveypro_item). This second step is clearly the natural continuation of the previous one and, for this reason, I created this new branch (https://github.com/kordan/moodle-mod_surveypro/tree/others_to_base_property) on top of content_among_basics. 3. Once I had a clear idea of how the itemplugin attributes were managed, I finally proceeded to adapt surveypro to php8.2 by creating the php8.2 branch. Obviously this branch was created on top of others_to_base_propertye, consequently, the php8.2 merge makes the first two branches useless. The outcome of "content_among_basics" is described in (1). The outcome of "others_to_base_property" is described in (2). The outcome of "php8.2" is described in (3). ===================================================== (1) Content and contentformat moved among base fields As part of a work of standardization and modernization of the module aimed at making the code homogeneous and, consequently, easily understandable and modifiable, I realized that the use of PHP 8.2 highlights a significant and very long series of errors that I must absolutely address. The first error among these is that the class of each item (item = fields + format) must have its own properties that it must manage on its own. But to define the list of properties of each item I have to decide which properties to consider "common" to all items and which to consider "specific" to each individual item. There are two reflections related to this problem: - Theoretically there are very few properties common to all items. Among these I only see: hidden, insearchform and reserved. All the others cannot be common to ALL items because, for example, the "pagebreak" item only has these three properties just mentioned; I already accepted this "lack" of properties ACTUALLY common to all items when I chose to create the itemsetup form (the form to setup a new item for the surveypro) from the union of a "item_setupbaseform" and an "itemsetupform". The item_setupbaseform has the fields it has and each item has a rule that says what it wants in its form and what it doesn't want to appear. (Each item defines a static vector called insetupform which declares what it wants to appear in the item_setupbaseform and what not. Obviously there is no similar vector for the specific form of each item because, having been created for the single item, it contains only and exclusively whatever you want.) I therefore realize that the answer to the question: which properties must be classified as "common" to all items and which, instead, must be classified as "specific" of each individual item is in the list of fields that I included, 10 years ago, in the "item_setupbaseform" and in the "itemsetupform". So in order to make the code more homogeneous and self-consistent, I have to start moving all the "common" fields from the tables of each individual item ('surveypro'.$type.'_'.$plugin) to the surveypro_item table. The two most difficult fields to move are 'content' and 'contentformat'. This is the reason that led me to this PR. - I lose compatibility with the past. I will write somewhere that if you want to keep your usertemplates and mastertemplates, you need to: -- before upgrading surveypro you have to load each usertemplate and mastertemplate into a course; -- upgrade your surveypro; -- regenerate each usertemplate and each mastertemplate. obviously the next PR I will make will relate to moving the other "common" properties from the specific tables to the surveypro_item table (and I will create them on top of this one). ===================================================== (2) Each common propery is now saved to surveypro_item When "content_among_basics" (that saves content and contentformat to surveypro_item and no longer into db tables of item plugins) and this PR will land to mastwer, I hope all will be ready to start to modify surveypro to let it correctly run in php8.2 and 8.3. With this PR the situation of properties should be: ``` | AGE | AUTOFILL | BOOLEAN | CHARACTER | CHECKBOX | DATE | DATETIME | FILEUPLOAD | INTEGER | MULTISELECT | NUMERIC | RADIOBUTTON | RATE | RECURRENCE | SELECT | SHORTDATE | TEXTAREA | TIME | FIELDSET | FIELDSETEND | LABEL | PAGEBREAK | id (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | surveyproid (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | type (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | plugin (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | content | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | √ | NO | contentformat | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | required | √ | NO | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | indent | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | position | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | customnumber | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | hideinstructions | √ | NO | NO | √ | √ | √ | √ | NO | √ | √ | √ | NO | √ | √ | NO | √ | √ | √ | NO | NO | NO | NO | variable | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | extranote | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | hidden | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | insearchform | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | reserved | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | sortindex (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | formpage (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | parentid | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | parentvalue | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | timecreated (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | timemodified (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– ``` All the properties in the first column are relative to a field of the table surveypro_item. All the properties in the first column correspond to a field of the item_setupbaseform that is the initial part of each itemsetupform. Not all the items use ALL of that properties. They declare the use of each property throught $this->insetupform[] = (false|true); If $this->insetupform[] == false, the corresponding field in the formbase is not displayed in item_setupbaseform (and the useless default goes into the database). Marked with (h) are properties hidden to user. In the next table the list of specific properties item per item. These properties are save in surveypro(field|format)_. Yes, some of them coincide, but the number of plugins sharing the same property is too low and even the semantic is too specific of each single plugin so I decided to save these properties among the fields of the child table and not in surveypro_item. ``` | AGE | AUTOFILL | BOOLEAN | CHARACTER | CHECKBOX | DATE | DATETIME | FILEUPLOAD | INTEGER | MULTISELECT | NUMERIC | RADIOBUTTON | RATE | RECURRENCE | SELECT | SHORTDATE | TEXTAREA | TIME | FIELDSET | FIELDSETEND | LABEL | PAGEBREAK | –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– | defaultoption | hiddenfield | defaultoption | trimonsave | options | defaultoption | step | maxfiles | defaultoption | options | defaultvalue | options | options | defaultoption | options | defaultoption | trimonsave | step | defaultstatus | | fullwidth | | defaultvalue | element01 | defaultvalue | defaultvalue | labelother | defaultvalue | defaultvalue | maxbytes | defaultvalue | defaultvalue | signed | labelother | rates | defaultvalue | labelother | defaultvalue | useeditor | defaultoption | | leftlabel | | lowerbound | element02 | downloadformat | pattern | defaultvalue | downloadformat | defaultvalue | filetypes | lowerbound | noanswerdefault | lowerbound | defaultoption | defaultoption | downloadformat | defaultoption | downloadformat | arearows | defaultvalue | | upperbound | element03 | style | minlength | noanswerdefault | lowerbound | downloadformat | | upperbound | downloadformat | upperbound | defaultvalue | defaultvalue | lowerbound | defaultvalue | lowerbound | areacols | downloadformat | | element04 | | maxlength | downloadformat | upperbound | lowerbound | | minimumrequired | decimals | downloadformat | downloadformat | upperbound | downloadformat | upperbound | minlength | lowerbound | | element05 | | minimumrequired | | upperbound | | maximumrequired | | adjustment | style | | maxlength | upperbound | | maximumrequired | | heightinrows | | differentrates | | adjustment | ``` ===================================================== (3) php8.2 This improvement makes surveypro compatible with php8.2. There is some small problem, however, that I don't understand and which, for this reason, I describe below. (a) I see a theoretical problem that I believe is closely related to my request for help in: https://moodle.org/mod/forum/discuss.php?d=457241 The problem that php8.2 raises is practically always linked to the fact that I can not evaluate a property without first declare it. One of the properties common to all surveypro items is "content" (alias, the content of the question) followed by the content_format. To define an item via the corresponding form at submission time, the HTML editor is processed through file_prepare_standard_editor that changes the content_editor property. When I pass the object $item to the file_prepare_standard_editor method, php8.2 raises an exception claiming that the content_editor property (that I must have defined previously) and that I have defined as protected cannot be modified because it is protected. I know it is a good practice to always define properties as protected so my question is: How should I behave? Do I have to make the property public? (b) Furthermore, but this is a completely secondary detail, protected $content_editor is considered an error by Code Checker. ``` FILE: /home/runner/work/moodle-mod_surveypro/moodle-mod_surveypro/moodle/mod/surveypro/classes/itembase.php 93 | ERROR | [x] Member variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.MemberNameUnderscore) 1128 | ERROR | [x] Variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.VariableNameUnderscore) 1129 | ERROR | [x] Variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.VariableNameUnderscore) ``` (c) In php8.2 and moodle master, I frequently get the error "Javascript code and/or AJAX requests are not ready after 10 seconds". At my eyes, it seems related to TinyMCE editor. Executing a submission of the item_setupbaseform with values that inhibit the submission itself, when the form is reloaded it is impossible to paste something in the content textarea. (d) I'm having a problem with style sheets. Moodle 4.4 defines the style class: ``` .mb-3, .my-3 { margin-bottom: 1rem !important; } ``` To override this class I am forced to use: ``` .path-mod-surveypro #userentry .mb-3, .path-mod-surveypro #usersearch .mb-3 { margin-bottom: 0 !important; } ``` specifying NECESSARILY !important to be able to override the parent class. The "!important" specification, however, is classified by Grunt (in the context of the GHA) as an error: ``` mod/surveypro/styles.css 28:22 ✖ Unexpected !important declaration-no-important 348:24 ✖ Unexpected !important declaration-no-important 356:24 ✖ Unexpected !important declaration-no-important 361:24 ✖ Unexpected !important declaration-no-important 366:22 ✖ Unexpected !important declaration-no-important 374:22 ✖ Unexpected !important declaration-no-important 379:22 ✖ Unexpected !important declaration-no-important 384:24 ✖ Unexpected !important declaration-no-important 392:24 ✖ Unexpected !important declaration-no-important 397:24 ✖ Unexpected !important declaration-no-important 402:22 ✖ Unexpected !important declaration-no-important 409:22 ✖ Unexpected !important declaration-no-important 414:22 ✖ Unexpected !important declaration-no-important 419:24 ✖ Unexpected !important declaration-no-important 426:24 ✖ Unexpected !important declaration-no-important 431:24 ✖ Unexpected !important declaration-no-important 436:22 ✖ Unexpected !important declaration-no-important 443:22 ✖ Unexpected !important declaration-no-important 448:22 ✖ Unexpected !important declaration-no-important 453:25 ✖ Unexpected !important declaration-no-important 460:25 ✖ Unexpected !important declaration-no-important 465:25 ✖ Unexpected !important declaration-no-important 470:23 ✖ Unexpected !important declaration-no-important 477:23 ✖ Unexpected !important declaration-no-important 482:23 ✖ Unexpected !important declaration-no-important 487:25 ✖ Unexpected !important declaration-no-important 494:25 ✖ Unexpected !important declaration-no-important 499:25 ✖ Unexpected !important declaration-no-important 28 problems (28 errors, 0 warnings) ``` --- .github/workflows/moodle-ci.yml | 6 +- TODO.txt | 20 +- backup/moodle2/backup_surveypro_stepslib.php | 20 +- classes/event/submission_created.php | 2 +- classes/event/submission_modified.php | 2 +- classes/event/submission_viewed.php | 2 +- classes/formbase.php | 7 +- classes/itembase.php | 1354 ++++++++---- classes/layout_branchingvalidation.php | 5 +- classes/layout_itemlist.php | 90 +- classes/layout_itemsetup.php | 4 +- classes/local/form/item_chooser.php | 6 +- classes/local/form/item_setupbaseform.php | 22 +- classes/local/form/mtemplate_applyform.php | 6 +- classes/local/form/mtemplate_createform.php | 4 + ...usersearch.php => response_searchform.php} | 18 +- .../{userform.php => response_submitform.php} | 180 +- classes/local/form/utemplate_importform.php | 5 +- classes/local/ipe/layout_customnumber.php | 5 +- classes/local/ipe/layout_required.php | 5 +- classes/local/ipe/layout_variable.php | 12 +- classes/mtemplate_apply.php | 134 +- classes/mtemplate_save.php | 229 +- classes/output/action_bar.php | 8 +- classes/plugininfo/surveyprofield.php | 6 +- classes/plugininfo/surveyproformat.php | 6 +- classes/privacy/provider.php | 2 +- classes/templatebase.php | 286 ++- classes/tools_export.php | 7 +- classes/tools_import.php | 10 +- classes/utemplate_apply.php | 191 +- classes/utemplate_import.php | 16 - classes/utemplate_manage.php | 28 +- classes/utemplate_save.php | 114 +- classes/utility_layout.php | 4 +- classes/utility_mform.php | 66 - classes/view_cover.php | 2 +- ...bmissionlist.php => view_responselist.php} | 55 +- ...sionsearch.php => view_responsesearch.php} | 6 +- ...issionform.php => view_responsesubmit.php} | 202 +- db/access.php | 4 +- db/install.xml | 9 + db/upgrade.php | 86 + ...kup_surveyprofield_age_subplugin.class.php | 5 +- field/age/classes/item.php | 446 ++-- field/age/db/install.xml | 31 +- field/age/db/upgrade.php | 62 + field/age/lang/en/surveyprofield_age.php | 12 +- field/age/lang/it/surveyprofield_age.php | 43 + field/age/tests/behat/itemform.feature | 4 +- field/age/tests/behat/submit_age.feature | 4 +- .../tests/behat/use_advanced_elements.feature | 8 +- ...2023103100.xml => age_only_2024032800.xml} | 228 +- field/age/version.php | 4 +- ...urveyprofield_autofill_subplugin.class.php | 5 +- field/autofill/classes/item.php | 518 +++-- field/autofill/db/install.xml | 34 +- field/autofill/db/upgrade.php | 65 +- .../lang/en/surveyprofield_autofill.php | 6 +- ...23000.xml => autofill_only_2024032800.xml} | 52 +- field/autofill/version.php | 4 +- ...surveyprofield_boolean_subplugin.class.php | 5 +- field/boolean/classes/item.php | 298 ++- field/boolean/db/install.xml | 30 +- field/boolean/db/upgrade.php | 63 +- .../lang/en/surveyprofield_boolean.php | 8 +- field/boolean/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_boolean.feature | 4 +- ...123000.xml => boolean_only_2024032800.xml} | 341 +-- field/boolean/version.php | 4 +- ...rveyprofield_character_subplugin.class.php | 5 +- field/character/classes/item.php | 349 +-- field/character/classes/itemsetupform.php | 19 +- field/character/db/install.xml | 32 +- field/character/db/upgrade.php | 64 +- .../lang/en/surveyprofield_character.php | 14 +- .../lang/es_mx/surveyprofield_character.php | 12 +- field/character/tests/behat/itemform.feature | 2 +- field/character/tests/behat/trim.feature | 9 +- ...0.xml => text_(short)_only_2024032800.xml} | 208 +- field/character/version.php | 4 +- ...urveyprofield_checkbox_subplugin.class.php | 5 +- field/checkbox/classes/item.php | 429 ++-- field/checkbox/db/install.xml | 38 +- field/checkbox/db/upgrade.php | 61 + .../lang/en/surveyprofield_checkbox.php | 18 +- field/checkbox/mform/advcheckbox.php | 77 - field/checkbox/mform/checkbox.php | 76 - field/checkbox/tests/behat/itemform.feature | 12 +- .../behat/settings_configuration_01.feature | 20 +- .../behat/settings_configuration_02.feature | 16 +- .../behat/settings_configuration_03.feature | 12 +- .../behat/settings_configuration_04.feature | 8 +- .../behat/settings_configuration_05.feature | 16 +- ...23000.xml => checkbox_only_2024032800.xml} | 454 ++-- field/checkbox/version.php | 4 +- ...up_surveyprofield_date_subplugin.class.php | 5 +- field/date/classes/item.php | 516 +++-- field/date/db/install.xml | 32 +- field/date/db/upgrade.php | 63 +- field/date/lang/en/surveyprofield_date.php | 10 +- field/date/tests/behat/itemform.feature | 6 +- field/date/tests/behat/submit_date.feature | 6 +- ...023103100.xml => date_only_2024032800.xml} | 214 +- field/date/version.php | 4 +- ...urveyprofield_datetime_subplugin.class.php | 5 +- field/datetime/classes/item.php | 670 ++++-- field/datetime/db/install.xml | 34 +- field/datetime/db/upgrade.php | 63 +- .../lang/en/surveyprofield_datetime.php | 12 +- field/datetime/tests/behat/itemform.feature | 10 +- .../tests/behat/submit_datetime.feature | 10 +- ....xml => date_and_time_only_2024032800.xml} | 233 +- field/datetime/version.php | 4 +- ...veyprofield_fileupload_subplugin.class.php | 5 +- field/fileupload/classes/item.php | 275 ++- field/fileupload/db/install.xml | 28 +- field/fileupload/db/upgrade.php | 61 + .../lang/en/surveyprofield_fileupload.php | 12 +- field/fileupload/mform/fileupload.php | 159 -- .../tests/behat/submit_attachment.feature | 18 +- ...000.xml => attachment_only_2024032800.xml} | 30 +- field/fileupload/version.php | 4 +- ...surveyprofield_integer_subplugin.class.php | 5 +- field/integer/classes/item.php | 231 +- field/integer/db/install.xml | 30 +- field/integer/db/upgrade.php | 67 +- .../lang/en/surveyprofield_integer.php | 10 +- .../lang/it/surveyprofield_integer.php | 4 +- field/integer/tests/behat/itemform.feature | 2 +- .../tests/behat/submit_integer.feature | 2 +- ...123000.xml => integer_only_2024032800.xml} | 111 +- field/integer/version.php | 4 +- ...eyprofield_multiselect_subplugin.class.php | 5 +- field/multiselect/classes/item.php | 397 ++-- field/multiselect/db/install.xml | 36 +- field/multiselect/db/upgrade.php | 61 + .../lang/en/surveyprofield_multiselect.php | 24 +- .../multiselect/tests/behat/itemform.feature | 2 +- .../behat/settings_configuration_01.feature | 20 +- .../behat/settings_configuration_02.feature | 14 +- .../behat/settings_configuration_03.feature | 10 +- .../behat/settings_configuration_04.feature | 12 +- .../behat/settings_configuration_05.feature | 12 +- ...00.xml => multiselect_only_2024032800.xml} | 209 +- field/multiselect/version.php | 4 +- ...surveyprofield_numeric_subplugin.class.php | 5 +- field/numeric/classes/item.php | 367 +-- field/numeric/db/install.xml | 32 +- field/numeric/db/upgrade.php | 63 +- .../lang/en/surveyprofield_numeric.php | 16 +- field/numeric/tests/behat/itemform.feature | 2 +- ...123000.xml => numeric_only_2024032800.xml} | 128 +- field/numeric/version.php | 4 +- ...eyprofield_radiobutton_subplugin.class.php | 5 +- field/radiobutton/classes/item.php | 358 +-- field/radiobutton/classes/itemsetupform.php | 5 +- field/radiobutton/db/install.xml | 34 +- field/radiobutton/db/upgrade.php | 63 +- .../lang/en/surveyprofield_radiobutton.php | 15 +- field/radiobutton/mform/radiobutton.php | 85 - .../radiobutton/tests/behat/itemform.feature | 14 +- .../tests/behat/submit_radiobutton.feature | 4 +- .../tests/behat/two_option_test.feature | 8 +- .../{mum_or_dad_test.xml => mum_or_dad.xml} | 120 +- ...00.xml => radiobutton_only_2024032800.xml} | 294 +-- field/radiobutton/version.php | 4 +- ...up_surveyprofield_rate_subplugin.class.php | 5 +- field/rate/classes/item.php | 344 +-- field/rate/classes/itemsetupform.php | 10 +- field/rate/db/install.xml | 36 +- field/rate/db/upgrade.php | 63 +- field/rate/lang/en/surveyprofield_rate.php | 24 +- field/rate/tests/behat/itemform.feature | 104 +- field/rate/tests/behat/submit_rate.feature | 24 +- ...015123000.xml => rate_only_2024032800.xml} | 234 +- field/rate/version.php | 4 +- ...veyprofield_recurrence_subplugin.class.php | 5 +- field/recurrence/classes/item.php | 444 ++-- field/recurrence/db/install.xml | 32 +- field/recurrence/db/upgrade.php | 63 +- .../lang/en/surveyprofield_recurrence.php | 12 +- field/recurrence/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_recurrence.feature | 4 +- ...100.xml => recurrence_only_2024032800.xml} | 233 +- field/recurrence/version.php | 4 +- ..._surveyprofield_select_subplugin.class.php | 5 +- field/select/classes/item.php | 300 ++- field/select/classes/itemsetupform.php | 1 - field/select/db/install.xml | 32 +- field/select/db/upgrade.php | 63 +- .../select/lang/en/surveyprofield_select.php | 12 +- .../select/lang/it/surveyprofield_select.php | 2 +- field/select/tests/behat/itemform.feature | 4 +- .../select/tests/behat/submit_select.feature | 6 +- ...5123000.xml => select_only_2024032800.xml} | 294 +-- field/select/version.php | 4 +- ...rveyprofield_shortdate_subplugin.class.php | 5 +- field/shortdate/classes/item.php | 441 ++-- field/shortdate/classes/itemsetupform.php | 2 +- field/shortdate/db/install.xml | 32 +- field/shortdate/db/upgrade.php | 63 +- .../lang/en/surveyprofield_shortdate.php | 10 +- field/shortdate/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_shortdate.feature | 4 +- ...0.xml => date_(short)_only_2024032800.xml} | 230 +- field/shortdate/version.php | 4 +- ...urveyprofield_textarea_subplugin.class.php | 5 +- field/textarea/classes/item.php | 338 +-- field/textarea/classes/itemsetupform.php | 2 +- field/textarea/db/install.xml | 34 +- field/textarea/db/upgrade.php | 63 +- .../lang/en/surveyprofield_textarea.php | 14 +- .../lang/es_mx/surveyprofield_textarea.php | 12 +- .../lang/it/surveyprofield_textarea.php | 10 +- field/textarea/mform/textarea_editor.php | 119 - field/textarea/mform/textarea_plain.php | 120 - field/textarea/tests/behat/itemform.feature | 4 +- .../behat/settings_configuration.feature | 4 +- field/textarea/tests/behat/trim.feature | 5 +- ...23000.xml => textarea_only_2024032800.xml} | 116 +- field/textarea/version.php | 4 +- ...up_surveyprofield_time_subplugin.class.php | 5 +- field/time/classes/item.php | 455 ++-- field/time/db/install.xml | 34 +- field/time/db/upgrade.php | 63 +- field/time/lang/en/surveyprofield_time.php | 12 +- field/time/tests/behat/itemform.feature | 20 +- field/time/tests/behat/submit_time.feature | 4 +- ...023103100.xml => time_only_2024032800.xml} | 233 +- field/time/version.php | 4 +- ...rveyproformat_fieldset_subplugin.class.php | 2 +- format/fieldset/classes/item.php | 105 +- format/fieldset/classes/itemsetupform.php | 2 +- format/fieldset/db/install.xml | 24 +- format/fieldset/db/upgrade.php | 20 + .../lang/en/surveyproformat_fieldset.php | 2 +- format/fieldset/version.php | 4 +- format/fieldsetend/classes/item.php | 81 +- .../lang/en/surveyproformat_fieldsetend.php | 2 +- format/fieldsetend/version.php | 4 +- ..._surveyproformat_label_subplugin.class.php | 5 +- format/label/classes/item.php | 159 +- format/label/classes/itemsetupform.php | 2 +- format/label/db/install.xml | 26 +- format/label/db/upgrade.php | 65 +- .../label/lang/en/surveyproformat_label.php | 6 +- format/label/mform/label.php | 86 - format/label/version.php | 4 +- format/pagebreak/classes/item.php | 93 +- .../lang/en/surveyproformat_pagebreak.php | 2 +- format/pagebreak/version.php | 4 +- index.php | 27 +- lang/en/surveypro.php | 110 +- lang/es/surveypro.php | 98 +- lang/es_mx/surveypro.php | 100 +- lang/it/surveypro.php | 32 +- layout.php | 21 +- lib.php | 25 +- mod_form.php | 16 +- mtemplates.php | 21 +- pix/stamp.png | Bin 0 -> 379 bytes pix/stamp.svg | 54 + report/attachments/classes/filterform.php | 2 +- report/attachments/classes/form.php | 13 +- report/attachments/classes/report.php | 1 - .../lang/en/surveyproreport_attachments.php | 4 +- .../behat/attachment_functionality.feature | 3 - report/attachments/version.php | 4 +- report/attachments/view.php | 2 +- report/colles/classes/report.php | 12 +- report/colles/graph.php | 4 +- .../colles/lang/en/surveyproreport_colles.php | 34 +- report/colles/version.php | 4 +- report/frequency/classes/filterform.php | 7 +- report/frequency/classes/report.php | 3 +- report/frequency/graph.php | 2 +- .../lang/en/surveyproreport_frequency.php | 4 +- .../lang/it/surveyproreport_frequency.php | 2 +- report/frequency/version.php | 4 +- report/lateusers/classes/report.php | 1 - report/lateusers/version.php | 4 +- report/responsesperuser/classes/report.php | 1 - report/responsesperuser/version.php | 4 +- report/userspercount/classes/report.php | 1 - .../lang/en/surveyproreport_userspercount.php | 2 +- report/userspercount/version.php | 4 +- reports.php | 4 +- styles.css | 214 +- .../attls/lang/en/surveyprotemplate_attls.php | 34 +- .../attls/lang/it/surveyprotemplate_attls.php | 32 +- template/attls/template.xml | 254 +-- template/attls/version.php | 4 +- .../en/surveyprotemplate_collesactual.php | 34 +- .../it/surveyprotemplate_collesactual.php | 32 +- template/collesactual/template.xml | 396 ++-- .../collesactual/tests/behat/graphs.feature | 52 +- .../tests/behat/reportswithanswers.feature | 156 +- .../tests/behat/reportswithoutanswers.feature | 53 +- template/collesactual/version.php | 4 +- ...urveyprotemplate_collesactualpreferred.php | 10 +- ...urveyprotemplate_collesactualpreferred.php | 10 +- template/collesactualpreferred/template.xml | 686 +++--- .../tests/behat/graphs.feature | 112 +- template/collesactualpreferred/version.php | 4 +- .../en/surveyprotemplate_collespreferred.php | 34 +- .../it/surveyprotemplate_collespreferred.php | 32 +- template/collespreferred/template.xml | 396 ++-- .../tests/behat/graphs.feature | 52 +- template/collespreferred/version.php | 4 +- .../surveyprotemplate_criticalincidents.php | 6 +- .../surveyprotemplate_criticalincidents.php | 6 +- template/criticalincidents/template.xml | 78 +- template/criticalincidents/version.php | 4 +- template/flags/classes/privacy/provider.php | 44 + template/flags/classes/template.php | 47 + .../flags/lang/en/surveyprotemplate_flags.php | 32 + .../flags/lang/es/surveyprotemplate_flags.php | 32 + .../flags/lang/it/surveyprotemplate_flags.php | 32 + template/flags/pix/icon.png | Bin 0 -> 625 bytes template/flags/pix/icon.svg | 579 +++++ template/flags/template.xml | 27 + template/flags/version.php | 30 + .../classes/privacy/provider.php | 44 + template/oneofeachenable/classes/template.php | 47 + .../en/surveyprotemplate_oneofeachenable.php | 248 +++ template/oneofeachenable/pix/icon.png | Bin 0 -> 625 bytes template/oneofeachenable/pix/icon.svg | 579 +++++ template/oneofeachenable/template.xml | 1965 +++++++++++++++++ template/oneofeachenable/version.php | 30 + templatemaster/version.php | 4 +- tests/behat/backup_restore.feature | 4 +- tests/behat/backup_simple.feature | 2 + tests/behat/behat_mod_surveypro.php | 23 +- tests/behat/change_of_mind.feature | 14 +- tests/behat/duplicate_response.feature | 2 +- tests/behat/item_action.feature | 34 +- tests/behat/lib_behattest.php | 94 +- tests/behat/parent_boolean.feature | 37 +- tests/behat/parent_checkbox.feature | 280 +-- tests/behat/parent_integer.feature | 48 +- tests/behat/parent_multiselect.feature | 168 +- tests/behat/parent_radiobutton.feature | 48 +- tests/behat/parent_select.feature | 44 +- ...readonly_browse_allowed_pages_only.feature | 2 +- tests/behat/restore_simple.feature | 91 +- .../behat/see_groupsubmissions_part01.feature | 4 +- .../behat/see_groupsubmissions_part02.feature | 2 +- .../behat/see_groupsubmissions_part03.feature | 2 +- .../behat/see_groupsubmissions_part04.feature | 7 +- tests/behat/submission_test.feature | 56 +- tests/behat/thankspage.feature | 7 +- tests/behat/timezone_independent.feature | 80 +- tests/behat/usertemplate_apply.feature | 8 +- tests/behat/usertemplate_applyall.feature | 72 +- tests/behat/usertemplate_create.feature | 6 +- tests/fixtures/demo_course-20160108.mbz | Bin 72980 -> 0 bytes tests/fixtures/demo_course-20240410.mbz | Bin 0 -> 89037 bytes ...{MMM_2023103100.xml => MMM_2024032800.xml} | 604 +++-- .../{item_action_test.xml => item_action.xml} | 200 +- ...103100.xml => parent-child_2024032800.xml} | 342 ++- tests/generator_test.php | 8 +- tests/lib_test.php | 15 +- tests/mastertemplate_test.php | 4 +- tests/separator_test.php | 56 +- tests/setup_test.php | 4 +- tools.php | 4 +- utemplates.php | 66 +- version.php | 6 +- view.php | 128 +- 370 files changed, 17524 insertions(+), 10547 deletions(-) rename classes/local/form/{usersearch.php => response_searchform.php} (89%) rename classes/local/form/{userform.php => response_submitform.php} (81%) delete mode 100644 classes/utility_mform.php rename classes/{view_submissionlist.php => view_responselist.php} (97%) rename classes/{view_submissionsearch.php => view_responsesearch.php} (96%) rename classes/{view_submissionform.php => view_responsesubmit.php} (87%) create mode 100644 field/age/lang/it/surveyprofield_age.php rename field/age/tests/fixtures/usertemplate/{age_only_2023103100.xml => age_only_2024032800.xml} (92%) rename field/autofill/tests/fixtures/usertemplate/{autofill_only_2015123000.xml => autofill_only_2024032800.xml} (92%) rename field/boolean/tests/fixtures/usertemplate/{boolean_only_2015123000.xml => boolean_only_2024032800.xml} (77%) rename field/character/tests/fixtures/usertemplate/{textshort_only_2015123000.xml => text_(short)_only_2024032800.xml} (87%) delete mode 100644 field/checkbox/mform/advcheckbox.php delete mode 100644 field/checkbox/mform/checkbox.php rename field/checkbox/tests/fixtures/usertemplate/{checkbox_only_2015123000.xml => checkbox_only_2024032800.xml} (93%) rename field/date/tests/fixtures/usertemplate/{date_only_2023103100.xml => date_only_2024032800.xml} (91%) rename field/datetime/tests/fixtures/usertemplate/{datetime_only_2023103100.xml => date_and_time_only_2024032800.xml} (88%) delete mode 100644 field/fileupload/mform/fileupload.php rename field/fileupload/tests/fixtures/usertemplate/{attachment_only_2015123000.xml => attachment_only_2024032800.xml} (90%) rename field/integer/tests/fixtures/usertemplate/{integer_only_2015123000.xml => integer_only_2024032800.xml} (88%) rename field/multiselect/tests/fixtures/usertemplate/{multiselect_only_2015123000.xml => multiselect_only_2024032800.xml} (87%) rename field/numeric/tests/fixtures/usertemplate/{numeric_only_2015123000.xml => numeric_only_2024032800.xml} (84%) delete mode 100644 field/radiobutton/mform/radiobutton.php rename field/radiobutton/tests/fixtures/usertemplate/{mum_or_dad_test.xml => mum_or_dad.xml} (90%) rename field/radiobutton/tests/fixtures/usertemplate/{radiobutton_only_2015123000.xml => radiobutton_only_2024032800.xml} (92%) rename field/rate/tests/fixtures/usertemplate/{rate_only_2015123000.xml => rate_only_2024032800.xml} (89%) rename field/recurrence/tests/fixtures/usertemplate/{recurrence_only_2023103100.xml => recurrence_only_2024032800.xml} (87%) rename field/select/tests/fixtures/usertemplate/{select_only_2015123000.xml => select_only_2024032800.xml} (92%) rename field/shortdate/tests/fixtures/usertemplate/{dateshort_only_2023103100.xml => date_(short)_only_2024032800.xml} (88%) delete mode 100644 field/textarea/mform/textarea_editor.php delete mode 100644 field/textarea/mform/textarea_plain.php rename field/textarea/tests/fixtures/usertemplate/{textarea_only_2015123000.xml => textarea_only_2024032800.xml} (87%) rename field/time/tests/fixtures/usertemplate/{time_only_2023103100.xml => time_only_2024032800.xml} (89%) delete mode 100644 format/label/mform/label.php create mode 100644 pix/stamp.png create mode 100644 pix/stamp.svg create mode 100644 template/flags/classes/privacy/provider.php create mode 100644 template/flags/classes/template.php create mode 100644 template/flags/lang/en/surveyprotemplate_flags.php create mode 100644 template/flags/lang/es/surveyprotemplate_flags.php create mode 100644 template/flags/lang/it/surveyprotemplate_flags.php create mode 100644 template/flags/pix/icon.png create mode 100644 template/flags/pix/icon.svg create mode 100644 template/flags/template.xml create mode 100644 template/flags/version.php create mode 100644 template/oneofeachenable/classes/privacy/provider.php create mode 100644 template/oneofeachenable/classes/template.php create mode 100644 template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php create mode 100644 template/oneofeachenable/pix/icon.png create mode 100644 template/oneofeachenable/pix/icon.svg create mode 100644 template/oneofeachenable/template.xml create mode 100644 template/oneofeachenable/version.php delete mode 100644 tests/fixtures/demo_course-20160108.mbz create mode 100644 tests/fixtures/demo_course-20240410.mbz rename tests/fixtures/usertemplate/{MMM_2023103100.xml => MMM_2024032800.xml} (95%) rename tests/fixtures/usertemplate/{item_action_test.xml => item_action.xml} (92%) rename tests/fixtures/usertemplate/{parent-child_2023103100.xml => parent-child_2024032800.xml} (91%) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 8cf028e1900..baea34564d1 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -29,12 +29,12 @@ jobs: matrix: include: - php: 8.1 - moodle-branch: MOODLE_403_STABLE + moodle-branch: MOODLE_404_STABLE database: mariadb suite: classic profile: default - - php: 8.1 - moodle-branch: MOODLE_403_STABLE + - php: 8.2 + moodle-branch: MOODLE_404_STABLE database: pgsql suite: default profile: chrome diff --git a/TODO.txt b/TODO.txt index 4958bd16a16..6cee0ee6f43 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,7 @@ -> does it make sense the research per long text? --> "Manage relation" page has lots of features, but the consequence is that the page is "cluttered" with too many settings. +-> "Manage relation" page has lots of features, but the consequence is that the page is "cluttered" with too many settings. Obviously a Show/Hide advanced button is needed. (thanks to JR) --> The Autofill question message "Content will be added at submit time" should not be displayed to the Student when taking the Survey, +-> The Autofill question message "Content will be added at submit time" should not be displayed to the Student taking the Survey, as it does not mean anything to him. That is a message for Teacher, not Student. (thanks to JR) -> grades? -> surveypro_get_view_actions()? @@ -9,10 +9,10 @@ as it does not mean anything to him. That is a message for Teacher, not Student. -> surveypro_scale_used($surveyproid, $scaleid)? -> surveypro_scale_used_anywhere($scaleid)? -> unit test (they are a must) --> *** Crucial known issue that is not fixable in my opinion. I apply a master template. -I make a surveypro with it. Tomorrow I update the master template with a newer version. -This new version has one more item in the middle. -Surveys built with the old release of the plugin will stop working fine as they will find in the right position string of a different template. +-> *** Crucial known issue that is not fixable in my opinion. I apply a master template. +I make a surveypro with it. Tomorrow I update the master template with a newer version. +This new version has one more item in the middle. +Surveys built with the old plugins will stop working fine as they will find in the right position string of a different template. -> possible better solution: use the first 32 chars of the question escaped -> is the autofill field saved to userdata even if it is not shown? -> allow upperbound date/datetime == to now @@ -21,7 +21,7 @@ Surveys built with the old release of the plugin will stop working fine as they -> mform elements in MMM have different sizes probably because of /theme/yui_combo.php? 3.13.0/cssreset/cssreset.css&3.13.0/cssfonts/cssfonts.css&3.13.0/cssgrids/cssgrids.css&3.13.0/cssbase/cssbase.css -1) Still it seems to be something strange when handling fileareas. +1) Still it seems to be something strange when handling fileareas. I just grepped by get_area_files and found a bunch of them new/strange for me. ELOY has to review this! > Please let me know better what do you mean. I can not understand it. @@ -31,15 +31,15 @@ I just grepped by get_area_files and found a bunch of them new/strange for me. E > literals is ok. > more yet, if there are groups... then everything (listing, reports, graphs) > must be by group. -things like the "phantom tabs" (sorry for the expression, lol, just joking) or the way "attempts" are performed... +things like the "phantom tabs" (sorry for the expression, lol, just joking) or the way "attempts" are performed... are substandard (to name it in some way). 2.a) A read me about what's missing (migration from old, usability review and discussion) -2.b) A commit (decided by you) where you want me to cut history. +2.b) A commit (decided by you) where you want me to cut history. Can be current commit of anything else if you want to preserve your latest commits for any reason. -2.c) A BIG WARNING saying that it must not be used in production sites with existing old surveypros +2.c) A BIG WARNING saying that it must not be used in production sites with existing old surveypros because they will be erased completely (beacuse of 1). README.md (so it will display nicely in github) ? diff --git a/backup/moodle2/backup_surveypro_stepslib.php b/backup/moodle2/backup_surveypro_stepslib.php index e20c560e95a..d7ccd30b667 100644 --- a/backup/moodle2/backup_surveypro_stepslib.php +++ b/backup/moodle2/backup_surveypro_stepslib.php @@ -44,18 +44,22 @@ protected function define_structure() { // Define each element separated. // Root element describing surveypro instance. $surveypro = new backup_nested_element('surveypro', ['id'], [ - 'name', 'intro', 'introformat', 'newpageforchild', 'neverstartedemail', - 'pauseresume', 'keepinprogress', 'captcha', 'history', 'anonymous', - 'timeopen', 'timeclose', 'startyear', 'stopyear', - 'maxentries', 'mailroles', 'mailextraaddresses', 'mailcontent', 'mailcontentformat', - 'thankspage', 'thankspageformat', 'riskyeditdeadline', 'template', 'completionsubmit', - 'timecreated', 'timemodified', ]); + 'name', 'intro', 'introformat', 'newpageforchild', 'neverstartedemail', + 'pauseresume', 'keepinprogress', 'captcha', 'history', 'anonymous', + 'timeopen', 'timeclose', 'startyear', 'stopyear', + 'maxentries', 'mailroles', 'mailextraaddresses', 'mailcontent', 'mailcontentformat', + 'thankspage', 'thankspageformat', 'riskyeditdeadline', 'template', 'completionsubmit', + 'timecreated', 'timemodified', + ]); $items = new backup_nested_element('items'); $item = new backup_nested_element('item', ['id', 'type', 'plugin'], [ - 'hidden', 'insearchform', 'reserved', 'sortindex', 'formpage', - 'parentid', 'parentvalue', 'timecreated', 'timemodified', ]); + 'content', 'contentformat', + 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', + 'hidden', 'insearchform', 'reserved', 'sortindex', 'formpage', + 'parentid', 'parentvalue', 'timecreated', 'timemodified', + ]); $submissions = new backup_nested_element('submissions'); diff --git a/classes/event/submission_created.php b/classes/event/submission_created.php index 88e7a55587c..10801fe9786 100644 --- a/classes/event/submission_created.php +++ b/classes/event/submission_created.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/event/submission_modified.php b/classes/event/submission_modified.php index 77ed7296dda..59812ed5bd9 100644 --- a/classes/event/submission_modified.php +++ b/classes/event/submission_modified.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/event/submission_viewed.php b/classes/event/submission_viewed.php index 865cac33337..7a9637831c1 100644 --- a/classes/event/submission_viewed.php +++ b/classes/event/submission_viewed.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/formbase.php b/classes/formbase.php index 000fb9f8170..e3177d1a0ed 100644 --- a/classes/formbase.php +++ b/classes/formbase.php @@ -123,8 +123,9 @@ public function set_user_boundary_formpages() { FROM {surveypro_item} WHERE surveyproid = :surveyproid AND reserved = :reserved + AND hidden = :hidden AND plugin <> :plugin'; - $whereparams = ['surveyproid' => $this->surveypro->id, 'reserved' => 0, 'plugin' => 'pagebreak']; + $whereparams = ['surveyproid' => $this->surveypro->id, 'reserved' => 0, 'hidden' => 0, 'plugin' => 'pagebreak']; $boundaries = $DB->get_record_sql($sql, $whereparams); $userfirstpage = isset($boundaries->userfirstpage) ? $boundaries->userfirstpage : 1; @@ -232,7 +233,7 @@ private function page_has_items($formpage) { } foreach ($itemseeds as $itemseed) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); if ($parentitem->userform_is_child_allowed_static($this->get_submissionid(), $itemseed)) { // If at least one parent allows its child, I finished. The page is going to display items. return true; @@ -296,7 +297,7 @@ public function get_prefill_data() { [$where, $params] = surveypro_fetch_items_seeds($id, true, $canaccessreserveditems, null, SURVEYPRO_TYPEFIELD, $page); if ($itemseeds = $DB->get_recordset_select('surveypro_item', $where, $params, 'sortindex', 'id, type, plugin')) { foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $where = ['submissionid' => $this->submissionid, 'itemid' => $item->get_itemid()]; $olduserdata = $DB->get_record('surveypro_answer', $where); diff --git a/classes/itembase.php b/classes/itembase.php index c538e5eeac5..e905b4f99ab 100644 --- a/classes/itembase.php +++ b/classes/itembase.php @@ -38,7 +38,9 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class itembase { +abstract class itembase { + + // Itembase properties. /** * @var object Course module object @@ -55,6 +57,11 @@ class itembase { */ public $surveypro; + /** + * @var int pluginid: the id of the item in the child surveypro(field|format)_plugin table + */ + protected $pluginid; + /** * @var int Unique itemid of the surveyproitem in surveypro_item table */ @@ -71,9 +78,49 @@ class itembase { protected $plugin; /** - * @var string Basename of the field as it is in the out form + * @var string The content of the question of the item */ - protected $itemname; + public $content; + + /** + * @var string The contentformat of the question of the item + */ + public $contentformat; + + /** + * @var int Is the item required? + */ + protected $required; + + /** + * @var int Indent of the item in the form page + */ + protected $indent; + + /** + * @var int The position of the item content in the frame of the user form + */ + protected $position; + + /** + * @var string The custom number of the item + */ + protected $customnumber; + + /** + * @var int Are the filling instruction going to explain the item in the user form? + */ + protected $hideinstructions; + + /** + * @var string The name of the item in the exported report + */ + protected $variable; + + /** + * @var string The content of custom extranote + */ + protected $extranote; /** * @var bool Visibility of this item in the out form @@ -110,6 +157,23 @@ class itembase { */ protected $parentvalue; + /** + * @var int timecreated + */ + protected $timecreated; + + /** + * @var int timemodified + */ + protected $timemodified; + + // Service variables + + /** + * @var string Basename of the field as it is in the out form + */ + protected $itemname; + /** * @var string The user friendly answer that the parent item has to have in order to show this item as child */ @@ -120,11 +184,6 @@ class itembase { */ protected $itemeditingfeedback; - /** - * @var array - */ - protected $fieldsusingformat = ['content' => SURVEYPRO_ITEMCONTENTFILEAREA]; - /** * List of fields properties the surveypro creator will manage in the item definition form * By default each item property is present in the form @@ -132,16 +191,17 @@ class itembase { * * @var array */ - protected $insetupform = [ + public $insetupform = [ 'common_fs' => true, 'content' => true, - 'customnumber' => true, + 'contentformat' => true, + 'required' => true, + 'indent' => true, 'position' => true, + 'variable' => true, 'extranote' => true, + 'customnumber' => true, 'hideinstructions' => true, - 'required' => true, - 'variable' => true, - 'indent' => true, 'hidden' => true, 'insearchform' => true, 'reserved' => true, @@ -149,7 +209,7 @@ class itembase { ]; /** - * Class constructor. + * Class constructor * * @param object $cm * @param object $surveypro @@ -159,12 +219,13 @@ class itembase { public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->cm = $cm; $this->surveypro = $surveypro; + $this->context = \context_module::instance($cm->id); } /** * Item load. * - * If itemid is provided, load the object (item + base + plugin) from database + * If itemid is provided, load the object (item = base + plugin) from database * If evaluateparentcontent is true, load the parentitem parentcontent property too * * @param integer $itemid @@ -179,10 +240,8 @@ protected function item_load($itemid, $getparentcontent) { debugging($message, DEBUG_DEVELOPER); } - $context = \context_module::instance($this->cm->id); - - // Some item, like pagebreak or fieldsetend, may be free of the plugin table. - if ($this->uses_db_table()) { + // Some item, like pagebreak or fieldsetend, may do not use the plugin table. + if ($this->get_usesplugintable()) { $tablename = 'surveypro'.$this->type.'_'.$this->plugin; $sql = 'SELECT *, i.id as itemid, p.id as pluginid FROM {surveypro_item} i @@ -194,28 +253,30 @@ protected function item_load($itemid, $getparentcontent) { WHERE i.id = :itemid'; } + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin']; if ($record = $DB->get_record_sql($sql, ['itemid' => $itemid])) { - foreach ($record as $option => $value) { - $this->{$option} = $value; + foreach ($record as $field => $value) { + if (in_array($field, $unrelevantfields)) { + continue; + } + $method = 'set_'.$field; + $this->{$method}($value); } - // Plugins not using contentformat (only Fieldset, at the moment) are satisfied. + // Plugins not using contentformat (only Fieldset and pagebreak, at the moment) are satisfied. // Pagebreak and fieldsetend are missing content too. - // Special care to fields with format. - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - foreach ($fieldsusingformat as $fieldname => $filearea) { - $this->{$fieldname} = file_rewrite_pluginfile_urls( - $this->{$fieldname}, 'pluginfile.php', $context->id, - 'mod_surveypro', $filearea, $itemid - ); - } + if (isset($this->content) && strpos($this->content, '@@PLUGINFILE@@/')) { // Pagebreak don't use $this->content. + // Special care to fields with format. + $this->content = file_rewrite_pluginfile_urls( + $this->content, 'pluginfile.php', $this->context->id, + 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid + ); } - unset($this->id); // I do not care it. I already heave: itemid and pluginid. $this->itemname = SURVEYPRO_ITEMPREFIX.'_'.$this->type.'_'.$this->plugin.'_'.$this->itemid; if ($getparentcontent && $this->parentid) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $this->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $this->parentid); $this->parentcontent = $parentitem->parent_decode_child_parentvalue($this->parentvalue); } } else { @@ -227,7 +288,7 @@ protected function item_load($itemid, $getparentcontent) { /** * Verify the validity of contents of the record. * - * for instance: age not greater than maximum age + * For instance: age not greater than maximum age. * * @param \stdClass $record * @return void @@ -245,6 +306,15 @@ public function item_force_coherence($record) { * √ surveyproid * √ type * √ plugin + * √ content + * √ contentformat + * √ required + * √ indent + * √ position + * √ customnumber + * √ hideinstructions + * √ variable + * √ extranote * √ hidden * √ insearchform * √ reserved @@ -255,14 +325,6 @@ public function item_force_coherence($record) { * √ timecreated * √ timemodified * - * in spite of this, here I also get: - * hideinstructions - * required - * - * in addition, here I also make cleanup of: - * extranote - * parentvalue - * * The following settings will be calculated later: * sortindex * formpage @@ -270,12 +332,7 @@ public function item_force_coherence($record) { * @param \stdClass $record * @return void */ - protected function get_common_settings($record) { - // You are going to change item content (maybe sortindex, maybe the parentitem) - // so, do not forget to reset items per page. - $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); - $utilitylayoutman->reset_pages(); - + protected function add_base_properties_to_record($record) { $timenow = time(); // Surveyproid. @@ -283,8 +340,10 @@ protected function get_common_settings($record) { // Plugin and type are already onboard. - // Checkboxes content. - $checkboxessettings = ['hidden', 'insearchform', 'reserved', 'hideinstructions', 'required']; + // Content and contentformat will be managed later. + + // Checkboxes values. + $checkboxessettings = ['required', 'hidden', 'hideinstructions', 'insearchform', 'reserved']; foreach ($checkboxessettings as $checkboxessetting) { if ($this->insetupform[$checkboxessetting]) { $record->{$checkboxessetting} = isset($record->{$checkboxessetting}) ? 1 : 0; @@ -313,15 +372,16 @@ protected function get_common_settings($record) { // Because of this, even if the user writes, for instance, "bread\nmilk" to parentvalue // I have to encode it to key(bread);key(milk). if (!empty($record->parentid)) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $record->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $record->parentid); $record->parentvalue = $parentitem->parent_encode_child_parentcontent($record->parentcontent); unset($record->parentcontent); // Why do I drop $record->parentcontent? } } /** - * Item save - * Executes surveyproitem_<> global level actions + * Item save. + * + * Executes surveypro(field|format)_<> global level actions * this is the save point of the global part of each plugin * * Here is the explanation of $this->itemeditingfeedback @@ -353,80 +413,66 @@ protected function get_common_settings($record) { * (digit 5) == 1: a chain of children items inherited reserved access because this item (as parent) was changed to reserved * * @param object $record - * @return void + * @return int $record->itemid */ public function item_save($record) { global $DB, $COURSE; - $context = \context_module::instance($this->cm->id); + $this->add_base_properties_to_record($record); $utilitysubmissionman = new utility_submission($this->cm, $this->surveypro); $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); $hassubmission = $utilitylayoutman->has_submissions(false); + // You are going to change item content (maybe sortindex, maybe the parentitem) + // so, do not forget to reset items per page. + $utilitylayoutman->reset_pages(); + $tablename = 'surveypro'.$this->type.'_'.$this->plugin; $this->itemeditingfeedback = SURVEYPRO_NOFEEDBACK; - // Does this record need to be saved as new record or as un update of a preexisting record? - if (empty($record->itemid)) { - // Item is new. + // Is this a new item or does it already exist? + if (empty($record->itemid)) { // Item is new. // Sortindex. $sql = 'SELECT COUNT(\'x\') FROM {surveypro_item} WHERE surveyproid = :surveyproid - AND sortindex > 0'; - $whereparams = ['surveyproid' => $this->cm->instance]; + AND sortindex > :sortindex'; + $whereparams = ['surveyproid' => $this->cm->instance, 'sortindex' => 0]; $record->sortindex = 1 + $DB->count_records_sql($sql, $whereparams); // Itemid. try { $transaction = $DB->start_delegated_transaction(); + // Before saving validate the variable name. + $this->item_validate_variablename($record); if ($itemid = $DB->insert_record('surveypro_item', $record)) { // First surveypro_item save. - // Now think to $tablename. - if ($this->uses_db_table()) { - // Before saving to the the plugin table, validate the variable name. - $this->item_validate_variablename($record, $itemid); - - $record->itemid = $itemid; - if ($pluginid = $DB->insert_record($tablename, $record)) { // First save of $tablename. - $this->itemeditingfeedback += 1; // 0*2^1+1*2^0. - } - } else { - $record->itemid = $itemid; - } - } - - // Special care to "editors". Remember that content and contentformat are in plugin table. - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { + if ($this->insetupform['contentformat']) { + // Special care to the field content equipped with an editor. + $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $this->context]; + $record->id = $itemid; $record = file_postupdate_standard_editor( - $record, $fieldname, $editoroptions, - $context, 'mod_surveypro', $filearea, $record->itemid + $record, 'content', $editoroptions, + $this->context, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $record->id ); + $DB->update_record('surveypro_item', $record); } - if ($this->uses_db_table()) { - // Tablename. - $record->id = $pluginid; - - if (!$DB->update_record($tablename, $record)) { // Update of $tablename. - $this->itemeditingfeedback -= ($this->itemeditingfeedback % 2); // Whatever it was, now it is a fail. - // Otherwise... - // Leave the previous $this->itemeditingfeedback. - // If it was a success, leave it as now you got one more success. - // If it was a fail, leave it as you can not cover the previous fail. + // Now think to $tablename. + $record->itemid = $itemid; // Always give a value to $record->itemid as it is returned by the method. + if ($this->get_usesplugintable()) { + if ($pluginid = $DB->insert_record($tablename, $record)) { // First save of $tablename. + $this->itemeditingfeedback += 1; // 0*2^1+1*2^0. } - // Record->content follows standard flow and has already been saved at first save time. } } $transaction->allow_commit(); // Event: item_created. - $eventdata = ['context' => $context, 'objectid' => $itemid]; + $eventdata = ['context' => $this->context, 'objectid' => $itemid]; $eventdata['other'] = ['type' => $record->type, 'plugin' => $record->plugin, 'view' => SURVEYPRO_NEWITEM]; $event = \mod_surveypro\event\item_created::create($eventdata); $event->trigger(); @@ -443,17 +489,6 @@ public function item_save($record) { } else { // Item already exists. - // Special care to "editors". - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { - $record = file_postupdate_standard_editor( - $record, $fieldname, $editoroptions, - $context, 'mod_surveypro', $filearea, $record->itemid - ); - } - } - // Begin of: Hide/unhide part 1. $oldhidden = $this->get_hidden(); // Used later. // End of: hide/unhide 1. @@ -465,19 +500,27 @@ public function item_save($record) { // Sortindex. // Doesn't change at item editing time. - // Surveypro_item. + // Mandatory id. $record->id = $record->itemid; try { $transaction = $DB->start_delegated_transaction(); - if ($DB->update_record('surveypro_item', $record)) { - if ($this->uses_db_table()) { - // Before saving to the plugin table, validate the variable name. - $this->item_validate_variablename($record, $record->itemid); + if ($this->insetupform['contentformat']) { + // Special care to "editors". + $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $this->context]; + $record = file_postupdate_standard_editor( + $record, 'content', $editoroptions, + $this->context, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $record->id + ); + } - $record->id = $record->pluginid; + // Variable. + $this->item_validate_variablename($record); + if ($DB->update_record('surveypro_item', $record)) { + if ($this->get_usesplugintable()) { + $record->id = $record->pluginid; if ($DB->update_record($tablename, $record)) { $this->itemeditingfeedback += 3; // 1*2^1+1*2^0 alias: editing + success. } else { @@ -495,7 +538,7 @@ public function item_save($record) { $this->item_manage_chains($record->itemid, $oldhidden, $record->hidden, $oldreserved, $record->reserved); // Event: item_modified. - $eventdata = ['context' => $context, 'objectid' => $record->itemid]; + $eventdata = ['context' => $this->context, 'objectid' => $record->itemid]; $eventdata['other'] = ['type' => $record->type, 'plugin' => $record->plugin, 'view' => SURVEYPRO_NEWITEM]; $event = \mod_surveypro\event\item_modified::create($eventdata); $event->trigger(); @@ -541,11 +584,10 @@ public function item_save($record) { /** * Validate the name of the variable to make sure it is unique. * - * @param stdobject $record - * @param integer $itemid + * @param object $record * @return void */ - public function item_validate_variablename($record, $itemid) { + public function item_validate_variablename($record) { global $DB; // If variable does not exist. @@ -553,41 +595,33 @@ public function item_validate_variablename($record, $itemid) { return; } - // Verify variable was set. If not, set $userchoosedname and $basename starting from the plugin name. + // Define $testname and $basename. if (!isset($record->variable) || empty($record->variable)) { - $userchoosedname = $this->plugin.'_001'; + $testname = $this->plugin.'_001'; $basename = $this->plugin; } else { - $userchoosedname = clean_param($record->variable, PARAM_TEXT); - if (preg_match('~^(.*)_[0-9]{3}$~', $userchoosedname, $matches)) { + $testname = clean_param($record->variable, PARAM_TEXT); + if (preg_match('~^(.*)_[0-9]{3}$~', $testname, $matches)) { $basename = $matches[1]; } else { - $basename = $userchoosedname; + $basename = $testname; } } - $testname = $userchoosedname; - - // Bloody Editing Teachers can create a boolean element, for instance, naming it 'age_001' - // having an age element named 'age_001' already onboard! - // Because of this I need to make as much queries as the number of used plugins in my surveypro! - // Get the list of used plugin. - $utilitysubmissionman = new utility_submission($this->cm, $this->surveypro); - $pluginlist = $utilitysubmissionman->get_used_plugin_list(SURVEYPRO_TYPEFIELD); - - $usednames = []; - foreach ($pluginlist as $plugin) { - $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; - $sql = 'SELECT p.itemid, p.variable + // Get all the other variables used in this surveypro. (eventually exluding the current one) + if (!isset($record->itemid) || empty($record->itemid)) { + $whereparams = ['surveyproid' => (int)$record->surveyproid]; + $usednames = $DB->get_records_menu('surveypro_item', $whereparams, 'id', 'id, variable'); + } else { + $whereparams = ['surveyproid' => (int)$record->surveyproid, 'itemid' => $record->itemid]; + $sql = 'SELECT i.id, i.variable FROM {surveypro_item} i - JOIN {'.$tablename.'} p ON p.itemid = i.id - WHERE ((i.surveyproid = :surveyproid) - AND (p.itemid <> :itemid))'; - $whereparams = ['surveyproid' => (int)$record->surveyproid, 'itemid' => $itemid]; - $usednames += $DB->get_records_sql_menu($sql, $whereparams); + WHERE ( (i.surveyproid = :surveyproid) + AND (i.id <> :itemid) )'; + $usednames = $DB->get_records_sql_menu($sql, $whereparams); } - // Verify the $userchoosedname name is unique. If not, change it. + // Verify the $testname name is unique. If not, change it. $i = 0; // If the name is a duplicate, concatenate a suffix starting from 1. while (in_array($testname, $usednames)) { $i++; @@ -598,8 +632,8 @@ public function item_validate_variablename($record, $itemid) { } /** - * Show/Hide chains of descendant/ancestors on the basis of the settings provided in the current editing process - * Make reserved/standard chains of descendant/ancestors on the basis of the settings provided in the current editing process + * Show/Hide chains of descendant/ancestors on the basis of the settings provided in the current editing process. + * Make reserved/standard chains of descendant/ancestors on the basis of the settings provided in the current editing process. * * @param integer $itemid * @param boolean $oldhidden @@ -609,7 +643,6 @@ public function item_validate_variablename($record, $itemid) { * @return void */ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserved, $newreserved) { - $context = \context_module::instance($this->cm->id); // Now hide or unhide (whether needed) chain of ancestors or descendents. if ($this->itemeditingfeedback & 1) { // Bitwise logic, alias: if the item was successfully saved. @@ -618,23 +651,23 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve if ($oldhidden != $newhidden) { $action = ($oldhidden) ? SURVEYPRO_SHOWITEM : SURVEYPRO_HIDEITEM; - $itemsetupman = new layout_itemsetup($this->cm, $context, $this->surveypro); - $itemsetupman->setup(); - $itemsetupman->set_type($this->type); - $itemsetupman->set_plugin($this->plugin); - $itemsetupman->set_itemid($itemid); - $itemsetupman->set_action($action); - $itemsetupman->set_view(SURVEYPRO_NOMODE); - $itemsetupman->set_confirm(SURVEYPRO_CONFIRMED_YES); + $itemlistman = new layout_itemlist($this->cm, $this->context, $this->surveypro); + $itemlistman->setup(); + $itemlistman->set_type($this->type); + $itemlistman->set_plugin($this->plugin); + $itemlistman->set_itemid($itemid); + $itemlistman->set_action($action); + // $itemlistman->set_view(SURVEYPRO_NOMODE); // <-- Where is it coming from? + $itemlistman->set_confirm(SURVEYPRO_CONFIRMED_YES); // Begin of: Hide/unhide part 2. if ( ($oldhidden == 1) && ($newhidden == 0) ) { - $itemsetupman->item_show_execute(); + $itemlistman->item_show_execute(); // A chain of parent items was shown. $this->itemeditingfeedback += 4; // 1*2^2. } if ( ($oldhidden == 0) && ($newhidden == 1) ) { - $itemsetupman->item_hide_execute(); + $itemlistman->item_hide_execute(); // Chain of children items was hided. $this->itemeditingfeedback += 8; // 1*2^3. } @@ -645,24 +678,24 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve if ($oldreserved != $newreserved) { $action = ($oldreserved) ? SURVEYPRO_MAKEAVAILABLE : SURVEYPRO_MAKERESERVED; - $itemsetupman = new layout_itemsetup($this->cm, $context, $this->surveypro); - $itemsetupman->setup(); - $itemsetupman->set_type($this->type); - $itemsetupman->set_plugin($this->plugin); - $itemsetupman->set_itemid($itemid); - $itemsetupman->set_action($action); - $itemsetupman->set_view(SURVEYPRO_NOMODE); - $itemsetupman->set_confirm(SURVEYPRO_CONFIRMED_YES); + $itemlistman = new layout_itemlist($this->cm, $this->context, $this->surveypro); + $itemlistman->setup(); + $itemlistman->set_type($this->type); + $itemlistman->set_plugin($this->plugin); + $itemlistman->set_itemid($itemid); + $itemlistman->set_action($action); + // $itemlistman->set_view(SURVEYPRO_NOMODE); + $itemlistman->set_confirm(SURVEYPRO_CONFIRMED_YES); // Begin of: Make reserved/free part 2. if ( ($oldreserved == 1) && ($newreserved == 0) ) { - if ($itemsetupman->item_makeavailable_execute()) { + if ($itemlistman->item_makeavailable_execute()) { // A chain of parents items inherited free access. $this->itemeditingfeedback += 16; // 1*2^4. } } if ( ($oldreserved == 0) && ($newreserved == 1) ) { - if ($itemsetupman->item_makereserved_execute()) { + if ($itemlistman->item_makereserved_execute()) { // A chain of children items inherited reserved access. $this->itemeditingfeedback += 32; // 1*2^5. } @@ -673,21 +706,20 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve } /** - * redefine the parentvalue of children items according to the new parameters of the just saved parent item. + * Redefine the parentvalue of children items according to the new parameters of the just saved parent item. * - * for instance: if I removed an item from the parent item - * while some children were using that item as condition to appear, - * I drop that item from the parentvalue of that children + * For instance: if I removed an item from the parent item + * while some children were using that item as parent, + * I drop that item from the parentvalue of that children. * * @return void */ public function item_update_childrenparentvalue() { global $DB, $CFG; - $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; - if ($classname::get_canbeparent()) { - // Take care: you can not use $this->get_content_array(SURVEYPRO_VALUES, 'options') to evaluate values - // because $item was loaded before last save, so $this->get_content_array(SURVEYPRO_VALUES, 'options') + if ($this->get_canbeparent()) { + // Take care: you can not use $this->get_textarea_content(SURVEYPRO_VALUES, 'options') to evaluate values + // because $item was loaded before last save, so $this->get_textarea_content(SURVEYPRO_VALUES, 'options') // will still return the previous values. $childrenitems = $DB->get_records('surveypro_item', ['parentid' => $this->itemid], 'id', 'id, parentvalue'); @@ -720,30 +752,73 @@ protected function item_builtin_string_load_support() { return; } + // If this routine fails it is difficult to delete each field from the surveypro using graphic user interface + // because the mdl_surveypro.template is not empty. + // To make it simple to escape trouble in case of error I delete mdl_surveypro.template now + // with the promise to set it again at the end of this method. + $DB->set_field('surveypro', 'template', null, ['id' => $surveyproid]); + // Take care: I verify the existence of the english folder even if, maybe, I will ask for strings in a different language. if (!file_exists($CFG->dirroot.'/mod/surveypro/template/'.$template.'/lang/en/surveyprotemplate_'.$template.'.php')) { // This template does not support multilang. return; } - if ($multilangfields = $this->get_multilang_fields()) { // Pagebreak and fieldsetend have no multilang_fields. - foreach ($multilangfields as $plugin) { - foreach ($plugin as $fieldname) { - // Backward compatibility. - // In the frame of https://github.com/kordan/moodle-mod_surveypro/pull/447 few multilang fields were added. - // This was really a mandatory addition but, - // opening surveypros created (from mastertemplates) before this addition, - // I may find that they don't have new added fields filled in the database - // so the corresponding property $this->{$fieldname} does not exist. - if (isset($this->{$fieldname})) { - $stringkey = $this->{$fieldname}; - $this->{$fieldname} = get_string($stringkey, 'surveyprotemplate_'.$template); - } else { - $this->{$fieldname} = ''; + if ($multilangfields = $this->get_multilang_fields(false)) { // Pagebreak and fieldsetend have no multilang_fields. + foreach ($multilangfields as $table => $mlfields) { + foreach ($mlfields as $mlfield) { + // I am using a surveypro built on a mastertemplate. + // In the template.xml I may have had, for instance, boolean_extranote_02 + // I saved (during parent::item_load) the content of template.xml in the properies of this item. + // (alias: $this->extranote = "boolean_extranote_02") + // Now, cycling over each multilang field, + // I find the key of the corresponding lang string in the properies of this item. + + // Each property was set because of the query executed in item_load but + // it may be that, for instance, I had mdl_surveypro_ite.extranote = null. + // In this case I have $this->extranote empty and this is why I need: if (!empty($this->{$mlfield})) {. + + if (!empty($this->{$mlfield})) { + // At the beginning $this->{$mlfield} may be "boolean_content_02". + $stringkey = $this->{$mlfield}; + $this->{$mlfield} = get_string($stringkey, 'surveyprotemplate_'.$template); + // Now $this->{$mlfield} is "content contains, now, '@@PLUGINFILE@@/' that did not contain before. + if (strpos($this->content, '@@PLUGINFILE@@/')) { + // Am I sure the file is already into SURVEYPRO_ITEMCONTENTFILEAREA + $fs = get_file_storage(); + $templateman = new templatebase($this->cm, $this->context, $this->surveypro); + + $regex = '~src="@@PLUGINFILE@@\/([^"]*)"~'; + if (preg_match_all($regex, $this->content, $matches)) { + foreach ($matches[1] as $filename) { + if (!$fs->get_file($this->context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $this->itemid, '/', $filename)) { + // I am using a surveypro built on a mastertemplate. + // Let's suppose an admin added a new lang file describing new pictures. + // Am I sure each new picture of the current lang file was loaded in the filearea? + // Take in mind that ONLY the files of the lang file in the language in use + // at mastertemplate apply time were loaded to filearea. + $templateman->load_new_files_from_lang($template, $this->itemid); + // Once you loaded each new file, don't check anymore. + break; + } } } + + // Special care to fields with format. + $this->content = file_rewrite_pluginfile_urls( + $this->content, 'pluginfile.php', $this->context->id, + 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $this->itemid + ); } } + + // As promised at the beginning of this method: + $DB->set_field('surveypro', 'template', $template, ['id' => $surveyproid]); } /** @@ -760,21 +835,22 @@ protected function item_builtin_string_load_support() { * [minutes] => 00 * ) * - * @param integer $time - * @return void + * @param integer $unixtime + * @return array $dateout */ - protected function item_split_unix_time($time) { - $datestring = date('Y_m_d_H_i', $time); + protected function item_split_unix_time($unixtime) { + $datestring = gmdate('Y_m_d_H_i', $unixtime); // 2012_07_11_16_03. - $getdate = []; - [$getdate['year'], $getdate['mon'], $getdate['mday'], $getdate['hours'], $getdate['minutes']] = explode('_', $datestring); + $dateout = []; + [$dateout['year'], $dateout['mon'], $dateout['mday'], $dateout['hours'], $dateout['minutes']] = explode('_', $datestring); + $dateout = array_map('intval', $dateout); - return $getdate; + return $dateout; } /** - * Does this item live into a form page?. + * Does this item live into a form page? * * Each item lives into a form page but not the pagebreak * @@ -785,7 +861,7 @@ public function item_uses_form_page() { } /** - * Does this item allow the question in left position?. + * Does this item allow the question in left position? * * Each item allows the question in left position but not the rate * @@ -796,7 +872,7 @@ public function item_left_position_allowed() { } /** - * clean the content of the field $record->{$field} (remove blank lines, trailing \r). + * Clean the content of the field $record->{$field} (remove blank lines, trailing \r). * * @param object $record Item record * @param array $fieldlist List of fields to clean @@ -816,21 +892,21 @@ protected function item_clean_textarea_fields($record, $fieldlist) { } /** - * This method defines if an item can be switched to mandatory or not. + * This method defines if an item can be set to mandatory or not. * - * Used by layout_itemsetup->display_items_table() to define the icon to show + * Used by layout_itemsetup->display_items_table() to define the icon to show. * * There are two types of fields. * 1) those for which (like the boolean) * defaultoption discriminates on the desired type of default: "Custom", "Invite", "No response" - * and, if defaultoption == "Custom", defaultvalue intervenes and declares which custom default is chosen. + * and, if defaultoption == "Custom", defaultvalue defines which custom default is choosen. * * 2) those for which (like multiselect). * noanswerdefault = 1 means "No response". * * @return boolean */ - public function item_canbemandatory() { + public function item_canbesettomandatory() { $return = true; if (isset($this->defaultoption)) { if ($this->defaultoption == SURVEYPRO_NOANSWERDEFAULT) { @@ -850,16 +926,27 @@ public function item_canbemandatory() { } /** - * Add to the item record that is going to be saved, items that can not be omitted with default value - * They, maybe, will be overwritten + * Add to the item record that is going to be saved, items that can not be omitted with default value. + * They, maybe, will be overwritten. * * @param \stdClass $record * @return void */ - public function item_add_mandatory_base_fields(&$record) { + public function item_add_fields_default_to_parent_table(&$record) { + $record->content = ''; + $record->contentformat = 1; + $record->required = 0; + $record->indent = 0; + $record->position = 0; + $record->customnumber = ''; + $record->hideinstructions = 0; + $record->variable = ''; + $record->extranote = ''; $record->hidden = 0; $record->insearchform = 0; $record->reserved = 0; + // $record->parentid = 0; + // $record->parentvalue = 0; $record->formpage = 0; $record->timecreated = time(); } @@ -879,36 +966,18 @@ public function item_add_color_unifier($mform) { } /** - * Get if the plugin uses a table into the db. - * - * @return if the plugin uses a personal table in the db. - */ - public function uses_db_table() { - return true; - } - - /** - * Uses mandatory database field? + * Uses mandatory attribute? * * Each item uses teh "mandatory" database field but not the autofill * * @return whether the item uses the "mandatory" database field */ - public static function item_uses_mandatory_dbfield() { + public static function has_mandatoryattribute() { return true; } /** - * Returns if the field plugin needs contentformat - * - * @return bool - */ - public static function response_uses_format() { - return false; - } - - /** - * Returns if the item has children + * Returns if the item has children. * * @return bool */ @@ -922,7 +991,7 @@ public function item_has_children() { } /** - * Returns if the item is a child + * Returns if the item is a child. * * @return bool */ @@ -937,10 +1006,35 @@ public function item_is_child() { return $return; } + /** + * List the fields that this plugin is expected to save as NULL in the database. + * + * @return array + */ + public function item_expected_null_fields() { + $expectednull = []; + foreach ($this->insetupform as $field => $value) { + if (!$value) { + $expectednull[] = $field; + } + } + + return $expectednull; + } + // MARK response. /** - * Report how the sql query does fit for this plugin + * Returns if the field plugin needs contentformat. + * + * @return bool + */ + public static function response_uses_format() { + return false; + } + + /** + * Report how the sql query does fit for this plugin. * * @param int $itemid * @param string $searchrestriction @@ -956,233 +1050,540 @@ public static function response_get_whereclause($itemid, $searchrestriction) { // MARK set. /** - * Defines presets for the editor field of surveyproitem in itembaseform.php. - * - * (copied from moodle20/cohort/edit.php) - * - * Some examples: - * Each SURVEYPRO_ITEMFIELD has: $this->insetupform['content'] == true and $fieldsusingformat == ['content'] - * Fieldset plugin has: $this->insetupform['content'] == true and $fieldsusingformat == null - * Pagebreak plugin has: $this->insetupform['content'] == false and $fieldsusingformat == null + * Set itemid. * + * @param int $itemid * @return void */ - public function set_editor() { - if (!$fieldsusingformat = $this->get_fieldsusingformat()) { - return; - } - - $context = \context_module::instance($this->cm->id); - // I have to set 'trusttext' => false because 'noclean' is ignored if trusttext is enabled! - $editoroptions = ['noclean' => true, 'subdirs' => true, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { - file_prepare_standard_editor($this, $fieldname, $editoroptions, $context, 'mod_surveypro', $filearea, $this->itemid); - } + public function set_itemid($itemid) { + $this->itemid = $itemid; } - // MARK get. - /** - * Get course module. + * Set pluginid. * - * @return the content of $cm property + * @param int $pluginid + * @return void */ - public function get_cm() { - return $this->cm; + public function set_pluginid($pluginid) { + $this->pluginid = $pluginid; } /** - * Get surveyproid. + * Set type. * - * @return the content of $surveyproid property + * @param string $type + * @return void */ - public function get_surveyproid() { - return $this->cm->instance; + public function set_type($type) { + $this->type = $type; } /** - * Get the list of fields using format. + * Set plugin. * - * @return the content of $fieldsusingformat property + * @param string $plugin + * @return void */ - public function get_fieldsusingformat() { - return $this->fieldsusingformat; + public function set_plugin($plugin) { + $this->plugin = $plugin; } /** - * Get if the plugin uses the position of options to save user answers. + * Set content. * - * @return bool The plugin uses the position of options to save user answers. + * @param string $content + * @return void */ - public function get_uses_positional_answer() { - return false; + public function set_content($content) { + $this->content = $content; } /** - * Get the preset for the item setup form. + * Set contentformat. * - * @return array $data + * @param string $contentformat + * @return void */ - public function get_itemform_preset() { - if (!empty($this->itemid)) { - $data = get_object_vars($this); - - // Just to save few nanoseconds. - unset($data['cm']); - unset($data['surveypro']); - unset($data['insetupform']); - } else { - $data = []; - $data['type'] = $this->type; - $data['plugin'] = $this->plugin; - } - - return $data; + public function set_contentformat($contentformat) { + $this->contentformat = $contentformat; } /** - * Get if the mform element corresponding to the propery $itemformelement has to be shown in the form. + * Set indent. * - * @param string $itemformelement - * @return true if the corresponding element has to be shown in the form; false otherwise + * @param int $indent of the item in the user form + * @return void */ - public function get_insetupform($itemformelement) { - return $this->insetupform[$itemformelement]; + public function set_indent($indent) { + $this->indent = $indent; } /** - * Get item id. + * Set position. * - * @return the content of $itemid property + * @param int $position of the content in the item in the form + * @return void */ - public function get_itemid() { - if (isset($this->itemid)) { - return $this->itemid; - } else { - return 0; - } + public function set_position($position) { + $this->position = $position; } /** - * Get type. + * Set customnumber. * - * @return the content of $type property + * @param string $customnumber of the item + * @return void */ - public function get_type() { - return $this->type; + public function set_customnumber($customnumber) { + $this->customnumber = $customnumber; } /** - * Get plugin. + * Set hideinstructions. * - * @return the content of $plugin property + * @param int $hideinstructions + * @return void */ - public function get_plugin() { - return $this->plugin; + public function set_hideinstructions($hideinstructions) { + $this->hideinstructions = (isset($hideinstructions) && !empty($hideinstructions)) ? 1 : 0; } /** - * Get content. + * Set extranote. * - * @return the content of $content property + * @param string $extranote for the item + * @return void */ - public function get_content() { - $options = ['overflowdiv' => false, 'allowid' => true, 'para' => false]; - return format_text($this->content, $this->contentformat, $options); + public function set_extranote($extranote) { + $this->extranote = $extranote; } /** - * Get content format. + * Set hidden. * - * @return the content of $contentformat property + * @param int $hidden + * @return void */ - public function get_contentformat() { - return $this->contentformat; + public function set_hidden($hidden) { + $this->hidden = (isset($hidden) && !empty($hidden)) ? 1 : 0; } /** - * Get plugin id. + * Set insearchform. * - * @return the content of $pluginid property + * @param int $insearchform + * @return void */ - public function get_pluginid() { - if (isset($this->pluginid)) { - return $this->pluginid; - } else { - return 0; - } + public function set_insearchform($insearchform) { + $this->insearchform = (isset($insearchform) && !empty($insearchform)) ? 1 : 0; } /** - * Get item name. + * Set reserved. * - * @return the content of $itemname property + * @param int $reserved + * @return void */ - public function get_itemname() { - return $this->itemname; + public function set_reserved($reserved) { + $this->reserved = (isset($reserved) && !empty($reserved)) ? 1 : 0; } /** - * Get hidden. + * Set sortindex. * - * @return the content of $hidden property + * @param int $sortindex + * @return void */ - public function get_hidden() { - return $this->hidden; + public function set_sortindex($sortindex) { + $this->sortindex = $sortindex; } /** - * Get in search form. + * Set formpage. * - * @return the content of $insearchform property + * @param int $formpage + * @return void */ - public function get_insearchform() { - return $this->insearchform; + public function set_formpage($formpage) { + $this->formpage = $formpage; } /** - * Get reserved. + * Set parentid. * - * @return the content of $reserved property + * @param int $parentid + * @return void */ - public function get_reserved() { - return $this->reserved; + public function set_parentid($parentid) { + $this->parentid = $parentid; } /** - * Get sortindex. + * Set parentvalue. * - * @return the content of $sortindex property + * @param int $parentvalue + * @return void */ - public function get_sortindex() { - return $this->sortindex; + public function set_parentvalue($parentvalue) { + $this->parentvalue = $parentvalue; } /** - * Get form page. + * Set timemodified. * - * @return the content of $formpage property + * @param int $timemodified + * @return void */ - public function get_formpage() { - return $this->formpage; + public function set_timemodified($timemodified) { + $this->timemodified = $timemodified; } /** - * Parse $this->labelother in $value and $label. + * Set timecreated. * - * @return $value - * @return $label + * @param int $timecreated + * @return void */ - protected function get_other() { - if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { - $label = trim($match[1]); - $value = trim($match[2]); - } else { - $label = trim($this->labelother); - $value = ''; - } - - return [$value, $label]; + public function set_timecreated($timecreated) { + $this->timecreated = $timecreated; + } + + /** + * Defines presets for the editor field of surveyproitem in itembaseform.php. + * + * (copied from moodle20/cohort/edit.php) + * + * Some examples: + * Each SURVEYPRO_ITEMFIELD: + * $this->insetupform['content'] == true + * $this->insetupform['contentformat'] = true + * + * Fieldset plugin: + * $this->insetupform['content'] == true + * $this->insetupform['contentformat'] = false + * + * Pagebreak plugin: + * $this->insetupform['content'] == false + * $this->insetupform['contentformat'] = false + * + * @return void + */ + public function set_editor() { + $data = new \stdClass(); + $data->content = $this->get_content(); + + if ($this->insetupform['contentformat']) { + // I have to set 'trusttext' => false because 'noclean' is ignored if trusttext is enabled! + $editoroptions = ['noclean' => true, 'subdirs' => true, 'maxfiles' => -1, 'context' => $this->context]; + $filearea = SURVEYPRO_ITEMCONTENTFILEAREA; + + $data->content = $this->get_content(); + $data->contentformat = $this->get_contentformat(); + $data = file_prepare_standard_editor( + $data, 'content', $editoroptions, $this->context, 'mod_surveypro', $filearea, $this->itemid + ); + } + + return $data; + } + + /** + * Set variable. + * + * @param string $variable + * @return void + */ + public function set_variable($variable) { + $variable = format_string($variable); + $this->variable = $variable; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $condition = false; + $condition = $condition || ($defaultoption == SURVEYPRO_CUSTOMDEFAULT); + $condition = $condition || ($defaultoption == SURVEYPRO_INVITEDEFAULT); + $condition = $condition || ($defaultoption == SURVEYPRO_NOANSWERDEFAULT); + if (!$condition) { + $message = 'Passed defaultoption is not allowed.'; + debugging($message, DEBUG_DEVELOPER); + } + + $this->defaultoption = $defaultoption; + } + + /** + * Set required. + * + * Introduced as needed by unit test. + * + * @param string $required + * @return void + */ + public function set_required($required) { + $this->required = (isset($required) && !empty($required)) ? 1 : 0; + } + + /** + * Set options. + * + * Introduced as needed by unit test. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + // MARK get. + + /** + * Make the list of the fields using multilang. + * This is the "default" list that is supposed to be empty because Pagebreak and fieldset inherit from it + * + * @param boolean $includemetafields + * @return array of fields + */ + abstract public function get_multilang_fields($includemetafields=true); + + /** + * Get course module. + * + * @return the content of $cm property + */ + public function get_cm() { + return $this->cm; + } + + /** + * Get surveyproid. + * + * @return the content of $surveyproid property + */ + public function get_surveyproid() { + return $this->cm->instance; + } + + /** + * Get type. + * + * @return the content of $type property + */ + public function get_type() { + return $this->type; + } + + /** + * Get plugin. + * + * @return the content of $plugin property + */ + public function get_plugin() { + return $this->plugin; + } + + /** + * Get content. + * + * @return the content of $content property + */ + public function get_content() { + $options = ['overflowdiv' => false, 'allowid' => true, 'para' => false]; + return format_text($this->content, $this->contentformat, $options); + } + + /** + * Get content format. + * + * @return the content of $contentformat property + */ + public function get_contentformat() { + return $this->contentformat; + } + + /** + * Get content_editor. + * + * @return the content of $contentformat property + */ + public function get_content_editor() { + return $this->content_editor; + } + + /** + * Get itemid. + * + * @return the content of $itemid property + */ + public function get_itemid() { + if (isset($this->itemid)) { + $return = $this->itemid; + } else { + $return = 0; + } + + return $return; + } + + /** + * Get plugin id. + * + * @return the content of $pluginid property + */ + public function get_pluginid() { + if (isset($this->pluginid)) { + $return = $this->pluginid; + } else { + $return = 0; + } + + return $return; + } + + /** + * Get item name. + * + * @return the content of $itemname property + */ + public function get_itemname() { + return $this->itemname; + } + + /** + * This method returns the list of the field used by the plugin. + * + * AT THE MOMENT, this method is never used. + * + * @param string $plugin + * @param string $type + * @return array + */ + public function get_plugin_fields($plugin, $type) { + global $CFG; + + if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { + $message = '$type and $plugin must be provided both or none.'; + debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); + } + + $installxmls = ['surveypro_item', 'db/install.xml']; + if (!empty($type) && !empty($plugin)) { + $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; + // Some plugins are missing the install.xml because they don't have specific attributes. + if (file_exists($installxml)) { + $installxmls['surveypro'.$type.'_'.$plugin] = $type.'/'.$plugin.'/db/install.xml'; + } + } + + foreach ($installxmls as $targettable => $installxml) { + $currentfile = $CFG->dirroot.'/mod/surveypro/'.$installxml; + $xmlall = simplexml_load_file($installxml); + foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. + foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. + $attributes = $xmltable->attributes(); + $tablename = $attributes['NAME']; + if ($tablename != $targettable) { + continue; + } + foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. + $curenttablefields = []; + foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. + $attributes = $xmlfield->attributes(); + $fieldname = $attributes['NAME']; + $curenttablefields[] = (string)$attributes['NAME']; + } + $fieldlist[$tablename] = $curenttablefields; + break; + } + // If the correct table has been found, don't go searching for one more table. Stop! + break; + } + // If the correct table has been found, don't go searching for one more table. Stop! + break; + } + } + + return $fieldlist; + } + + /** + * Get if the plugin uses the position of options to save user answers. + * + * @return bool The plugin uses the position of options to save user answers. + */ + public function get_uses_positional_answer() { + return false; + } + + /** + * Get if the mform element corresponding to the propery $itemformelement has to be shown in the form. + * + * @param string $itemformelement + * @return true if the corresponding element has to be shown in the form; false otherwise + */ + public function get_insetupform($itemformelement) { + return $this->insetupform[$itemformelement]; + } + + /** + * Get hidden. + * + * @return the content of $hidden property + */ + public function get_hidden() { + // This property is common to EACH item plugin + $return = ((empty($this->hidden)) || ($this->hidden == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get insearchform. + * + * @return the content of $insearchform property + */ + public function get_insearchform() { + // This property is common to EACH item plugin + $return = ((empty($this->insearchform)) || ($this->insearchform == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get reserved. + * + * @return the content of $reserved property + */ + public function get_reserved() { + // This property is common to EACH item plugin + $return = ((empty($this->reserved)) || ($this->reserved == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get sortindex. + * + * @return the content of $sortindex property + */ + public function get_sortindex() { + return $this->sortindex; + } + + /** + * Get formpage. + * + * @return the content of $formpage property + */ + public function get_formpage() { + return $this->formpage; } /** @@ -1192,15 +1593,17 @@ protected function get_other() { */ public function get_usesoptionother() { if (property_exists($this, 'labelother')) { - return !empty($this->labelother); + $return = !empty($this->labelother); } else { - return false; + $return = false; } + + return $return; } /** - * Get the content of textareas. Get the first or the second part of each row based on $content - * Each row is written with the format: + * Get the content of textareas. Get the first or the second part of each row based on $content. + * Each row is supposed to be written with the format: * value::label * or * label @@ -1209,9 +1612,9 @@ public function get_usesoptionother() { * @param string $field Name of the text area field, source of the multiline text * @return array $values */ - public function get_content_array($content, $field) { + public function get_textarea_content($content, $field) { if (($content != SURVEYPRO_VALUES) && ($content != SURVEYPRO_LABELS)) { - throw new Exception('Bad parameter passed to get_content_array'); + throw new Exception('Bad parameter passed to get_textarea_content'); } $index = ($content == SURVEYPRO_VALUES) ? 1 : 2; @@ -1231,16 +1634,19 @@ public function get_content_array($content, $field) { } /** - * Make the list of the fields using multilang - * This is the "default" list that is supposed to be empty because Pagebreak and fieldset inherit from it + * Provide the list of the fields of surveypro_item using multilang. * - * @return array of felds + * @param boolean $includemetafields true if you need filename and filecontent too. + * @return array the list of the fields of surveypro_item using multilang */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = []; + public function get_base_multilang_fields($includemetafields) { + if ($includemetafields) { + $return = ['content', 'filename', 'filecontent', 'extranote']; + } else { + $return = ['content', 'extranote']; + } - return $fieldlist; + return $return; } /** @@ -1282,14 +1688,17 @@ public function get_parentvalue() { * Get the requested property. * * @param string $field - * @return the content of the field whether defined + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { if (isset($this->{$field})) { - return $this->{$field}; + $method = 'get_'.$field; + $return = $this->{$method}(); } else { - return false; + $return = false; } + + return $return; } /** @@ -1308,29 +1717,29 @@ public function get_variable() { */ public function get_customnumber() { if (isset($this->customnumber)) { - return $this->customnumber; + $return = $this->customnumber; } else { - return false; + $return = false; } + + return $return; } /** * Get required. * - * @return bool false if the property is not set for the class (like, for instance, for autofill or label) - * int 0|1 acording to the property + * @return int 0|1 acording to the property + * bool false if the property is not set (like, for instance, for autofill or label) */ public function get_required() { // It may be not set as in page_break, autofill or some more. - if (!isset($this->required)) { - return false; + if (isset($this->required)) { + $return = empty($this->required) ? 0 : 1; } else { - if (empty($this->required)) { - return 0; - } else { - return 1; - } + $return = false; } + + return $return; } /** @@ -1352,11 +1761,14 @@ public function get_indent() { * @return the content of $hideinstructions property whether defined */ public function get_hideinstructions() { + // It may be not set in some plugin item if (isset($this->hideinstructions)) { - return $this->hideinstructions; + $return = empty($this->hideinstructions) ? 0 : 1; } else { - return false; + $return = false; } + + return $return; } /** @@ -1385,6 +1797,49 @@ public function get_extranote() { } } + /** + * Returns the list of common item properties. + * + * @return array $data + */ + public function get_base_properties() { + $baseproperties = [ + 'surveyproid', 'type', 'plugin', 'content', 'contentformat', 'required', 'indent', 'position', + 'customnumber', 'hideinstructions', 'variable', 'extranote', 'hidden', 'insearchform', 'reserved', + 'parentid', 'parentvalue', 'parentcontent', + ]; + + return $baseproperties; + } + + /** + * Prepare presets for itemsetuprform. + * + * @param array $pluginproperties + * @return array $data + */ + public function get_base_presets($pluginproperties) { + if (!empty($this->itemid)) { + $baseproperties = $this->get_base_properties(); + $properties = array_merge($baseproperties, $pluginproperties); + + $data = $this->set_editor(); // Now $data is a new \stdClass(). + $data->itemid = $this->get_itemid(); // Mandatory! + $data->pluginid = $this->get_pluginid(); // Mandatory! + foreach ($properties as $property) { + $method = 'get_'.$property; + $data->{$property} = $this->{$method}(); + } + // Parentcontent does not come from db. + } else { + $data = new \stdClass(); + $data->type = $this->type; + $data->plugin = $this->plugin; + } + + return $data; + } + /** * Get downloadformat. * @@ -1528,6 +1983,28 @@ public function get_itemeditingfeedback() { return $this->itemeditingfeedback; } + /** + * Does this item use a specific table? + * + * @return the content of the static property "usesplugintable" + */ + public function get_usesplugintable() { + $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; + + return $classname::$usesplugintable; + } + + /** + * Can this item be parent? + * + * @return the content of the static property "canbeparent" + */ + public function get_canbeparent() { + $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; + + return $classname::$canbeparent; + } + /** * Return the xml schema for surveypro_<> table. * @@ -1541,9 +2018,26 @@ public static function get_itembase_schema() { - - - + + + + + + + + + + + + + + + + + + + + @@ -1561,86 +2055,6 @@ public static function get_itembase_schema() { return $schema; } - // MARK set. - - /** - * Set contentformat. - * - * @param string $contentformat - * @return void - */ - public function set_contentformat($contentformat) { - $this->contentformat = $contentformat; - } - - /** - * Set variable. - * - * @param string $variable - * @return void - */ - public function set_variable($variable) { - $variable = format_string($variable); - $this->variable = $variable; - } - - /** - * Set defaultoption. - * - * Introduced as needed by unit test. - * - * @param string $defaultoption - * @return void - */ - public function set_defaultoption($defaultoption) { - $condition = false; - $condition = $condition || ($defaultoption == SURVEYPRO_CUSTOMDEFAULT); - $condition = $condition || ($defaultoption == SURVEYPRO_INVITEDEFAULT); - $condition = $condition || ($defaultoption == SURVEYPRO_NOANSWERDEFAULT); - if (!$condition) { - $message = 'Passed defaultoption is not allowed.'; - debugging($message, DEBUG_DEVELOPER); - } - - $this->defaultoption = $defaultoption; - } - - /** - * Set labelother. - * - * Introduced as needed by unit test. - * - * @param string $labelother - * @return void - */ - public function set_labelother($labelother) { - $this->labelother = (string)$labelother; - } - - /** - * Set required. - * - * Introduced as needed by unit test. - * - * @param string $required - * @return void - */ - public function set_required($required) { - $this->labelother = $required; - } - - /** - * Set options. - * - * Introduced as needed by unit test. - * - * @param string $options - * @return void - */ - public function set_options($options) { - $this->options = $options; - } - // MARK parent. /** @@ -1693,16 +2107,20 @@ public function userform_get_full_info($searchform) { } } } + + $return = ''; if (isset($fillinginstruction) && $fillinginstruction && isset($extranote) && $extranote) { - return $fillinginstruction.'
'.$extranote; + $return = $fillinginstruction.'
'.$extranote; } else { if (isset($fillinginstruction) && $fillinginstruction) { - return $fillinginstruction; + $return = $fillinginstruction; } if (isset($extranote) && $extranote) { - return $extranote; + $return = $extranote; } } + + return $return; } /** @@ -1753,8 +2171,8 @@ public function userform_is_child_allowed_static($submissionid, $childitemrecord } /** - * This function is used ONLY if $surveypro->newpageforchild == false - * it adds as much as needed $mform->disabledIf to disable items when parent condition does not match + * This function is used ONLY if $surveypro->newpageforchild == false. + * It adds as much as needed $mform->disabledIf to disable items when parent condition does not match * This method is used by the child item * In the frame of this method the parent item is loaded and is requested to provide the disabledif conditions for its child * @@ -1802,7 +2220,7 @@ public function userform_add_disabledif($mform) { $displaydebuginfo = false; foreach ($parentrestrictions as $parentid => $childparentvalue) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $parentid); $disabilitationinfo = $parentitem->userform_get_parent_disabilitation_info($childparentvalue); if ($displaydebuginfo) { diff --git a/classes/layout_branchingvalidation.php b/classes/layout_branchingvalidation.php index 86268db63cc..f4ad8e661db 100644 --- a/classes/layout_branchingvalidation.php +++ b/classes/layout_branchingvalidation.php @@ -161,12 +161,12 @@ public function display_relations_table() { echo $OUTPUT->notification($message, 'notifymessage'); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemishidden = $item->get_hidden(); if ($item->get_parentid()) { // Here I do not know type and plugin. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $item->get_parentid()); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $item->get_parentid()); } $tablerow = []; @@ -265,7 +265,6 @@ public function display_relations_table() { $itemseeds->close(); $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } } diff --git a/classes/layout_itemlist.php b/classes/layout_itemlist.php index 9f75cb6b51b..e8a2dc37221 100644 --- a/classes/layout_itemlist.php +++ b/classes/layout_itemlist.php @@ -127,7 +127,7 @@ class layout_itemlist { protected $itemeditingfeedback; /** - * @var StdClass object with the feedback for the user + * @var stdClass object with the feedback for the user */ protected $actionfeedback; @@ -256,7 +256,8 @@ public function display_items_table() { $righticn = new \pix_icon('t/right', $indentstr, 'moodle', $iconparams); $moveherestr = get_string('movehere'); - $movehereicn = new \pix_icon('movehere', $moveherestr, 'moodle', ['title' => $moveherestr, 'class' => 'placeholder']); + $iconparams = ['title' => $moveherestr]; + $movehereicn = new \pix_icon('movehere', $moveherestr, 'moodle', $iconparams); $availablestr = get_string('available_title', 'mod_surveypro'); $iconparams = ['title' => $availablestr]; @@ -316,7 +317,7 @@ public function display_items_table() { } foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemid = $itemseed->itemid; $itemishidden = $item->get_hidden(); $sortindex = $item->get_sortindex(); @@ -529,12 +530,15 @@ public function display_items_table() { } // SURVEYPRO_REQUIRED ON/OFF. - $currentrequired = $item->get_required(); - if ($currentrequired !== false) { // It may be "not set" as in page_break, autofill or some more. + $plugin = $item->get_plugin(); + $type = $item->get_type(); + $classname = 'surveypro'.$type.'_'.$plugin.'\item'; + $usesmandatoryattribute = $classname::has_mandatoryattribute(); + if ($usesmandatoryattribute) { // It may be not used as in page_break, autofill or some more. $paramurl = $paramurlbase; $paramurl['sesskey'] = sesskey(); - if ($item->item_canbemandatory()) { + if ($item->item_canbesettomandatory()) { $required = $item->get_required(); $tmpl = new layout_required($itemid, $required, $sortindex); $tmpl->set_type_toggle(); @@ -623,7 +627,6 @@ public function display_items_table() { } $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } @@ -727,12 +730,12 @@ public function display_relations_table() { echo $OUTPUT->notification($message, 'notifymessage'); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemishidden = $item->get_hidden(); if ($item->get_parentid()) { // Here I do not know type and plugin. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $item->get_parentid()); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $item->get_parentid()); } $tablerow = []; @@ -831,7 +834,6 @@ public function display_relations_table() { $itemseeds->close(); $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } @@ -998,8 +1000,8 @@ public function actions_execution() { redirect($returnurl); break; case SURVEYPRO_CHANGEINDENT: - $where = ['itemid' => $this->rootitemid]; - $DB->set_field('surveypro'.$this->type.'_'.$this->plugin, 'indent', $this->nextindent, $where); + $where = ['id' => $this->rootitemid]; + $DB->set_field('surveypro_item', 'indent', $this->nextindent, $where); break; case SURVEYPRO_MAKERESERVED: $this->item_makereserved_execute(); @@ -1173,7 +1175,7 @@ public function item_hide_feedback() { if ($this->confirm == SURVEYPRO_UNCONFIRMED) { if ($itemstoprocess > 1) { // Ask for confirmation. $dependencies = []; - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->itemcontent = $item->get_content(); @@ -1263,7 +1265,7 @@ public function item_show_feedback() { $itemstoprocess = count($toshowlist); // This is the list of ancestors. if ($this->confirm == SURVEYPRO_UNCONFIRMED) { if ($itemstoprocess > 1) { // Ask for confirmation. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->lastitem = $item->get_content(); @@ -1388,7 +1390,7 @@ public function item_makereserved_feedback() { if ($itemstoprocess > 1) { // Ask for confirmation. // If the clicked element has not parents. $a = new \stdClass(); - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a->itemcontent = $item->get_content(); foreach ($itemstoreserve as $itemtoreserve) { $dependencies[] = $itemtoreserve->sortindex; @@ -1402,7 +1404,7 @@ public function item_makereserved_feedback() { if ($baseitemid != $this->rootitemid) { $firstparentitem = reset($itemstoreserve); - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $firstparentitem->id); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $firstparentitem->id); $a->parentcontent = $parentitem->get_content(); $message = get_string('confirm_reservechainitems_newparent', 'mod_surveypro', $a); } else { @@ -1515,7 +1517,7 @@ public function item_makeavailable_feedback() { if ($itemstoprocess > 1) { // Ask for confirmation. // If the clicked element has not parents. $a = new \stdClass(); - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a->itemcontent = $item->get_content(); foreach ($itemstoavailable as $itemtoavailable) { $dependencies[] = $itemtoavailable->sortindex; @@ -1529,7 +1531,7 @@ public function item_makeavailable_feedback() { if ($baseitemid != $this->rootitemid) { $firstparentitem = reset($itemstoavailable); - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $firstparentitem->id); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $firstparentitem->id); $a->parentcontent = $parentitem->get_content(); $message = get_string('confirm_freechainitems_newparent', 'mod_surveypro', $a); } else { @@ -1600,7 +1602,7 @@ public function item_delete_execute() { } // Get the content of the item for the feedback message. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $killedsortindex = $item->get_sortindex(); $whereparams = ['id' => $this->rootitemid]; @@ -1630,7 +1632,7 @@ public function item_delete_feedback() { if ($this->confirm == SURVEYPRO_UNCONFIRMED) { // Ask for confirmation. // In the frame of the confirmation I need to declare whether some child will break the link. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->content = $item->get_content(); @@ -2047,34 +2049,48 @@ public function drop_multilang_execute() { global $DB; if ($this->confirm == SURVEYPRO_CONFIRMED_YES) { + // Overwrite keys from the database and replace it with the actual strings. $template = $this->surveypro->template; + $where = ['surveyproid' => $this->surveypro->id]; $itemseeds = $DB->get_records('surveypro_item', $where, 'sortindex', 'id, type, plugin'); foreach ($itemseeds as $itemseed) { $id = $itemseed->id; $type = $itemseed->type; $plugin = $itemseed->plugin; - $item = surveypro_get_item($this->cm, $this->surveypro, $id, $type, $plugin); - $itemsmlfields = $item->get_multilang_fields(); // Pagebreak and fieldsetend have no multilang_fields. - if ($itemsmlfields[$plugin]) { - // Note: ml means multi language. - foreach ($itemsmlfields as $itemmlfield) { // Note: $itemmlfield is an array of fields. + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $id, $type, $plugin); + + $itemsmlfields = $item->get_multilang_fields(false); + if ($itemsmlfields) { // Pagebreak and fieldsetend have no multilang_fields. + // SELECT content,extranote,options,labelother,defaultvalue FROM {surveyprofield_radiobutton} WHERE id = 8. + foreach ($itemsmlfields as $table => $fields) { // Note: $itemmlfield is an array of arrays of fields. + if (!count($fields)) { + continue; + } $record = new \stdClass(); - $record->id = $item->get_pluginid(); - - $where = ['id' => $record->id]; - $fieldlist = implode(',', $itemmlfield); - // SELECT content,extranote,options,labelother,defaultvalue FROM {surveyprofield_radiobutton} WHERE id = 8. - $reference = $DB->get_record('surveypro'.$type.'_'.$plugin, $where, $fieldlist, MUST_EXIST); - foreach ($itemmlfield as $mlfieldname) { - $stringkey = $reference->{$mlfieldname}; + + $fieldlist = implode(',', $fields); + if ($table == 'surveypro_item') { + $where = ['id' => $id]; + $savedrecord = $DB->get_record($table, $where, $fieldlist, MUST_EXIST); + $record->id = $id; + } else { + $where = ['itemid' => $id]; + $savedrecord = $DB->get_record($table, $where, 'id,'.$fieldlist, MUST_EXIST); + $record->id = $savedrecord->id; + } + + foreach ($fields as $mlfieldname) { + $stringkey = $savedrecord->{$mlfieldname}; + if (core_text::strlen($stringkey)) { $record->{$mlfieldname} = get_string($stringkey, 'surveyprotemplate_'.$template); } else { $record->{$mlfieldname} = null; } } - $DB->update_record('surveypro'.$type.'_'.$plugin, $record); + + $DB->update_record($table, $record); } } } @@ -2115,14 +2131,14 @@ public function drop_multilang_feedback() { // Ask for confirmation. $message = get_string('confirm_dropmultilang', 'mod_surveypro'); - $optionbase = ['s' => $this->cm->instance, 'act' => SURVEYPRO_DROPMULTILANG, 'section' => 'itemslist']; + $optionbase = ['s' => $this->cm->instance]; - $optionsyes = $optionbase; + $optionsyes = $optionbase + ['section' => 'itemslist', 'act' => SURVEYPRO_DROPMULTILANG]; $optionsyes['cnf'] = SURVEYPRO_CONFIRMED_YES; $urlyes = new \moodle_url('/mod/surveypro/layout.php', $optionsyes); $buttonyes = new \single_button($urlyes, get_string('yes')); - $optionsno = $optionbase; + $optionsno = $optionbase + ['section' => 'preview']; $optionsno['cnf'] = SURVEYPRO_CONFIRMED_NO; $urlno = new \moodle_url('/mod/surveypro/layout.php', $optionsno); $buttonno = new \single_button($urlno, get_string('no')); diff --git a/classes/layout_itemsetup.php b/classes/layout_itemsetup.php index 362fb7beb1b..f3de30730b7 100644 --- a/classes/layout_itemsetup.php +++ b/classes/layout_itemsetup.php @@ -287,10 +287,10 @@ public function prevent_direct_user_input() { * * @return void */ - public function item_identitycard() { + public function display_iteminfo() { global $OUTPUT; - $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '.. + $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $friendlyname = get_string('userfriendlypluginname', 'surveypro'.$this->type.'_'.$this->plugin); $iconparams = ['title' => $friendlyname, 'class' => 'icon']; diff --git a/classes/local/form/item_chooser.php b/classes/local/form/item_chooser.php index d8d6d110cbb..a7b3a473d9a 100644 --- a/classes/local/form/item_chooser.php +++ b/classes/local/form/item_chooser.php @@ -54,13 +54,13 @@ public function definition() { // Take care! Here the plugin holds type and plugin both. $fieldplugins = surveypro_get_plugin_list(SURVEYPRO_TYPEFIELD, true); foreach ($fieldplugins as $k => $v) { - $fieldplugins[$k] = get_string('userfriendlypluginname', 'surveyprofield_'.$v); + $fieldplugins[$k] = get_string('userfriendlypluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$v); } asort($fieldplugins); $formatplugins = surveypro_get_plugin_list(SURVEYPRO_TYPEFORMAT, true); foreach ($formatplugins as $k => $v) { - $formatplugins[$k] = get_string('userfriendlypluginname', 'surveyproformat_'.$v); + $formatplugins[$k] = get_string('userfriendlypluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$v); } asort($formatplugins); @@ -70,7 +70,7 @@ public function definition() { $elementgroup = []; $elementgroup[] = $mform->createElement('selectgroups', $fieldname, '', $pluginlist); $elementgroup[] = $mform->createElement('submit', $fieldname.'_button', get_string('add')); - $mform->addGroup($elementgroup, $fieldname.'_group', get_string($fieldname, 'mod_surveypro'), [' '], false); + $mform->addGroup($elementgroup, $fieldname.'_group', get_string('item', 'mod_surveypro'), [' '], false); $mform->addHelpButton($fieldname.'_group', $fieldname, 'surveypro'); } } diff --git a/classes/local/form/item_setupbaseform.php b/classes/local/form/item_setupbaseform.php index 68ecf9a2d37..d2b84948494 100644 --- a/classes/local/form/item_setupbaseform.php +++ b/classes/local/form/item_setupbaseform.php @@ -52,6 +52,7 @@ public function definition() { // Get _customdata. $item = $this->_customdata['item']; + // $fortheeditor = $item->get_fortheeditor(); $surveypro = $item->surveypro; $cm = $item->get_cm(); @@ -84,8 +85,7 @@ public function definition() { // Itembase: content & contentformat. if ($item->get_insetupform('content')) { - $fieldsusingformat = $item->get_fieldsusingformat(); - if (array_key_exists('content', $fieldsusingformat)) { + if ($item->insetupform['contentformat']) { $fieldname = 'content_editor'; $editoroptions = ['trusttext' => true, 'subdirs' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES]; $mform->addElement('editor', $fieldname, get_string($fieldname, 'mod_surveypro'), null, $editoroptions); @@ -212,13 +212,13 @@ public function definition() { // $classname::get_canbeparent() == true; // I also should include the clause "reserved = my one" but I omit this validation // because the surveypro creator can, at every time, change the availability of the current item. - // So I move the validation of the holding form at the form validation time. + // So I move the validation of the holding form at form validation time. - // Build the list only for searchable plugins. + // Build the list only for items that can be parent. $pluginlist = surveypro_get_plugin_list(SURVEYPRO_TYPEFIELD); foreach ($pluginlist as $plugin) { - $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - if (!$classname::get_canbeparent()) { + $dummyitem = surveypro_get_itemclass($cm, $surveypro, 0, SURVEYPRO_TYPEFIELD, $plugin); + if (!$dummyitem->get_canbeparent()) { unset($pluginlist[$plugin]); } } @@ -239,13 +239,13 @@ public function definition() { $select = $quickform->createElement('select', $fieldname, get_string($fieldname, 'mod_surveypro')); $select->addOption(get_string('choosedots'), 0); foreach ($parentsseeds as $parentsseed) { - $parentitem = surveypro_get_item($cm, $surveypro, $parentsseed->id, $parentsseed->type, $parentsseed->plugin); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $parentsseed->id, $parentsseed->type, $parentsseed->plugin); $star = ($parentitem->get_reserved()) ? '(*) ' : ''; // I do not need to take care of contents of items of master templates // because if I am here, $parent is a standard item and not a multilang one. $content = $star; - $content .= get_string('pluginname', 'surveyprofield_'.$parentitem->get_plugin()); + $content .= get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$parentitem->get_plugin()); $content .= ' ['.$parentitem->get_sortindex().']: '.strip_tags($parentitem->get_content()); $content = surveypro_cutdownstring($content); @@ -277,11 +277,11 @@ public function definition() { $rowparity = 1 - $rowparity; $a->examples .= \html_writer::start_tag('tr', ['class' => 'r' . $rowparity]); $a->examples .= \html_writer::start_tag('td', ['class' => 'pluginname']); - $a->examples .= get_string('pluginname', 'surveyprofield_'.$plugin); + $a->examples .= get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin); $a->examples .= \html_writer::end_tag('td'); $a->examples .= \html_writer::start_tag('td', ['class' => 'inputformat']); - $a->examples .= get_string('parentformat', 'surveyprofield_'.$plugin); + $a->examples .= get_string('parentformat', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin); $a->examples .= \html_writer::end_tag('td'); $a->examples .= \html_writer::end_tag('tr'); } @@ -293,7 +293,7 @@ public function definition() { if ($item->get_type() == SURVEYPRO_TYPEFIELD) { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyprofield_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); } } diff --git a/classes/local/form/mtemplate_applyform.php b/classes/local/form/mtemplate_applyform.php index dc96c33c6d6..7c6ec297383 100644 --- a/classes/local/form/mtemplate_applyform.php +++ b/classes/local/form/mtemplate_applyform.php @@ -99,8 +99,10 @@ public function validation($data, $files) { $templatename = $data['mastertemplate']; $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$templatename.'/template.xml'; $xml = file_get_contents($templatepath); - $errormessage = $applyman->validate_xml($xml); - if ($errormessage !== false) { + + $applyman->validate_xml($xml); + $errormessage = $applyman->get_xmlvalidationoutcome(); + if (!empty($errormessage->key)) { $addendum = get_string('mastertemplateaddendum', 'mod_surveypro'); if (isset($errormessage->a)) { $errors['mastertemplate'] = get_string($errormessage->key, 'mod_surveypro', $errormessage->a).$addendum; diff --git a/classes/local/form/mtemplate_createform.php b/classes/local/form/mtemplate_createform.php index 2da180fac1f..9c97af9b4a9 100644 --- a/classes/local/form/mtemplate_createform.php +++ b/classes/local/form/mtemplate_createform.php @@ -45,6 +45,9 @@ class mtemplate_createform extends \moodleform { public function definition() { $mform = $this->_form; + // Get _customdata. + $defaultname = $this->_customdata->defaultname; + // Mtemplatecreate: surveyproid. $fieldname = 'surveyproid'; $mform->addElement('hidden', $fieldname, 0); @@ -56,6 +59,7 @@ public function definition() { $mform->addHelpButton($fieldname, $fieldname, 'surveypro'); $mform->addRule($fieldname, get_string('required'), 'required', null, 'client'); $mform->setType($fieldname, PARAM_FILE); // This word is going to be a file name. + $mform->setDefault($fieldname, $defaultname); $this->add_action_buttons(false, get_string('save', 'mod_surveypro')); } diff --git a/classes/local/form/usersearch.php b/classes/local/form/response_searchform.php similarity index 89% rename from classes/local/form/usersearch.php rename to classes/local/form/response_searchform.php index 1417e692f5b..23e1fac68d3 100644 --- a/classes/local/form/usersearch.php +++ b/classes/local/form/response_searchform.php @@ -37,7 +37,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class usersearch extends \moodleform { +class response_searchform extends \moodleform { /** * Definition. @@ -63,7 +63,7 @@ public function definition() { // so they and are not selected by the css3 selector: fieldset div.fitem:nth-of-type(even) {. $mform->addElement('static', 'beginning_extrarow', '', ''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); // Position. $position = $item->get_position(); @@ -71,8 +71,9 @@ public function definition() { if ($position == SURVEYPRO_POSITIONTOP) { $itemname = $item->get_itemname().'_extrarow'; $content = $item->get_content(); - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, $elementnumber, $content, $option); + + $elementgroup[] = $mform->createElement('static', $itemname, $elementnumber, $content); + $mform->addGroup($elementgroup, $this->itemname.'_group', '', '', false, $class); $item->item_add_color_unifier($mform); } @@ -107,8 +108,11 @@ public function definition() { $item->item_add_color_unifier($mform); $itemname = $item->get_itemname().'_info'; - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, get_string('note', 'mod_surveypro'), $fullinfo, $option); + + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, get_string('note', 'mod_surveypro'), $fullinfo); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); + } } $itemseeds->close(); @@ -151,7 +155,7 @@ public function validation($data, $files) { $olditemid = $itemid; - $item = surveypro_get_item($cm, $surveypro, $itemid, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $type, $plugin); $item->userform_mform_validation($data, $errors, true); } } diff --git a/classes/local/form/userform.php b/classes/local/form/response_submitform.php similarity index 81% rename from classes/local/form/userform.php rename to classes/local/form/response_submitform.php index 1a1e0aa06d0..2b65782ede3 100644 --- a/classes/local/form/userform.php +++ b/classes/local/form/response_submitform.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The class representing the out form + * The class representing the surveypro form for the student * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -37,7 +37,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class userform extends \moodleform { +class response_submitform extends \moodleform { /** * Definition. @@ -67,20 +67,20 @@ public function definition() { $notestr = get_string('note', 'mod_surveypro'); - // Userform: s. + // Response_submitform: s. $mform->addElement('hidden', 's', $surveypro->id); $mform->setType('s', PARAM_INT); - // Userform: submissionid. + // Response_submitform: submissionid. // I usually set 0 into mform elements and then I replace them with preset. // Here I can not follow this habit because... - // if the userform has autofill items (that may use labels), in order to display them + // if the Response_submitform has autofill items (that may use labels), in order to display them // I need to ask to $mform the value of $submissionid. $mform->addElement('hidden', 'submissionid', $submissionid); $mform->setType('submissionid', PARAM_INT); - // Userform: formpage. - // Value is provided by $userform->set_data($prefill); in view.php ['section' => 'submissionform']. + // Response_submitform: formpage. + // Value is provided by $response_submitform->set_data($prefill); in view.php ['section' => 'responsesubmit']. $mform->addElement('hidden', 'formpage', 0); $mform->setType('formpage', PARAM_INT); @@ -99,6 +99,10 @@ public function definition() { $mform->addElement('static', 'nomoreitems', $notestr, get_string('nomoreitems', 'mod_surveypro', $a)); } + if ($mode == SURVEYPRO_PREVIEWMODE) { + $this->add_buttons($surveypro, $formpage, $userfirstpage, $userlastpage, $mode); + } + foreach ($itemseeds as $itemseed) { if ($mode == SURVEYPRO_PREVIEWMODE) { $itemaschildisallowed = true; @@ -106,7 +110,7 @@ public function definition() { // Is the current item allowed in this page? if ($itemseed->parentid) { // Get it now AND NEVER MORE. - $parentitem = surveypro_get_item($cm, $surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $itemseed->parentid); // If parentitem is in a previous page, have a check // otherwise @@ -124,7 +128,7 @@ public function definition() { } if ($itemaschildisallowed) { - $item = surveypro_get_item($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); // Position. $position = $item->get_position(); @@ -132,8 +136,10 @@ public function definition() { if ($position == SURVEYPRO_POSITIONTOP) { $itemname = $item->get_itemname().'_extrarow'; $content = $item->get_contentwithnumber(); - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, $elementnumber, $content, $option); + $class = ['class' => 'indent-'.$item->get_indent()]; + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, $elementnumber, $content); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); $item->item_add_color_unifier($mform); } @@ -158,8 +164,10 @@ public function definition() { $item->item_add_color_unifier($mform); $itemname = $item->get_itemname().'_note'; - $attributes = ['class' => 'indent-'.$item->get_indent().' label_static']; - $mform->addElement('mod_surveypro_label', $itemname, '', $fullinfo, $attributes); + $class = ['class' => 'indent-'.$item->get_indent()]; + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, '', $fullinfo); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); } if (!$surveypro->newpageforchild) { @@ -181,57 +189,7 @@ public function definition() { return; } - // Buttons. - $buttonlist = []; - if ($formpage > $userfirstpage) { - $buttonlist['prevbutton'] = get_string('previousformpage', 'mod_surveypro'); - } - if ($mode != SURVEYPRO_PREVIEWMODE) { - $pasuseresumesurvey = ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMENOEMAIL); - $pasuseresumesurvey = $pasuseresumesurvey || ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMEEMAIL); - if ($pasuseresumesurvey) { - $buttonlist['pausebutton'] = get_string('pause', 'mod_surveypro'); - } - if ($formpage == $userlastpage) { - if ($surveypro->history) { - $where = ['id' => $submissionid]; - $submissionstatus = $DB->get_field('surveypro_submission', 'status', $where, IGNORE_MISSING); - if ($submissionstatus === false) { // Submissions still does not exist. - $usesimplesavebutton = true; - } else { - $usesimplesavebutton = ($submissionstatus == SURVEYPRO_STATUSINPROGRESS); - } - } else { - $usesimplesavebutton = true; - } - if ($usesimplesavebutton) { - $buttonlist['savebutton'] = get_string('submit'); - } else { - $buttonlist['saveasnewbutton'] = get_string('saveasnew', 'mod_surveypro'); - } - } - } - if ($formpage < $userlastpage) { - $buttonlist['nextbutton'] = get_string('nextformpage', 'mod_surveypro'); - } - - if (count($buttonlist) == 1) { - $name = array_key_first($buttonlist); - $label = $buttonlist[$name]; - - $mform->closeHeaderBefore($name); - $mform->addElement('submit', $name, $label); - } - - if (count($buttonlist) > 1) { - $buttonarray = []; - foreach ($buttonlist as $name => $label) { - $buttonarray[] = $mform->createElement('submit', $name, $label); - } - $mform->addGroup($buttonarray, 'buttonsrow', '', ' ', false); - $mform->setType('buttonsrow', PARAM_RAW); - $mform->closeHeaderBefore('buttonsrow'); - } + $this->add_buttons($surveypro, $formpage, $userfirstpage, $userlastpage, $mode); } /** @@ -284,7 +242,7 @@ public function validation($data, $files) { $olditemid = $itemid; - $item = surveypro_get_item($cm, $surveypro, $itemid, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $type, $plugin); if ($surveypro->newpageforchild) { $itemisenabled = true; // Since it is displayed, it is enabled. $parentitem = null; @@ -295,7 +253,7 @@ public function validation($data, $files) { $parentitem = null; } else { // Call its parent. - $parentitem = surveypro_get_item($cm, $surveypro, $parentitemid); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $parentitemid); // Tell parent that his child has parentvalue = 1;3. if ($parentitem->get_formpage() == $item->get_formpage()) { $itemisenabled = $parentitem->userform_is_child_allowed_dynamic($item->get_parentvalue(), $data); @@ -307,25 +265,95 @@ public function validation($data, $files) { } if ($itemisenabled) { - $propertyexists = property_exists('surveypro'.$type.'_'.$plugin.'\item', 'trimonsave'); - if ($propertyexists && $item->get_trimonsave()) { - if (trim($content) != $content) { - $warnings[$elementname] = get_string('uerr_willbetrimmed', 'mod_surveypro'); - } - } $item->userform_mform_validation($data, $errors, false); } + // Otherwise... // Code: echo 'parent item doesn\'t allow the validation of the child item '.$item->itemid;. // Code: echo ', plugin = '.$item->plugin.'('.$item->content.')
';. } } - if ($errors) { - // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. - $errors += $warnings; + return $errors; + } + + + /** + * Add buttons at the end of the submitform. + * + * @return void + */ + public function add_buttons() { + global $DB; + + $mform = $this->_form; + + $surveypro = $this->_customdata->surveypro; + $submissionid = $this->_customdata->submissionid; + $formpage = $this->_customdata->formpage; + $userfirstpage = $this->_customdata->userfirstpage; + $userlastpage = $this->_customdata->userlastpage; + $mode = $this->_customdata->mode; + + // Buttons. + $buttonlist = []; + if ($formpage > $userfirstpage) { + $buttonlist['prevbutton'] = get_string('previousformpage', 'mod_surveypro'); + } + if ($mode != SURVEYPRO_PREVIEWMODE) { + $pasuseresumesurvey = ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMENOEMAIL); + $pasuseresumesurvey = $pasuseresumesurvey || ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMEEMAIL); + if ($pasuseresumesurvey) { + $buttonlist['pausebutton'] = get_string('pause', 'mod_surveypro'); + } + if ($formpage == $userlastpage) { + if ($surveypro->history) { + $where = ['id' => $submissionid]; + $submissionstatus = $DB->get_field('surveypro_submission', 'status', $where, IGNORE_MISSING); + if ($submissionstatus === false) { // Submissions still does not exist. + $usesimplesavebutton = true; + } else { + $usesimplesavebutton = ($submissionstatus == SURVEYPRO_STATUSINPROGRESS); + } + } else { + $usesimplesavebutton = true; + } + if ($usesimplesavebutton) { + $buttonlist['savebutton'] = get_string('submit'); + } else { + $buttonlist['saveasnewbutton'] = get_string('saveasnew', 'mod_surveypro'); + } + } + $buttonlist['cancelbutton'] = get_string('cancel'); + } + if ($formpage < $userlastpage) { + $buttonlist['nextbutton'] = get_string('nextformpage', 'mod_surveypro'); } - return $errors; + if (count($buttonlist) == 1) { + $name = array_key_first($buttonlist); + $label = $buttonlist[$name]; + + $mform->closeHeaderBefore($name); + if ($name == 'cancelbutton') { + $mform->addElement('cancel'); + } else { + $mform->addElement('submit', $name, $label); + } + } + + if (count($buttonlist) > 1) { + $buttonarray = []; + foreach ($buttonlist as $name => $label) { + if ($name == 'cancelbutton') { + $buttonarray[] = $mform->createElement('cancel'); + } else { + $buttonarray[] = $mform->createElement('submit', $name, $label); + } + } + $mform->addGroup($buttonarray, 'buttonsrow', '', ' ', false); + $mform->setType('buttonsrow', PARAM_RAW); + $mform->closeHeaderBefore('buttonsrow'); + } } } diff --git a/classes/local/form/utemplate_importform.php b/classes/local/form/utemplate_importform.php index 6fc4a83425d..22f47a21b6c 100644 --- a/classes/local/form/utemplate_importform.php +++ b/classes/local/form/utemplate_importform.php @@ -109,8 +109,9 @@ public function validation($data, $files) { $xmlfileid = $file->get_id(); $xml = $importman->get_utemplate_content($xmlfileid); - $errormessage = $importman->validate_xml($xml); - if ($errormessage !== false) { + $importman->validate_xml($xml); + $errormessage = $importman->get_xmlvalidationoutcome(); + if (!empty($errormessage->key)) { if (isset($errormessage->a)) { $errors['importfile_filemanager'] = get_string($errormessage->key, 'mod_surveypro', $errormessage->a); } else { diff --git a/classes/local/ipe/layout_customnumber.php b/classes/local/ipe/layout_customnumber.php index a40f11f0399..4b8ea5a9cb6 100644 --- a/classes/local/ipe/layout_customnumber.php +++ b/classes/local/ipe/layout_customnumber.php @@ -55,15 +55,14 @@ public function __construct($itemid, $customnumber) { public static function update($itemid, $newcnumber) { global $DB; - $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], 'id, surveyproid, type, plugin', MUST_EXIST); + $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], 'id, surveyproid', MUST_EXIST); $surveypro = $DB->get_record('surveypro', ['id' => $itemrecord->surveyproid], '*', MUST_EXIST); $cm = get_coursemodule_from_instance('surveypro', $surveypro->id, $surveypro->course, false, MUST_EXIST); $context = \context_module::instance($cm->id); external_api::validate_context($context); - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; $newcnumber = clean_param($newcnumber, PARAM_TEXT); - $DB->set_field($tablename, 'customnumber', $newcnumber, ['itemid' => $itemid]); + $DB->set_field('surveypro_item', 'customnumber', $newcnumber, ['id' => $itemid]); return new static($itemid, $newcnumber); } diff --git a/classes/local/ipe/layout_required.php b/classes/local/ipe/layout_required.php index c9348eab4d9..117c18af1eb 100644 --- a/classes/local/ipe/layout_required.php +++ b/classes/local/ipe/layout_required.php @@ -90,16 +90,15 @@ public function export_for_template(\renderer_base $output) { public static function update($itemid, $newrequired) { global $DB; - $fields = 'id, surveyproid, type, plugin, sortindex'; + $fields = 'id, surveyproid, sortindex'; $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], $fields, MUST_EXIST); $surveypro = $DB->get_record('surveypro', ['id' => $itemrecord->surveyproid], 'id, course', MUST_EXIST); $cm = get_coursemodule_from_instance('surveypro', $surveypro->id, $surveypro->course, false, MUST_EXIST); $context = \context_module::instance($cm->id); external_api::validate_context($context); - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; $newrequired = clean_param($newrequired, PARAM_INT); - $DB->set_field($tablename, 'required', $newrequired, ['itemid' => $itemid]); + $DB->set_field('surveypro_item', 'required', $newrequired, ['id' => $itemid]); if (!empty($newrequired)) { // This item that WAS NOT mandatory IS NOW mandatory. diff --git a/classes/local/ipe/layout_variable.php b/classes/local/ipe/layout_variable.php index ccd22610bea..68d3d9caf5d 100644 --- a/classes/local/ipe/layout_variable.php +++ b/classes/local/ipe/layout_variable.php @@ -61,20 +61,18 @@ public static function update($itemid, $newvarname) { $context = \context_module::instance($cm->id); external_api::validate_context($context); - // Why was I required to move surveypro_get_item from locallib.php to lib.php? - $item = surveypro_get_item($cm, $surveypro, $itemid, $itemrecord->type, $itemrecord->plugin); + // Why was I required to move surveypro_get_itemclass from locallib.php to lib.php? + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $itemrecord->type, $itemrecord->plugin); // Before saving to the the plugin table, validate the variable name. $record = new \stdClass(); + $record->itemid = $itemid; $record->surveyproid = $surveypro->id; $record->variable = $newvarname; $record->plugin = $itemrecord->plugin; - $item->item_validate_variablename($record, $itemid); - - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; - $newvarname = $record->variable; - $DB->set_field($tablename, 'variable', $newvarname, ['itemid' => $itemid]); + $item->item_validate_variablename($record); + $DB->set_field('surveypro_item', 'variable', $record->variable, ['id' => $itemid]); return new static($itemid, $newvarname); } diff --git a/classes/mtemplate_apply.php b/classes/mtemplate_apply.php index 1036174b0b6..a73a54c6ea3 100644 --- a/classes/mtemplate_apply.php +++ b/classes/mtemplate_apply.php @@ -41,6 +41,23 @@ class mtemplate_apply extends mtemplate_base { */ protected $langtree = []; + /** + * @var array + */ + protected $mastertemplate; + + // MARK set. + + /** + * Set mastertemplate. + * + * @param string $mastertemplate + * @return void + */ + public function set_mastertemplate($mastertemplate) { + $this->mastertemplate = $mastertemplate; + } + // MARK get. /** @@ -64,6 +81,20 @@ public function get_mtemplates() { // MARK other. + /** + * Execute last minute check before applying master templates. + * + * @return void + */ + public function lastminute_template_check() { + global $CFG; + + $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$this->mastertemplate.'/template.xml'; + $xml = file_get_contents($templatepath); + + $this->validate_xml($xml); + } + /** * Actually add items coming from template to the db. * @@ -92,10 +123,9 @@ public function add_items_from_template() { $naturalsortindex = 0; foreach ($simplexml->children() as $xmlitem) { - // Read the attributes of the item node. foreach ($xmlitem->attributes() as $attribute => $value) { - // The $xmlitem looks like: . + // The $xmlitem looks like: . if ($attribute == 'type') { $currenttype = (string)$value; } @@ -104,61 +134,75 @@ public function add_items_from_template() { } } - // Take care to details. // Load the item class in order to call its methods to validate $record before saving it. - $item = surveypro_get_item($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); foreach ($xmlitem->children() as $xmltable) { // Surveypro_item and surveypro_<>. $tablename = $xmltable->getName(); - if ($tablename == 'surveypro_item') { - $currenttablestructure = $this->get_table_structure(); - } else { - $currenttablestructure = $this->get_table_structure($currenttype, $currentplugin); - } $record = new \stdClass(); - - // Add to $record mandatory fields that will be overwritten, hopefully, with the content of the usertemplate. - $record->surveyproid = (int)$this->surveypro->id; - $record->type = $currenttype; - $record->plugin = $currentplugin; if ($tablename == 'surveypro_item') { - $item->item_add_mandatory_base_fields($record); + $itemid = 0; // This is the proof the surveypro_item record has not yet been saved. + + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure(); + + $record->surveyproid = (int)$this->surveypro->id; + $record->type = $currenttype; + $record->plugin = $currentplugin; + $item->item_add_fields_default_to_parent_table($record); } else { - $item->item_add_mandatory_plugin_fields($record); + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure($currenttype, $currentplugin); + + $record->itemid = $itemid; // It has been defined when surveypro_item record was saved. + $item->item_add_fields_default_to_child_table($record); } foreach ($xmltable->children() as $xmlfield) { - $fieldname = $xmlfield->getName(); + $xmltag = $xmlfield->getName(); // Generally $xmltag is the name of the field. // Tag always belong to surveypro_item table. - if ($fieldname == 'parent') { - foreach ($xmlfield->children() as $xmlparentattribute) { - $fieldname = $xmlparentattribute->getName(); - $fieldexists = in_array($fieldname, $currenttablestructure); + if ($xmltag == 'parent') { + // Debug: $label = 'Count of attributes of the field '.$xmltag;. + // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. + foreach ($xmlfield->children() as $xmlchildattribute) { + $xmltag = $xmlchildattribute->getName(); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlparentattribute; + $record->{$xmltag} = (string)$xmlchildattribute; } } continue; } - // Tag always belong to surveypro(field|format)_<> table. - // So: ($fieldname == 'embedded') only when surveypro_item has already been saved. - // So: $itemid is known. - if ($fieldname == 'embedded') { - // Debug: $label = 'Count of attributes of the field '.$fieldname; + // Tag always belong to surveypro_item table. + if ($xmltag == 'embedded') { + // Urgently create a record because its id is needed here. + // Please do not create a new record twice. + // If 2 embedded pictures are part of the content, be sure to create only one record. + // If you already created the record for the first embedded picture, do not create one more record now. + if (empty($itemid)) { + $itemid = $DB->insert_record('surveypro_item', $record); + } + + // Debug: $label = 'Count of attributes of the field '.$xmltag; // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. foreach ($xmlfield->children() as $xmlfileattribute) { $fileattributename = $xmlfileattribute->getName(); if ($fileattributename == 'filename') { - $filename = $xmlfileattribute; + $attributecontent = (string)$xmlfileattribute; + $filename = get_string($attributecontent, 'surveyprotemplate_'.$this->templatename); } if ($fileattributename == 'filecontent') { - $filecontent = base64_decode($xmlfileattribute); + $attributecontent = (string)$xmlfileattribute; + $encodedcontent = get_string($attributecontent, 'surveyprotemplate_'.$this->templatename); + $filecontent = base64_decode($encodedcontent); } } + // Debug: echo 'I need to add: "'.$filename.'" to the filearea
';. + // Add the file described by $filename and $filecontent to filearea. // Alias, add pictures found in the utemplate to filearea. $filerecord = new \stdClass(); @@ -172,14 +216,19 @@ public function add_items_from_template() { continue; } - $fieldexists = in_array($fieldname, $currenttablestructure); + // The method xml_validation checks only the formal schema validity. + // It does not know whether the xml is old and holds no longer needed fields + // or does not hold fields that are now mandatory. + // Because of this, I can not SIMPLY add $xmltag to $record but I need to make some more investigation. + // I neglect unneeded used fields, here. + // I will add mandatory (but missing because the usertemplate may be old) fields, + // before saving in the frame of the $item->item_force_coherence. + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlfield; + $record->{$xmltag} = (string)$xmlfield; } } - unset($record->id); - // Apply master template settings. [$tablename, $record] = $mastertemplate->apply_template_settings($tablename, $record, $config); @@ -192,16 +241,23 @@ public function add_items_from_template() { $record->parentid = $DB->get_field('surveypro_item', 'id', $whereparams, MUST_EXIST); } - $itemid = $DB->insert_record($tablename, $record); + $item->item_validate_variablename($record); + if (empty($itemid)) { // If the record in surveypro_item has NOT already been added. + $itemid = $DB->insert_record('surveypro_item', $record); + } else { + // I had to urgently create a record to get its id in order to give it to $fs->create_file_from_string. + // Now I can not create a different record because I passed the id of the existing one. + // So I update the found record. + $record->id = $itemid; + $DB->update_record('surveypro_item', $record); + } } else { // Take care to details. $item->item_force_coherence($record); - $item->item_validate_variablename($record, $itemid); - $record->itemid = $itemid; $DB->insert_record($tablename, $record, false); } - } + } // Closes foreach ($xmlitem->children() as $xmltable) alias: Surveypro_item and surveypro_<>. } } @@ -220,8 +276,8 @@ public function apply_template() { // End of: delete all existing items. $this->templatename = $this->formdata->mastertemplate; - $record = new \stdClass(); + $record = new \stdClass(); $record->id = $this->surveypro->id; $record->template = $this->templatename; $DB->update_record('surveypro', $record); @@ -288,6 +344,4 @@ public function welcome_apply_message() { $message = get_string('welcome_mtemplateapply', 'mod_surveypro'); echo $OUTPUT->notification($message, 'notifymessage'); } - - } diff --git a/classes/mtemplate_save.php b/classes/mtemplate_save.php index 843e9db1913..80009a32337 100644 --- a/classes/mtemplate_save.php +++ b/classes/mtemplate_save.php @@ -43,6 +43,30 @@ class mtemplate_save extends mtemplate_base { // MARK get. + /** + * Get translated strings. + * + * @param string $userlang + * @return void + */ + public function get_translated_strings($userlang) { + $stringsastext = []; + $a = new \stdClass(); + $a->userlang = $userlang; + foreach ($this->langtree as $langbranch) { + foreach ($langbranch as $k => $originalstring) { + if (empty($originalstring)) { + $stringsastext[] = '$string[\''.$k.'\'] = \'\';'; + } else { + $a->stringkey = $k; + $stringsastext[] = get_string('translatedstring', 'mod_surveypro', $a); + } + } + } + + return "\n".implode("\n", $stringsastext)."\n"; + } + /** * Generate the array of strings for the lang file of the mastertemplate plugin. * @@ -58,7 +82,7 @@ public function get_lang_file_content() { } } - return "\n".implode("\n", $stringsastext); + return "\n".implode("\n", $stringsastext)."\n"; } /** @@ -107,17 +131,33 @@ public function get_plugin_name() { * @return void */ public function build_langtree($multilangfields, $item) { - foreach ($multilangfields as $plugin => $fieldnames) { - foreach ($fieldnames as $fieldname) { - $component = $plugin.'_'.$fieldname; - if (isset($this->langtree[$component])) { - $index = count($this->langtree[$component]); + global $DB; + + $itemid = $item->get_itemid(); + $plugin = $item->get_plugin(); + foreach ($multilangfields as $table => $multilanfields) { + foreach ($multilanfields as $multilanfield) { + // Filename and filecontent are multilang fields BUT I they may not be set. + if ( ($multilanfield == 'filename') || ($multilanfield == 'filecontent') ) { + continue; + } + + // Key. + $key = $plugin.'_'.$multilanfield; + if (isset($this->langtree[$key])) { + $index = count($this->langtree[$key]); } else { $index = 0; } $stringindex = sprintf('%02d', 1 + $index); - $content = str_replace("\r", '', $item->get_generic_property($fieldname)); - $this->langtree[$component][$component.'_'.$stringindex] = $content; + + // Value. + if ($multilanfield == 'content') { + $value = $DB->get_field('surveypro_item', 'content', ['id' => $itemid], MUST_EXIST); + } else { + $value = str_replace("\r", '', $item->get_generic_property($multilanfield)); + } + $this->langtree[$key][$key.'_'.$stringindex] = $value; } } } @@ -371,6 +411,31 @@ public function replace_package($filecontent, $pluginname) { return $filecontent; } + /** + * Add to langtree as many elements as the number of files found among content fields. + * + * If in the frame of the content of an item I find 5 embedded images, I add 5 extra elements to langtree. + * I can not use the standard procedure written in build_langtree because I don't know what I will find. + * + * @param string $plugin + * @param string $field + * @param string $content + * @return string $stringindex + */ + public function add_entry_in_langtree($plugin, $field, $content) { + $key = $plugin.'_'.$field; + if (isset($this->langtree[$key])) { + $index = count($this->langtree[$key]); + } else { + $index = 0; + } + $stringindex = sprintf('%02d', 1 + $index); + $val = $key.'_'.$stringindex; + $this->langtree[$key][$val] = $content; + + return $val; + } + /** * Write master template content. * @@ -393,7 +458,7 @@ public function write_template_content($visiblesonly=true) { $xmltemplate = new \SimpleXMLElement(''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $xmlitem = $xmltemplate->addChild('item'); $xmlitem->addAttribute('type', $itemseed->type); @@ -402,14 +467,65 @@ public function write_template_content($visiblesonly=true) { $xmlitem->addAttribute('version', $pluginversion[$index]); // Surveypro_item. + $structure = $this->get_table_structure(); + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; + $unrelevantfields = array_merge($unrelevantfields, $item->item_expected_null_fields()); $xmltable = $xmlitem->addChild('surveypro_item'); if ($multilangfields = $item->get_multilang_fields()) { // Pagebreak and fieldsetend have no multilang_fields. $this->build_langtree($multilangfields, $item); } - - $structure = $this->get_table_structure(); foreach ($structure as $field) { + if (in_array($field, $unrelevantfields)) { + continue; + } + + if ($field == 'content') { + // If $field == 'content' I can not use the property of the object $item because + // in case of pictures, for instance, $item->content looks like: + // 'MMM' + // and not like: + // '...get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + // $val = $DB->get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + // if (core_text::strlen($val)) { + // $xmlfield = $xmltable->addChild('content', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // } + + $val = $this->xml_get_field_content($item, $field, $multilangfields); + if (\core_text::strlen($val)) { + $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + } // Otherwise: It is empty, do not evaluate: jump. + + if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemseed->id)) { + foreach ($files as $file) { + $filename = $file->get_filename(); + if ($filename == '.') { + continue; + } + $xmlembedded = $xmltable->addChild('embedded'); + + // Add an entry in langtree for filename. + $val = $this->add_entry_in_langtree($itemseed->plugin, 'filename', $filename); + // End of: add corresponding string in langtree. + + // $val = $this->xml_get_field_content($item, 'filename', $multilangfields); + $xmlembedded->addChild('filename', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // $xmlembedded->addChild('filename', $filename); + + // Add corresponding string in langtree. + $content = base64_encode($file->get_content()); + $val = $this->add_entry_in_langtree($itemseed->plugin, 'filecontent', $content); + // End of: add corresponding string in langtree. + + // $val = $this->xml_get_field_content($item, 'filecontent', $multilangfields); + $xmlembedded->addChild('filecontent', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // $xmlembedded->addChild('filecontent', $content); + } + } + continue; + } + if ($field == 'parentid') { $parentid = $item->get_parentid(); if ($parentid) { @@ -424,61 +540,44 @@ public function write_template_content($visiblesonly=true) { } // Otherwise: It is empty, do not evaluate: jump. continue; } + if ($field == 'parentvalue') { continue; } - $val = $this->xml_get_field_content($item, 'item', $field, $multilangfields); - + $val = $this->xml_get_field_content($item, $field, $multilangfields); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (\core_text::strlen($val)) { $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. } // Child table. + $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; $structure = $this->get_table_structure($itemseed->type, $itemseed->plugin); + // Take care: some items plugin may be free of their own specific table. if (!count($structure)) { continue; } - $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; + $unrelevantfields = ['id', 'itemid']; $xmltable = $xmlitem->addChild($tablename); foreach ($structure as $field) { - // If $field == 'content' I can not use the property of the object $item because - // in case of pictures, for instance, $item->content has to look like: - // 'MMM' - // and not like: - // 'img1xml_get_field_content($item, $itemseed->plugin, $field, $multilangfields); - } else { - $val = $DB->get_field($tablename, 'content', ['itemid' => $itemseed->id], MUST_EXIST); - } - if (\core_text::strlen($val)) { - $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); - // Otherwise: It is empty, do not evaluate: jump. + if (in_array($field, $unrelevantfields)) { + continue; } - if ($field == 'content') { - $itemid = $item->get_itemid(); - if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid)) { - foreach ($files as $file) { - $filename = $file->get_filename(); - if ($filename == '.') { - continue; - } - $xmlembedded = $xmltable->addChild('embedded'); - $xmlembedded->addChild('filename', $filename); - $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); - } - } - } + $val = $this->xml_get_field_content($item, $field, $multilangfields); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); + if (\core_text::strlen($val)) { + $xmlfield = $xmltable->addChild($field, $val); + } // Otherwise: It is empty, do not evaluate: jump. } } - // The case: $option == false if 100% waste of time + // In the coming code, "$option == false;" if 100% waste of time and should be changed to "$option == true;" // BUT BUT BUT... // the output in the file is well written. // I prefer a more readable xml file instead of few nanoseconds saved. @@ -497,29 +596,45 @@ public function write_template_content($visiblesonly=true) { /** * Get the content of a field for the XML file. + * This tree is needed to build the lang files of the master template. + * The idea is: + * if the field am I dialing with is a multilang field { + * return the key of the lang file + * } + * if the field am I dialing with is NOT a multilang field { + * return the content of the field + * } * - * @param object $item - * @param string $plugin + * Once this function returns its output the XML describing the surveypro of this master template will be: + * boolean_content_01 + * or + * 0 + * + * @param object $itemclass The class needed to call $itemclass->get_generic_property($field); * @param string $field * @param array $multilangfields - * @return void + * @return string the key for the lang file of the direct content of the file */ - public function xml_get_field_content($item, $plugin, $field, $multilangfields) { - // 1a: Has the plugin $plugin multilang fields?. - if (isset($multilangfields[$plugin])) { - // 1b: If the field that is going to be assigned belongs to your multilang fields. - if (in_array($field, $multilangfields[$plugin])) { - $component = $plugin.'_'.$field; - - if (isset($this->langtree[$component])) { - end($this->langtree[$component]); - $val = key($this->langtree[$component]); - return $val; + public function xml_get_field_content($itemclass, $field, $multilangfields) { + // 1a: Has the current plugin multilang fields?. + if (!empty($multilangfields)) { // Pagebrak and fieldsetend don't have $multilangfields. + $plugin = $itemclass->get_plugin(); + foreach ($multilangfields as $table => $multilangfield) { + // 1b: Is the field that is going to be assigned belongs to the multilang fields of this plugin? + if (in_array($field, $multilangfield)) { + $key = $plugin.'_'.$field; // For instance: boolean_content + + if (isset($this->langtree[$key])) { // Langtree has already been defined. + $index = count($this->langtree[$key]); + $stringindex = sprintf('%02d', $index); + $val = $key.'_'.$stringindex; + return $val; + } } } } - $content = $item->get_generic_property($field); + $content = $itemclass->get_generic_property($field); if (\core_text::strlen($content)) { $val = $content; } else { diff --git a/classes/output/action_bar.php b/classes/output/action_bar.php index cee01898cc2..29da25d2dde 100644 --- a/classes/output/action_bar.php +++ b/classes/output/action_bar.php @@ -103,9 +103,9 @@ public function draw_view_action_bar(): string { $menu[$linktosubmissions->out(false)] = get_string('surveypro_responses', 'mod_surveypro'); } - // View -> searchsubmissions. + // View -> responsesearch. if ($cansearch && $utilitylayoutman->has_search_items()) { - $paramurl['section'] = 'searchsubmissions'; + $paramurl['section'] = 'responsesearch'; $linktosearch = new moodle_url('/mod/surveypro/view.php', $paramurl); $menu[$linktosearch->out(false)] = get_string('surveypro_view_search', 'mod_surveypro'); } @@ -132,8 +132,8 @@ public function draw_view_action_bar(): string { } } - // If section = 'submissionform', set $activeurl according to the way the form is going to be used. - if (strpos($this->currenturl->out(false), 'submissionform')) { + // If section = 'responsesubmit', set $activeurl according to the way the form is going to be used. + if (strpos($this->currenturl->out(false), 'responsesubmit')) { if (isset($gosthlink)) { $activeurl = $gosthlink; } else { diff --git a/classes/plugininfo/surveyprofield.php b/classes/plugininfo/surveyprofield.php index 3392b0fec6d..32b0caf928d 100644 --- a/classes/plugininfo/surveyprofield.php +++ b/classes/plugininfo/surveyprofield.php @@ -26,6 +26,10 @@ use core_text, core\plugininfo\base, core_plugin_manager, moodle_url; +defined('MOODLE_INTERNAL') || die(); + +require_once(dirname(__FILE__).'/../../lib.php'); + /** * The mod_surveypro field plugin class. * @@ -49,7 +53,7 @@ public static function get_enabled_plugins() { } $installed = []; foreach ($plugins as $plugin => $version) { - $installed[] = 'surveyprofield_'.$plugin; + $installed[] = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; } [$installed, $params] = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); diff --git a/classes/plugininfo/surveyproformat.php b/classes/plugininfo/surveyproformat.php index f3de8ddee5f..7b0c7630176 100644 --- a/classes/plugininfo/surveyproformat.php +++ b/classes/plugininfo/surveyproformat.php @@ -26,6 +26,10 @@ use core_text, core\plugininfo\base, core_plugin_manager, moodle_url; +defined('MOODLE_INTERNAL') || die(); + +require_once(dirname(__FILE__).'/../../lib.php'); + /** * The mod_surveypro format plugin class. * @@ -49,7 +53,7 @@ public static function get_enabled_plugins() { } $installed = []; foreach ($plugins as $plugin => $version) { - $installed[] = 'surveyproformat_'.$plugin; + $installed[] = 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$plugin; } [$installed, $params] = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 7dd683e44f3..231bbbfc888 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -237,7 +237,7 @@ protected static function store_current_data(&$surveyprodata, $surveyproanswer, protected static function export_get_itemcontent($surveyproanswer) { global $DB; - $tablename = 'surveyprofield_'.$surveyproanswer->plugin; + $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$surveyproanswer->plugin; $itemid = $surveyproanswer->itemid; $params = ['itemid' => $itemid]; $plugin = $DB->get_record($tablename, $params); diff --git a/classes/templatebase.php b/classes/templatebase.php index 3f308eaf1ea..1a526b328ea 100644 --- a/classes/templatebase.php +++ b/classes/templatebase.php @@ -63,6 +63,11 @@ class templatebase { */ protected $langtree = []; + /** + * @var string Outcome of the last minute check before applying templates. + */ + protected $xmlvalidationoutcome; + /** * Class constructor. * @@ -76,17 +81,135 @@ public function __construct($cm, $context, $surveypro) { $this->surveypro = $surveypro; } + // MARK set. + + /** + * Set xmlvalidationoutcome. + * + * @param stdClass $xmlvalidationoutcome + * @return void + */ + public function set_xmlvalidationoutcome($xmlvalidationoutcome=null) { + if (is_null($xmlvalidationoutcome)) { + $xmlvalidationoutcome = new \stdClass(); + } + $this->xmlvalidationoutcome = $xmlvalidationoutcome; + } + + // MARK get. + + /** + * Returns the ordered list of fields for the itembase (or the plugin) table. + * + * @param string $type (optional) + * @param string $plugin (optional) + * @return void + */ + public function get_table_structure($type=null, $plugin=null) { + global $CFG; + + if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { + $message = '$type and $plugin must be provided both or none.'; + debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); + } + + $fieldlist = []; + if (empty($type) && empty($plugin)) { + $installxml = $CFG->dirroot.'/mod/surveypro/db/install.xml'; + $targettable = 'surveypro_item'; + } else { + $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; + $targettable = 'surveypro'.$type.'_'.$plugin; + + // Some plugins are missing the install.xml because they don't have attributes. + if (!file_exists($installxml)) { + return $fieldlist; + } + } + + $xmlall = simplexml_load_file($installxml); + foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. + foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. + $attributes = $xmltable->attributes(); + $tablename = $attributes['NAME']; + if ($tablename != $targettable) { + continue; + } + foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. + foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. + $attributes = $xmlfield->attributes(); + $fieldname = $attributes['NAME']; + $fieldlist[] = (string)$attributes['NAME']; + } + break; + } + break; + } + break; + } + + return $fieldlist; + } + + /** + * Get plugin versions. + * + * @return versions of each field and format plugin + */ + public static function get_subplugin_versions() { + $versions = []; + $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; + + foreach ($types as $type) { + $plugins = surveypro_get_plugin_list($type, true); + foreach ($plugins as $plugin => $unused) { + $versions[$plugin] = get_config('surveypro'.$plugin, 'version'); + } + } + + return $versions; + } + + /** + * Get xml validation outcome + * + * @return xmlvalidationoutcome + */ + public function get_xmlvalidationoutcome() { + return $this->xmlvalidationoutcome; + } + + /** + * Get user template content. + * + * @param int $utemplateid + * @return void + */ + public function get_utemplate_content($utemplateid=0) { + $fs = get_file_storage(); + if (empty($utemplateid)) { + $utemplateid = $this->utemplateid; + } + $xmlfile = $fs->get_file_by_id($utemplateid); + + return $xmlfile->get_content(); + } + + // MARK other. + /** * Validate the uploaded xml file. * * @param object $xml File to validate - * @return object|boolean error describing the message to show, false if no error is found + * @return object|false error describing the message to show, false if no error is found */ public function validate_xml($xml) { global $CFG; $debug = false; // Set $debug = true if you want to stop anyway to debug the xml template. + $this->set_xmlvalidationoutcome(); + $pluginversion = self::get_subplugin_versions(); if ($debug) { $simplexml = new \SimpleXMLElement($xml); @@ -95,7 +218,7 @@ public function validate_xml($xml) { } foreach ($simplexml->children() as $xmlitem) { foreach ($xmlitem->attributes() as $attribute => $value) { - // Example: . + // Example: . // Debug: echo 'Found: '.$attribute.' = '.$value.'
';. if ($attribute == 'type') { $currenttype = (string)$value; @@ -111,19 +234,22 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'missingitemtype'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } if (!isset($currentplugin)) { $error = new \stdClass(); $error->key = 'missingitemplugin'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } if (!isset($currentversion)) { $error = new \stdClass(); $error->key = 'missingitemversion'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } // Ok, $currenttype and $currentplugin are onboard. @@ -132,11 +258,12 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'invalidtypeorplugin'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } $index = $currenttype.'_'.$currentplugin; - if ($pluginversion[$index] < $currentversion) { + if ($pluginversion[$index] > $currentversion) { $a = new \stdClass(); $a->type = $currenttype; $a->plugin = $currentplugin; @@ -147,7 +274,8 @@ public function validate_xml($xml) { $error->a = $a; $error->key = 'versionmismatch'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } foreach ($xmlitem->children() as $xmltable) { @@ -167,7 +295,8 @@ public function validate_xml($xml) { $error->key = 'badtablenamefound'; $error->a = $tablename; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } $xsd = $classname::get_plugin_schema(); // Plugin schema. } @@ -176,7 +305,8 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'xsdnotfound'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } $mdom = new \DOMDocument(); @@ -217,7 +347,8 @@ public function validate_xml($xml) { $error->a = $a; $error->key = 'reportederror'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } if (!$status) { @@ -230,89 +361,100 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'schemavalidationfailed'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } } } - - return false; } - // MARK get. + /** + * Tell the user that the usertemplate is obsolete. + * + * @return void + */ + public function lastminute_stop() { + global $OUTPUT; + + $errormessage = $this->get_xmlvalidationoutcome(); + if (isset($errormessage->key)) { + if (isset($errormessage->a)) { + $message = get_string($errormessage->key, 'mod_surveypro', $errormessage->a); + } else { + $message = get_string($errormessage->key, 'mod_surveypro'); + } + $message .= get_string('utemplate_nolongervalid', 'mod_surveypro'); + + echo $OUTPUT->notification($message, 'notifyproblem'); + $paramurl = ['s' => $this->surveypro->id, 'area' => 'layout', 'section' => 'itemslist']; + $url = new \moodle_url('/mod/surveypro/layout.php', $paramurl); + echo $OUTPUT->continue_button($url); + + echo $OUTPUT->footer(); + die(); + } + } /** - * Get the ordered list of fields for the itembase (or the plugin) table. + * Tell the user that the usertemplate is obsolete. * - * @param string $type (optional) - * @param string $plugin (optional) + * @param string $mtemplate + * @param int $itemid * @return void */ - public function get_table_structure($type=null, $plugin=null) { + public function load_new_files_from_lang($mtemplate, $itemid) { global $CFG; - if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { - $message = '$type and $plugin must be provided both or none.'; - debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); - } + // I need to push to SURVEYPRO_ITEMCONTENTFILEAREA new files described in current lang file that may be new. - $fieldlist = []; - if (empty($type) && empty($plugin)) { - $installxml = $CFG->dirroot.'/mod/surveypro/db/install.xml'; - $targettable = 'surveypro_item'; - $uselessfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; - } else { - $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; - $targettable = 'surveypro'.$type.'_'.$plugin; - $uselessfields = ['id', 'itemid']; + $context = \context_module::instance($this->cm->id); - // Some plugins are missing the install.xml because they havn't attributes. - if (!file_exists($installxml)) { - return $fieldlist; - } + $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$mtemplate.'/template.xml'; + if (!file_exists($templatepath)) { + return; } - $xmlall = simplexml_load_file($installxml); - foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. - foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. - $attributes = $xmltable->attributes(); - $tablename = $attributes['NAME']; - if ($tablename != $targettable) { + $fs = get_file_storage(); + + $templatecontent = file_get_contents($templatepath); + $simplexml = new \SimpleXMLElement($templatecontent); + foreach ($simplexml->children() as $xmlitem) { + foreach ($xmlitem->children() as $xmltable) { // Surveypro_item and surveypro_<>. + $tablename = $xmltable->getName(); + if ($tablename != 'surveypro_item') { continue; } - foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. - foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. - $attributes = $xmlfield->attributes(); - $fieldname = $attributes['NAME']; - if (in_array($fieldname, $uselessfields) === false) { - $fieldlist[] = (string)$attributes['NAME']; + foreach ($xmltable->children() as $xmlfield) { + $fieldname = $xmlfield->getName(); + if ($fieldname != 'embedded') { + continue; + } + foreach ($xmlfield->children() as $xmlfileattribute) { + $fileattributename = $xmlfileattribute->getName(); + if ($fileattributename == 'filename') { + $attributecontent = (string)$xmlfileattribute; + $filename = get_string($attributecontent, 'surveyprotemplate_'.$mtemplate); + } + if ($fileattributename == 'filecontent') { + $attributecontent = (string)$xmlfileattribute; + $encodedcontent = get_string($attributecontent, 'surveyprotemplate_'.$mtemplate); + $filecontent = base64_decode($encodedcontent); } } - break; + if (!$fs->file_exists($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid, '/', $filename)) { + // Add the new found file to filearea. + $filerecord = new \stdClass(); + $filerecord->contextid = $context->id; + $filerecord->component = 'mod_surveypro'; + $filerecord->filearea = SURVEYPRO_ITEMCONTENTFILEAREA; + $filerecord->itemid = $itemid; + $filerecord->filepath = '/'; + $filerecord->filename = $filename; + + $fileinfo = $fs->create_file_from_string($filerecord, $filecontent); + } } - break; - } - break; - } - - return $fieldlist; - } - - /** - * Get plugin versions. - * - * @return versions of each field and format plugin - */ - public static function get_subplugin_versions() { - $versions = []; - $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; - - foreach ($types as $type) { - $plugins = surveypro_get_plugin_list($type, true); - foreach ($plugins as $plugin => $unused) { - $versions[$plugin] = get_config('surveypro'.$plugin, 'version'); } } - - return $versions; } } diff --git a/classes/tools_export.php b/classes/tools_export.php index 461e7927f5a..4bfd6a28bc4 100644 --- a/classes/tools_export.php +++ b/classes/tools_export.php @@ -266,9 +266,8 @@ public function export_get_output_headers() { $itemseedskeys = []; foreach ($itemseeds as $itemseed) { - $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemseed->plugin; - $where = ['itemid' => $itemseed->id]; - $currentheader = $DB->get_field($tablename, 'variable', $where); + $where = ['id' => $itemseed->id]; + $currentheader = $DB->get_field('surveypro_item', 'variable', $where); $headerlabels[] = $currentheader; $itemseedskeys[] = $itemseed->id; if ($this->formdata->outputstyle == SURVEYPRO_RAW) { @@ -567,7 +566,7 @@ public function decode_content($richsubmission) { } else { $itemid = $richsubmission->itemid; $plugin = $richsubmission->plugin; - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $plugin); $return = $item->userform_db_to_export($richsubmission); } diff --git a/classes/tools_import.php b/classes/tools_import.php index fd36f9473ef..d2b8456a8d9 100644 --- a/classes/tools_import.php +++ b/classes/tools_import.php @@ -512,10 +512,10 @@ public function get_survey_infos() { $whereparams = ['surveyproid' => $this->surveypro->id]; foreach ($pluginlist as $plugin) { $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - $canbemandatory = $classname::item_uses_mandatory_dbfield(); + $usesmandatoryattribute = $classname::has_mandatoryattribute(); $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; - $fieldname = ($canbemandatory) ? ', p.required' : ''; + $fieldname = ($usesmandatoryattribute) ? ', p.required' : ''; $sql = 'SELECT p.itemid, p.variable'.$fieldname.' FROM {surveypro_item} i JOIN {'.$tablename.'} p ON p.itemid = i.id @@ -528,7 +528,7 @@ public function get_survey_infos() { if ($classname::response_uses_format()) { $surveyheaders[$itemvar->itemid.SURVEYPRO_IMPFORMATSUFFIX] = $itemvar->variable.SURVEYPRO_IMPFORMATSUFFIX; } - if ($canbemandatory) { + if ($usesmandatoryattribute) { if ($itemvar->required > 0) { $requireditems[] = $itemvar->itemid; } @@ -645,7 +645,7 @@ public function buil_item_helpers() { continue; } } - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid); // Itemhelperinfo. $itemhelper = new \stdClass(); @@ -663,7 +663,7 @@ public function buil_item_helpers() { if ($itemhelper->usespositionalanswer) { // The count of the options is enough. - $optionscountpercol[$col] = count($item->get_content_array(SURVEYPRO_LABELS, 'options')); + $optionscountpercol[$col] = count($item->get_textarea_content(SURVEYPRO_LABELS, 'options')); } } diff --git a/classes/utemplate_apply.php b/classes/utemplate_apply.php index 7f4f186d819..8e77a31c655 100644 --- a/classes/utemplate_apply.php +++ b/classes/utemplate_apply.php @@ -38,6 +38,11 @@ */ class utemplate_apply extends utemplate_base { + /** + * @var int User confirmation to actions + */ + protected $action; + /** * @var int User confirmation to actions */ @@ -91,22 +96,6 @@ private function set_confirm($confirm) { // MARK get. - /** - * Get user template content. - * - * @param int $utemplateid - * @return void - */ - public function get_utemplate_content($utemplateid=0) { - $fs = get_file_storage(); - if (empty($utemplateid)) { - $utemplateid = $this->utemplateid; - } - $xmlfile = $fs->get_file_by_id($utemplateid); - - return $xmlfile->get_content(); - } - /** * Get the content of the user template drop down menu. * @@ -153,9 +142,8 @@ public function add_items_from_template() { $naturalsortindex = 0; foreach ($simplexml->children() as $xmlitem) { - // Read the attributes of the item node: - // The xmlitem looks like: . + // The xmlitem looks like: . foreach ($xmlitem->attributes() as $attribute => $value) { if ($attribute == 'type') { $currenttype = (string)$value; @@ -165,52 +153,62 @@ public function add_items_from_template() { } } - // Take care to details. // Load the item class in order to call its methods to validate $record before saving it. - $item = surveypro_get_item($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); - foreach ($xmlitem->children() as $xmltable) { // Tables are: surveypro_item and surveypro(field|format)_<>. + foreach ($xmlitem->children() as $xmltable) { // Tables are: surveypro_item and surveypro(field|format)_(plugin). $tablename = $xmltable->getName(); - if ($tablename == 'surveypro_item') { - $currenttablestructure = $this->get_table_structure(); - } else { - $currenttablestructure = $this->get_table_structure($currenttype, $currentplugin); - } + // Begin of: Create a new record and fill it with basic infor and defaults. $record = new \stdClass(); - - // Add to $record mandatory fields that will be overwritten, hopefully, with the content of the usertemplate. - $record->surveyproid = (int)$this->surveypro->id; - $record->type = $currenttype; - $record->plugin = $currentplugin; if ($tablename == 'surveypro_item') { - $item->item_add_mandatory_base_fields($record); + $itemid = 0; // This is the proof the surveypro_item record has not yet been saved. + + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure(); + + $record->surveyproid = (int)$this->surveypro->id; + $record->type = $currenttype; + $record->plugin = $currentplugin; + $item->item_add_fields_default_to_parent_table($record); } else { - $item->item_add_mandatory_plugin_fields($record); + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure($currenttype, $currentplugin); + + $record->itemid = $itemid; // It has been defined when surveypro_item record was saved. + $item->item_add_fields_default_to_child_table($record); } + // End of: Create a new record and fill it with basic infor and defaults. - foreach ($xmltable->children() as $xmlfield) { - $fieldname = $xmlfield->getName(); + // Begin of: Overwrite defaults with utemplate data. + foreach ($xmltable->children() as $xmlfield) { // Run over fields listed in the xml. + $xmltag = $xmlfield->getName(); // Generally $xmltag is the name of the field. // Tag always belong to surveypro_item table. - if ($fieldname == 'parent') { - // Debug: $label = 'Count of attributes of the field '.$fieldname;. + if ($xmltag == 'parent') { + // Debug: $label = 'Count of attributes of the field '.$xmltag;. // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. - foreach ($xmlfield->children() as $xmlparentattribute) { - $fieldname = $xmlparentattribute->getName(); - $fieldexists = in_array($fieldname, $currenttablestructure); + foreach ($xmlfield->children() as $xmlchildattribute) { + $xmltag = $xmlchildattribute->getName(); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlparentattribute; + $record->{$xmltag} = (string)$xmlchildattribute; } } continue; } - // Tag always belong to surveypro(field|format)_<> table - // so: ($fieldname == 'embedded') only when surveypro_item has already been saved... - // so: $itemid is known. - if ($fieldname == 'embedded') { - // Debug: $label = 'Count of attributes of the field '.$fieldname;. + // Tag always belong to surveypro_item table. + if ($xmltag == 'embedded') { + // Urgently create a record because its id is needed here. + // Please do not create a new record twice. + // If 2 embedded pictures are part of the content, take care to create only one record. + // If you already created the record for the first embedded picture, do not create one more record now. + if (empty($itemid)) { + $itemid = $DB->insert_record('surveypro_item', $record); + } + + // Debug: $label = 'Count of attributes of the field '.$xmltag; // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. foreach ($xmlfield->children() as $xmlfileattribute) { $fileattributename = $xmlfileattribute->getName(); @@ -224,8 +222,8 @@ public function add_items_from_template() { // Debug: echo 'I need to add: "'.$filename.'" to the filearea
';. - // Add the file described by $filename and $filecontent to filearea, - // alias, add pictures found in the utemplate to filearea. + // Add the file described by $filename and $filecontent to filearea. + // Alias, add pictures found in the utemplate to filearea. $filerecord = new \stdClass(); $filerecord->contextid = $this->context->id; $filerecord->component = 'mod_surveypro'; @@ -241,38 +239,96 @@ public function add_items_from_template() { // It does not know whether the xml is old and holds no longer needed fields // or does not hold fields that are now mandatory. // Because of this, I can not SIMPLY add $fieldname to $record but I need to make some more investigation. - // I neglect no longer used fields, here. + // I neglect unneeded used fields, here. // I will add mandatory (but missing because the usertemplate may be old) fields, // before saving in the frame of the $item->item_force_coherence. - $fieldexists = in_array($fieldname, $currenttablestructure); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlfield; + $record->{$xmltag} = (string)$xmlfield; } } + // End of: Overwrite defaults with utemplate data. - unset($record->id); - + // Begin of: Overwrite defaults with utemplate data. if ($tablename == 'surveypro_item') { $naturalsortindex++; $record->sortindex = $naturalsortindex + $sortindexoffset; - if (!empty($record->parentid)) { + if (!empty($record->parentid)) { // If I have a parent, its record was already saved. $whereparams = ['surveyproid' => $this->surveypro->id]; $whereparams['sortindex'] = $record->parentid + $sortindexoffset; $record->parentid = $DB->get_field('surveypro_item', 'id', $whereparams, MUST_EXIST); } - $itemid = $DB->insert_record($tablename, $record); + $item->item_validate_variablename($record); + if (empty($itemid)) { // If the record in surveypro_item has NOT already been added. + $itemid = $DB->insert_record('surveypro_item', $record); + } else { + // I had to urgently create a record to get its id in order to give it to $fs->create_file_from_string. + // Now I can not create a different record because I passed the id of the existing one. + // So I update the found record. + $record->id = $itemid; + $DB->update_record('surveypro_item', $record); + } } else { // Take care to details. $item->item_force_coherence($record); - $item->item_validate_variablename($record, $itemid); - $record->itemid = $itemid; $DB->insert_record($tablename, $record, false); } + // End of: Overwrite defaults with utemplate data. } } } + /** + * Ask for confirmation when a utemplate is applied directly. + * + * @return void + */ + public function ask_for_confirmation() { + global $OUTPUT; + + if ($this->confirm == SURVEYPRO_UNCONFIRMED) { + $message = get_string('confirm_applyutemplate', 'mod_surveypro'); + + $optionbase = ['s' => $this->cm->instance, 'act' => $this->action, 'sesskey' => sesskey()]; + + $optionsyes = $optionbase; + $optionsyes['cnf'] = SURVEYPRO_CONFIRMED_YES; + $optionsyes['section'] = 'apply'; + $optionsyes['fid'] = $this->utemplateid; + $optionsyes['action'] = SURVEYPRO_APPLYUTEMPLATE; + $urlyes = new \moodle_url('/mod/surveypro/utemplates.php', $optionsyes); + $yeslabel = get_string('yes_applyutemplate', 'mod_surveypro'); + $buttonyes = new \single_button($urlyes, $yeslabel); + + $optionsno = $optionbase; + $optionsno['cnf'] = SURVEYPRO_CONFIRMED_NO; + $optionsyes['section'] = 'manage'; + $urlno = new \moodle_url('/mod/surveypro/utemplates.php', $optionsno); + $buttonno = new \single_button($urlno, get_string('no')); + + echo $OUTPUT->confirm($message, $buttonyes, $buttonno); + echo $OUTPUT->footer(); + die(); + } + } + + /** + * Execute last minute check before applying user templates. + * + * @return void + */ + public function lastminute_template_check() { + if (!empty($this->utemplateid)) { + $utemplateid = $this->utemplateid; + } else { + $parts = explode('_', $this->formdata->usertemplateinfo); + $utemplateid = $parts[1]; + } + + $xml = $this->get_utemplate_content($utemplateid); + $this->validate_xml($xml); + } /** * Apply template. @@ -280,21 +336,25 @@ public function add_items_from_template() { * @return void */ public function apply_template() { - $applyction = $this->formdata->action; - $parts = explode('_', $this->formdata->usertemplateinfo); - $this->utemplateid = $parts[1]; + if (!isset($this->formdata->action)) { + $applyaction = SURVEYPRO_IGNOREITEMS; + } else { + $applyaction = $this->formdata->action; + $parts = explode('_', $this->formdata->usertemplateinfo); + $this->utemplateid = $parts[1]; + } // Before continuing. - if ($applyction != SURVEYPRO_DELETEALLITEMS) { + if ($applyaction != SURVEYPRO_DELETEALLITEMS) { // Dispose assignemnt of pages. $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); $utilitylayoutman->reset_pages(); } - $this->trigger_event('usertemplate_applied', $applyction); + $this->trigger_event('usertemplate_applied', $applyaction); // Begin the process executing preliminary actions. - switch ($applyction) { + switch ($applyaction) { case SURVEYPRO_IGNOREITEMS: break; case SURVEYPRO_HIDEALLITEMS: @@ -325,9 +385,8 @@ public function apply_template() { $utilitylayoutman->items_reindex(); break; - break; default: - $message = 'Unexpected $applyction = '.$applyction; + $message = 'Unexpected $applyaction = '.$applyaction; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } @@ -361,7 +420,7 @@ public function friendly_stop() { if ($this->surveypro->template && (!$riskyediting)) { // This survey comes from a master template so it is multilang. echo $OUTPUT->notification(get_string('applyusertemplatedenied02', 'mod_surveypro'), 'notifyproblem'); - $url = new \moodle_url('/mod/surveypro/view.php', ['s' => $this->surveypro->id, 'section' => 'submissionform']); + $url = new \moodle_url('/mod/surveypro/view.php', ['s' => $this->surveypro->id, 'section' => 'responsesubmit']); echo $OUTPUT->continue_button($url); echo $OUTPUT->footer(); die(); diff --git a/classes/utemplate_import.php b/classes/utemplate_import.php index b1dbd2c0872..3c21eee4dd9 100644 --- a/classes/utemplate_import.php +++ b/classes/utemplate_import.php @@ -77,22 +77,6 @@ public function get_filemanager_options() { return $templateoptions; } - /** - * Get user template content. - * - * @param int $utemplateid - * @return void - */ - public function get_utemplate_content($utemplateid=0) { - $fs = get_file_storage(); - if (empty($utemplateid)) { - $utemplateid = $this->utemplateid; - } - $xmlfile = $fs->get_file_by_id($utemplateid); - - return $xmlfile->get_content(); - } - // MARK other. /** diff --git a/classes/utemplate_manage.php b/classes/utemplate_manage.php index 15c03f86b05..2344509424c 100644 --- a/classes/utemplate_manage.php +++ b/classes/utemplate_manage.php @@ -187,11 +187,13 @@ public function delete_utemplate() { if ($this->confirm == SURVEYPRO_CONFIRMED_YES) { // Put the name in the gobal vaiable, to remember it for the log. + // At log time I haven't availability of the file so I can not ask fot its name. $this->templatename = $this->get_utemplate_name(); $fs = get_file_storage(); $xmlfile = $fs->get_file_by_id($this->utemplateid); $a = $xmlfile->get_filename(); + $xmlfile->delete(); $this->trigger_event('usertemplate_deleted'); @@ -217,6 +219,7 @@ public function display_usertemplates_table() { require_once($CFG->libdir.'/tablelib.php'); + $canapplyutemplates = has_capability('mod/surveypro:applyusertemplates', $this->context); $candownloadutemplates = has_capability('mod/surveypro:downloadusertemplates', $this->context); $candeleteutemplates = has_capability('mod/surveypro:deleteusertemplates', $this->context); @@ -224,13 +227,17 @@ public function display_usertemplates_table() { $paramurlbase = ['s' => $this->cm->instance]; // End of $paramurlbase definition. + $applytitle = get_string('utemplate_apply', 'mod_surveypro'); + $iconparams = ['title' => $applytitle]; + $applyicn = new \pix_icon('stamp', $applytitle, 'surveypro', $iconparams); + $deletetitle = get_string('delete'); $iconparams = ['title' => $deletetitle]; $deleteicn = new \pix_icon('t/delete', $deletetitle, 'moodle', $iconparams); - $importtitle = get_string('exporttemplate', 'mod_surveypro'); - $iconparams = ['title' => $importtitle]; - $importicn = new \pix_icon('t/download', $importtitle, 'moodle', $iconparams); + $exporttitle = get_string('exporttemplate', 'mod_surveypro'); + $iconparams = ['title' => $exporttitle]; + $exporticn = new \pix_icon('t/download', $exporttitle, 'moodle', $iconparams); $table = new \flexible_table('templatelist'); @@ -297,6 +304,18 @@ public function display_usertemplates_table() { $row++; $icons = ''; + + // SURVEYPRO_APPLYUTEMPLATE. + if ($canapplyutemplates) { + $paramurl = $paramurlbase; + $paramurl['act'] = SURVEYPRO_APPLYUTEMPLATE; + $paramurl['section'] = 'apply'; + $paramurl['sesskey'] = sesskey(); + + $link = new \moodle_url('/mod/surveypro/utemplates.php', $paramurl); + $icons .= $OUTPUT->action_icon($link, $applyicn, null, ['title' => $applytitle]); + } + // SURVEYPRO_DELETEUTEMPLATE. if ($candeleteutemplates) { if ($utemplate->userid == $USER->id) { // The user template can be deleted only by its owner. @@ -318,7 +337,7 @@ public function display_usertemplates_table() { $paramurl['sesskey'] = sesskey(); $link = new \moodle_url('/mod/surveypro/utemplates.php', $paramurl); - $icons .= $OUTPUT->action_icon($link, $importicn, null, ['title' => $importtitle]); + $icons .= $OUTPUT->action_icon($link, $exporticn, null, ['title' => $exporttitle]); } $tablerow[] = $icons; @@ -326,7 +345,6 @@ public function display_usertemplates_table() { $table->add_data($tablerow); } $table->set_attribute('align', 'center'); - $table->summary = get_string('templatelist', 'mod_surveypro'); $table->print_html(); } diff --git a/classes/utemplate_save.php b/classes/utemplate_save.php index 882812c7117..b623132e2fe 100644 --- a/classes/utemplate_save.php +++ b/classes/utemplate_save.php @@ -76,15 +76,31 @@ public function welcome_save_message() { } /** - * Write template content. + * Write user template content. + * + * TAKE CARE + * At "usertemplate creation" time, in order to recover the ID of the parent record to be assigned to the child record in a + * possible parent-child relation, I write, in the parentid field of the child record in the XML, the sortindex of the parent + * record and not the ID of the parent record. At "usertemplate apply" time, to get the ID of the parent record, I get the + * sortindex written in the XML and I add to it the sortindexoffset (that is nothing more than the number of preexisting items + * in the accepting surveypro) that I calculate at the beginning of the "usertemplate apply" process. Finally I get the ID of + * the item that has sortindex equal to ("sortindex taken from the usertemplate" + sortindexoffset) with a query "SELECT the ID + * of the item WHERE sortindex = ...". + * + * When the user creates a usertemplate with only visible items, this trick does not work because the parent's sortindex could + * be 100 even if the parent is the first record (and, in my plan, is should have sortindex == 1). + * + * For this reason, at "usertemplate creation" time, I AM FORCED to use a "hot" calculated sortindex instead of using the one + * taken from the db. * * @param boolean $visiblesonly * @return void */ - public function write_template_content($visiblesonly=true) { + public function write_template_content($visiblesonly) { global $DB; $pluginversion = self::get_subplugin_versions(); + $where = ['surveyproid' => $this->surveypro->id]; if ($visiblesonly) { $where['hidden'] = '0'; @@ -96,7 +112,7 @@ public function write_template_content($visiblesonly=true) { $xmltemplate = new \SimpleXMLElement(''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $xmlitem = $xmltemplate->addChild('item'); $xmlitem->addAttribute('type', $itemseed->type); @@ -105,72 +121,102 @@ public function write_template_content($visiblesonly=true) { $xmlitem->addAttribute('version', $pluginversion[$index]); // Surveypro_item. - $xmltable = $xmlitem->addChild('surveypro_item'); $structure = $this->get_table_structure(); + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; + $unrelevantfields = array_merge($unrelevantfields, $item->item_expected_null_fields()); + $xmltable = $xmlitem->addChild('surveypro_item'); foreach ($structure as $field) { + if (in_array($field, $unrelevantfields)) { + continue; + } + + if ($field == 'content') { + // If $field == 'content' I can not use the property of the object $item because + // in case of pictures, for instance, $item->content has to look like: + // 'MMM' + // and not like: + // 'img1get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + if (core_text::strlen($val)) { + $xmlfield = $xmltable->addChild('content', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + } + if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemseed->id)) { + foreach ($files as $file) { + $filename = $file->get_filename(); + if ($filename == '.') { + continue; + } + $xmlembedded = $xmltable->addChild('embedded'); + $xmlembedded->addChild('filename', $filename); + $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); + } + } + + continue; + } + if ($field == 'parentid') { $parentid = $item->get_parentid(); if ($parentid) { // Store the sortindex of the parent instead of its id, because at restore time parentid will change. + // Get $parentsortindex. $whereparams = ['id' => $parentid]; - $sortindex = $DB->get_field('surveypro_item', 'sortindex', $whereparams, MUST_EXIST); - $val = $item->get_parentvalue(); + $parentsortindex = $DB->get_field('surveypro_item', 'sortindex', $whereparams, MUST_EXIST); + + if ($visiblesonly) { + $sql = 'SELECT COUNT(\'x\') + FROM {surveypro_item} + WHERE surveyproid = :surveyproid + AND hidden = :hidden + AND sortindex < :sortindex'; + $whereparams = ['surveyproid' => $this->surveypro->id, 'hidden' => 1, 'sortindex' => $parentsortindex]; + $hidedsortindex = $DB->count_records_sql($sql, $whereparams); + $parentsortindex -= $hidedsortindex; + } + + // Get $parentsortindex. + $parentvalue = $item->get_parentvalue(); $xmlparent = $xmltable->addChild('parent'); - $xmlfield = $xmlparent->addChild('parentid', $sortindex); - $xmlfield = $xmlparent->addChild('parentvalue', $val); + $xmlfield = $xmlparent->addChild('parentid', $parentsortindex); + $xmlfield = $xmlparent->addChild('parentvalue', $parentvalue); } // Otherwise: It is empty, do not evaluate: jump. continue; } + if ($field == 'parentvalue') { continue; } $val = $item->get_generic_property($field); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (core_text::strlen($val)) { $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. } // Child table. + $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; $structure = $this->get_table_structure($itemseed->type, $itemseed->plugin); + // Take care: some items plugin may be free of their own specific table. if (!count($structure)) { continue; } - $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; + $unrelevantfields = ['id', 'itemid']; $xmltable = $xmlitem->addChild($tablename); foreach ($structure as $field) { - // If $field == 'content' I can not use the property of the object $item because - // in case of pictures, for instance, $item->content has to look like: - // 'MMM' - // and not like: - // 'img1get_generic_property($field); - } else { - $val = $DB->get_field($tablename, 'content', ['itemid' => $itemseed->id], MUST_EXIST); + + if (in_array($field, $unrelevantfields)) { + continue; } + $val = $item->get_generic_property($field); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (core_text::strlen($val)) { - $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. - - if ($field == 'content') { - $itemid = $item->get_itemid(); - if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid)) { - foreach ($files as $file) { - $filename = $file->get_filename(); - if ($filename == '.') { - continue; - } - $xmlembedded = $xmltable->addChild('embedded'); - $xmlembedded->addChild('filename', $filename); - $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); - } - } - } } } diff --git a/classes/utility_layout.php b/classes/utility_layout.php index d63500361ee..499b068c5ac 100644 --- a/classes/utility_layout.php +++ b/classes/utility_layout.php @@ -379,7 +379,7 @@ public function delete_answers($whereparams, $item=null) { debugging('Error at line '.__LINE__.' of file '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $validanswerparams = ['id', 'submissionid', 'itemid', 'content']; + $validanswerparams = ['id', 'submissionid', 'itemid', 'content', 'verified']; $startingparams = array_keys($whereparams); foreach ($startingparams as $startingparam) { if (!in_array($startingparam, $validanswerparams)) { @@ -610,7 +610,7 @@ public function get_answers_idlist_from_answers($whereparams) { global $DB; // Verify input params integrity. - $validanswerparams = ['id', 'submissionid', 'itemid', 'content']; + $validanswerparams = ['id', 'submissionid', 'itemid', 'content', 'verified']; $startingparams = array_keys($whereparams); foreach ($startingparams as $startingparam) { if (!in_array($startingparam, $validanswerparams)) { diff --git a/classes/utility_mform.php b/classes/utility_mform.php deleted file mode 100644 index 21a2198a4c4..00000000000 --- a/classes/utility_mform.php +++ /dev/null @@ -1,66 +0,0 @@ -. - -/** - * The utility_mform class - * - * @package mod_surveypro - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_surveypro; - -/** - * The class managing mform classes - * - * @package mod_surveypro - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class utility_mform { - - /** - * Register classes extending mform classes - * - * @return void - */ - public static function register_form_elements() { - global $CFG; - - $basepath = $CFG->dirroot.'/mod/surveypro'; - $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; - - foreach ($types as $type) { - $plugins = surveypro_get_plugin_list($type); - foreach ($plugins as $plugin) { - $filepath = $basepath.'/'.$type.'/'.$plugin.'/mform'; - if (file_exists($filepath) && is_dir($filepath)) { - $classfiles = scandir($filepath); - foreach ($classfiles as $classfile) { - if ($classfile[0] == '.') { // Hidden files, '.' and '..'. - continue; - } - $basename = basename($classfile, '.php'); - $extendingclass = 'mod_surveypro_'.$basename; - $parentpath = $filepath.'/'.$classfile; - \MoodleQuickForm::registerElementType($extendingclass, $parentpath, 'surveypromform_'.$basename); - } - } - } - } - } -} diff --git a/classes/view_cover.php b/classes/view_cover.php index 9b496f1eae5..78e2296e828 100644 --- a/classes/view_cover.php +++ b/classes/view_cover.php @@ -157,7 +157,7 @@ public function display_cover() { $paramurl['s'] = $this->cm->instance; $paramurl['mode'] = SURVEYPRO_NEWRESPONSEMODE; $paramurl['area'] = 'surveypro'; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; $paramurl['begin'] = 1; $url = new \moodle_url('/mod/surveypro/view.php', $paramurl); $message = get_string('addnewsubmission', 'mod_surveypro'); diff --git a/classes/view_submissionlist.php b/classes/view_responselist.php similarity index 97% rename from classes/view_submissionlist.php rename to classes/view_responselist.php index 9ae5dc6892e..32bf6d16570 100644 --- a/classes/view_submissionlist.php +++ b/classes/view_responselist.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionlist class + * The view_responselist class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -35,7 +35,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionlist { +class view_responselist { /** * @var object Course module object @@ -662,6 +662,7 @@ public function display_submissions_table() { $caneditownsubmissions = has_capability('mod/surveypro:editownsubmissions', $this->context); $caneditotherssubmissions = has_capability('mod/surveypro:editotherssubmissions', $this->context); $canduplicateownsubmissions = has_capability('mod/surveypro:duplicateownsubmissions', $this->context); + $canduplicateotherssubmissions = has_capability('mod/surveypro:duplicateotherssubmissions', $this->context); $candeleteownsubmissions = has_capability('mod/surveypro:deleteownsubmissions', $this->context); $candeleteotherssubmissions = has_capability('mod/surveypro:deleteotherssubmissions', $this->context); $cansavetopdfownsubmissions = has_capability('mod/surveypro:savetopdfownsubmissions', $this->context); @@ -837,9 +838,29 @@ public function display_submissions_table() { } // Actions. + $icons = ''; $paramurl = $paramurlbase; $paramurl['submissionid'] = $submission->submissionid; + // View. + $displayviewicon = false; + if ($ismine) { // Owner is me. + $displayviewicon = ($submission->status != SURVEYPRO_STATUSINPROGRESS); + } else { + if ($mysamegroup) { // Owner is from a group of mine. + $displayviewicon = ($submission->status == SURVEYPRO_STATUSINPROGRESS) ? false : $canseeotherssubmissions; + } + } + if ($displayviewicon) { + $paramurl['mode'] = SURVEYPRO_READONLYMODE; + $paramurl['begin'] = 1; + $paramurl['section'] = 'responsesubmit'; + + $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); + $paramlink = ['id' => 'view_submission_'.$submissionsuffix, 'title' => $readonlyaccessstr]; + $icons .= $OUTPUT->action_icon($link, $readonlyicn, null, $paramlink); + } + // Edit. $displayediticon = false; if ($ismine) { // Owner is me. @@ -863,27 +884,19 @@ public function display_submissions_table() { if ($displayediticon) { $paramurl['mode'] = SURVEYPRO_EDITMODE; $paramurl['begin'] = 1; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; if ($submission->status == SURVEYPRO_STATUSINPROGRESS) { // Here title and alt are ALWAYS $nonhistoryeditstr. $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); $paramlink = ['id' => 'edit_submission_'.$submissionsuffix, 'title' => $nonhistoryeditstr]; - $icons = $OUTPUT->action_icon($link, $nonhistoryediticn, null, $paramlink); + $icons .= $OUTPUT->action_icon($link, $nonhistoryediticn, null, $paramlink); } else { // Here title and alt depend from $this->surveypro->history. $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); $paramlink = ['id' => $linkidprefix.$submissionsuffix, 'title' => $attributestr]; - $icons = $OUTPUT->action_icon($link, $attributeicn, null, $paramlink); + $icons .= $OUTPUT->action_icon($link, $attributeicn, null, $paramlink); } - } else { - $paramurl['mode'] = SURVEYPRO_READONLYMODE; - $paramurl['begin'] = 1; - $paramurl['section'] = 'submissionform'; - - $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); - $paramlink = ['id' => 'view_submission_'.$submissionsuffix, 'title' => $readonlyaccessstr]; - $icons = $OUTPUT->action_icon($link, $readonlyicn, null, $paramlink); } // Duplicate. @@ -893,7 +906,7 @@ public function display_submissions_table() { } else { if ($mysamegroup) { // Owner is from a group of mine. // I should be here only if $canseeotherssubmissions = true. - $displayduplicateicon = $caneditotherssubmissions; + $displayduplicateicon = $canduplicateotherssubmissions; } } if ($displayduplicateicon) { // I am the owner or a groupmate. @@ -967,7 +980,6 @@ public function display_submissions_table() { } $submissions->close(); - $table->summary = get_string('submissionslist', 'mod_surveypro'); $table->print_html(); // If this is the output of a search and nothing has been found add a way to show all submissions. @@ -1006,7 +1018,8 @@ public function show_action_buttons($tifirst, $tilast) { // End of: is the button to add one more response going to be the page? // Begin of: is the button to delete all responses going to be the page? - $deleteall = $candeleteownsubmissions; + $deleteall = true; + $deleteall = $deleteall && $candeleteownsubmissions; $deleteall = $deleteall && $candeleteotherssubmissions; $deleteall = $deleteall && empty($this->searchquery); $deleteall = $deleteall && empty($tifirst); // Hide the deleteall button if not all the responses are shown. @@ -1020,7 +1033,7 @@ public function show_action_buttons($tifirst, $tilast) { $paramurl['mode'] = SURVEYPRO_NEWRESPONSEMODE; $paramurl['begin'] = 1; $paramurl['area'] = 'surveypro'; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; $addurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); $buttoncount = 1; @@ -1205,7 +1218,7 @@ public function show_thanks_page($responsestatus, $justsubmitted) { $paramurlbase = ['s' => $this->cm->instance]; if ($cansubmitmore) { // If the user is allowed to submit one more response. - $paramurl = $paramurlbase + ['mode' => SURVEYPRO_NEWRESPONSEMODE, 'begin' => 1, 'section' => 'submissionform']; + $paramurl = $paramurlbase + ['mode' => SURVEYPRO_NEWRESPONSEMODE, 'begin' => 1, 'section' => 'responsesubmit']; $buttonurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); $onemore = new \single_button($buttonurl, get_string('addnewsubmission', 'mod_surveypro'), 'post', 'primary'); @@ -1699,7 +1712,7 @@ public function submission_to_pdf() { $answernotprovided = get_string('answernotsubmitted', 'mod_surveypro'); foreach ($itemseeds as $itemseed) { // Pagebreaks are not selected by surveypro_fetch_items_seeds. - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $template = $item::get_pdf_template(); if (!$template) { @@ -1813,8 +1826,8 @@ private function add_pdf_details($pdf, $user, $timecreated, $timemodified) { // Set document information. $pdf->SetCreator(PDF_CREATOR); $pdf->SetAuthor('moodle-mod_surveypro'); - $pdf->SetTitle(get_string('userresponse', 'mod_survyepro')); - $pdf->SetSubject(get_string('pdfsubject', 'mod_survyepro')); + $pdf->SetTitle(get_string('userresponse', 'mod_surveypro')); + $pdf->SetSubject(get_string('pdfsubject', 'mod_surveypro')); $textheader = $this->get_header_text($user, $timecreated, $timemodified); $pdf->SetHeaderData('', 0, $this->surveypro->name, $textheader, [0, 64, 255], [0, 64, 128]); diff --git a/classes/view_submissionsearch.php b/classes/view_responsesearch.php similarity index 96% rename from classes/view_submissionsearch.php rename to classes/view_responsesearch.php index 9b10f780224..b5dcc759609 100644 --- a/classes/view_submissionsearch.php +++ b/classes/view_responsesearch.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionsearch class + * The view_responsesearch class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -33,7 +33,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionsearch { +class view_responsesearch { /** * @var object Course module object @@ -120,7 +120,7 @@ public function get_searchparamurl() { continue; } } - $item = surveypro_get_item($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); $userdata = new \stdClass(); $item->userform_get_user_answer($iteminfo->contentperelement, $userdata, true); diff --git a/classes/view_submissionform.php b/classes/view_responsesubmit.php similarity index 87% rename from classes/view_submissionform.php rename to classes/view_responsesubmit.php index 3df84e05f90..40c03aff0fa 100644 --- a/classes/view_submissionform.php +++ b/classes/view_responsesubmit.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionform class + * The view_responsesubmit class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -36,7 +36,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionform extends formbase { +class view_responsesubmit extends formbase { /** * @var int $mode @@ -181,7 +181,7 @@ private function save_surveypro_submission() { $timenow = time(); $savebutton = isset($this->formdata->savebutton); $saveasnewbutton = isset($this->formdata->saveasnewbutton); - // Useless: $nextbutton = isset($this->formdata->nextbutton);. + // Useless: $nextbutton = isset($this->formdata->nextbutton); $pausebutton = isset($this->formdata->pausebutton); // Useless: $prevbutton = isset($this->formdata->prevbutton);. if ($saveasnewbutton) { @@ -192,7 +192,7 @@ private function save_surveypro_submission() { // I don't save the status here because it is useless // the status is defined from the validity of each answer - // and will be saved after each respose in function save_user_data. + // and will be saved after each respose in function save_user_response. if (empty($this->formdata->submissionid)) { // Add a new record to surveypro_submission. @@ -223,7 +223,7 @@ private function save_surveypro_submission() { $submission->timecreated = $timenow; } - // Note: $DB->update_record must be inside curly brackets otherwise + // Note: $DB->update_record must be inside curly brackets (this if statement) otherwise // using "<< previous" or "next >>" to browse the submission // I get the error: // moodle_database::update_record_raw() no fields found. @@ -396,7 +396,7 @@ private function save_surveypro_submission() { * asking to the parent class to manage its own data * passing it $iteminfo->contentperelement. */ - public function save_user_data() { + public function save_user_response() { global $DB, $COURSE; $savebutton = isset($this->formdata->savebutton); @@ -405,14 +405,14 @@ public function save_user_data() { $prevbutton = isset($this->formdata->prevbutton); $nextbutton = isset($this->formdata->nextbutton); - // Drop out undesired answers from the submission. - if (!$this->surveypro->newpageforchild) { - // TAKE CARE: It is not enough to drop out unexpected answers. - // If the response is new, dropping an answer from $this->formdata make you sure the related value will not be saved - // but if the response is not new you may have the answer already in the database - // and you need to actually delete the old datum from DB! Ignoring it is not enough. - $this->drop_undesired_answers(); - } + // There are two types of undesired answers. + // The first: all the answers, of the current submission, coming from disabled item. + // The second: all the answers already saved to database but no longer valid. + // This second type comes from the following scenario: + // User edits an already submitted response. He/she changes the answer to a parent item. (Yes to no or whatever). + // There may be answers already saved in the database FOR THE SAME SUBMISSION that were allowed yesterday + // but that are not allowed now after the current change to the answer to the parent item. I have to delete them. + $this->drop_undesired_answers(); if ($savebutton || $saveasnewbutton) { $this->drop_unverified_data(); @@ -500,7 +500,7 @@ public function save_user_data() { $useranswer->timecreated = time(); $useranswer->verified = ($prevbutton || $pausebutton) ? 0 : 1; - $item = surveypro_get_item($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); // Now I ask to each item the answer for the db starting from what the user provided ($iteminfo->contentperelement). $item->userform_get_user_answer($iteminfo->contentperelement, $useranswer, false); @@ -521,7 +521,7 @@ public function save_user_data() { // 3) User reads the url and understands that the formapge is passed in GET (visible in the url). // 4) At page 3 (the page the user still does not see) of the surveypro there is mandatory field. // 5) Because of 3) user jumps to page 4 and make the final submit. - // This check is needed to verify that EACH mandatory surveypro field was actually saved. + // A check is needed to verify that EACH mandatory surveypro field was actually saved. // SECOND SCENARIO. // Let's suppose the following scenario. @@ -532,7 +532,7 @@ public function save_user_data() { // 5) User return back to page 1 without filling the mandatory field. // 6) Page 2 is saved WITHOUT the mandatory field because when the user moves back, the form VALIDATION is not executed. // 7) Because of 3) user jumps to page 3 and make the final submit. - // This check is needed to verify that EACH surveypro field was actually saved as VERIFIED. + // A check is needed to verify that EACH surveypro field was actually saved as VERIFIED. // I have to ALWAYS check for the validity of all responses // and not ONLY when ($savebutton || $saveasnewbutton) are presssed because... @@ -542,7 +542,7 @@ public function save_user_data() { // 4) I return back to page 1 // 5) Page 2 is saved WITHOUT the mandatory field because when the user moves back, the form VALIDATION is not executed. // 6) I use the breadcrumb to go somewhere else - // 7) the submission HAS TO BE saved as IN PROGRESS and not as CLOSED + // 7) So, the submission HAS TO BE saved as IN PROGRESS and not as CLOSED // even if ($savebutton || $saveasnewbutton) where never pressed. // Be optimistic. Let's start by assuming user was correct. @@ -600,14 +600,14 @@ private function check_mandatories_are_in() { $requireditems = []; foreach ($pluginlist as $plugin) { $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - $canbemandatory = $classname::item_uses_mandatory_dbfield(); - if ($canbemandatory) { + $usesmandatoryattribute = $classname::has_mandatoryattribute(); + if ($usesmandatoryattribute) { $sql = 'SELECT i.id, i.parentid, i.parentvalue, i.reserved FROM {surveypro_item} i - JOIN {surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'} p ON p.itemid = i.id + JOIN {surveyprofield_'.$plugin.'} p ON p.itemid = i.id WHERE i.surveyproid = :surveyproid AND i.hidden = :hidden - AND p.required > :required + AND i.required > :required ORDER BY p.itemid'; $whereparams = ['surveyproid' => $this->surveypro->id, 'hidden' => 0, 'required' => 0]; @@ -636,7 +636,7 @@ private function check_mandatories_are_in() { $this->responsestatus = SURVEYPRO_MISSINGMANDATORY; break; } else { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); if ($parentitem->userform_is_child_allowed_static($this->get_submissionid(), $itemseed)) { // Parent is here but it allows this item as child in this submission. Answer was jumped. // Take care: this check is valid for chains of parent-child relations too. @@ -666,9 +666,9 @@ private function check_all_was_verified() { /** * Drop old answers saved with 'verified' = 0. - * They comes from data written in pages not validated (because user returned to previous page) - * They were converted to answers with 'verified' = 1 whaen the users arrived to the same page and moved forward - * and if they are still there... they must be deleted now. + * They comes from answers in pages not verified (because user returned to previous page) + * Unverified answers are set to 'verified' when the users arrives to the page where they are NOT DISABLED and moves forward. + * If, at submission time, unverified answers are still somewhere... they must be deleted. * * Example * page 1: What is your gender? @@ -677,18 +677,18 @@ private function check_all_was_verified() { * * User starts. * Page 1: What is your gender? 'M' and 'Next page >>' - * Page 2: Question2: 'I am a male' and '<< Previous page' + * Page 2: 'Question2: Do you confirm you are a male?' 'I am a male' and '<< Previous page' * 'I am a male' is saved as unverified * Page 1: What is your gender? 'F' and 'Next page >>' - * Page 2: Question3: 'I am a female' and '<< Previous page' + * Page 2: 'Question3: Do you confirm you are a female?' 'I am a female' and '<< Previous page' * 'I am a female' is saved as unverified * Page 1: What is your gender? 'M' and 'Next page >>' - * Page 2: Question2: 'I confirm I am a male' and 'Submit' + * Page 2: 'Question2: Do you confirm you are a male?': 'I confirm I am a male' and 'Submit' * * At submit time I have: - * Question1: 'M' saved as verified - * Question2: 'I am a female' saved as unverified - * Question3: 'I confirm I am a male' saved as verified + * Question1: 'M' is saved as verified + * Question2: 'I am a female' is saved as unverified + * Question3: 'I confirm I am a male' is saved as verified * * Submit and 'I am a female' is saved as verified * Now I have to delete the unverified answer @@ -696,11 +696,8 @@ private function check_all_was_verified() { * @return void */ public function drop_unverified_data() { - global $DB; - - $whereparams = ['submissionid' => $this->formdata->submissionid, 'verified' => 0]; - $where = 'submissionid = :submissionid AND verified = :verified'; - $DB->delete_records_select('surveypro_answer', $where, $whereparams); + $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); + $utilitylayoutman->delete_answers(['submissionid' => $this->formdata->submissionid, 'verified' => 0]); } /** @@ -753,7 +750,7 @@ public function notifypeople() { $recipient->mailformat = 1; foreach ($morerecipients as $moreemail) { // Do not create duplicates. - if (in_array($moreemail, $firstlist)) { + if (isset($firstlist) && in_array($moreemail, $firstlist)) { continue; } $recipient->firstname = $moreemail; @@ -824,7 +821,7 @@ public function add_readonly_browsing_buttons() { $params['s'] = $this->surveypro->id; $params['submissionid'] = $this->get_submissionid(); $params['mode'] = SURVEYPRO_READONLYMODE; - $params['section'] = 'submissionform'; + $params['section'] = 'responsesubmit'; $userformpagecount = $this->get_userformpagecount(); if ($userformpagecount > 1) { @@ -865,103 +862,124 @@ public function add_readonly_browsing_buttons() { } /** - * Drop all the answers returned by disabled items. + * The goal of this method is twofold. + * + * The first objective is to drop all the answers returned by disabled items. * * If a child item is disabled by the parent in its same page, * the child answer (whether set) is undesired and must be deleted. * - * Let's suppose parent and child element in the same page. + * First scenario. + * Let's suppose parent and child element share the same page. * I provide the right parent answer so that the child becomes enabled. * Now I enter some input in the child element. * Then I return to parent element and change its answer. * Child is now disabled BUT equipped with an answer. * This is the answer I want to drop out. * + * Second scenario. + * Let's suppose parent and child element share the same page. + * I provide the right parent answer so that the child becomes enabled. + * I save. + * Tomorrow I return to the same response and I change my mind so that the child item is no longer enabled. + * At save time I have to drop the answers provided in the first submission. + * * @return void */ private function drop_undesired_answers() { - // Begin of: delete all the values returned by disabled items (that were NOT supposed to be returned: MDL-34815). + global $DB; + + // Take in mind that, for mysterious motivations, NOT ALWAYS mform returns ONLY enabled element content. + $submittedformpage = $this->formdata->formpage; + + // I must get the list of ALL the items of this page to check if they were already submitted in the past + // even if they were not submitted now. + $canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $this->context); + + // The current submission. $dirtydata = (array)$this->formdata; - $elementnames = array_keys($dirtydata); + + $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); + + $formpage = $this->formdata->formpage; + + [$where, $params] = surveypro_fetch_items_seeds( + $this->surveypro->id, true, $canaccessreserveditems, null, null, $formpage + ); + $fieldlist = 'id, plugin, type, parentid, parentvalue'; + $itemseeds = $DB->get_records_select('surveypro_item', $where, $params, 'sortindex', $fieldlist); $disposelist = []; $olditemid = 0; - foreach ($elementnames as $elementname) { - if ($matches = utility_item::get_item_parts($elementname)) { - // With the introduction of interactive fieldset... - // those format elements are now equipped with open/close triangle... - // and they submit their own state. - // Drop them out. - $condition = false; - $condition = $condition || ($matches['prefix'] == SURVEYPRO_DONTSAVEMEPREFIX); - $condition = $condition || ($matches['type'] == SURVEYPRO_TYPEFORMAT); - if ($condition) { - continue; // To next foreach. - } - } else { - continue; + foreach ($itemseeds as $itemseed) { + // With the introduction of interactive fieldset... + // those format elements are now equipped with open/close triangle... + // and they submit their own state. + // Drop them out. + if ($itemseed->type == SURVEYPRO_TYPEFORMAT) { + continue; // To next foreach. } - $type = $matches['type']; - $plugin = $matches['plugin']; - $itemid = $matches['itemid']; - if ($itemid == $olditemid) { + if (empty($itemseed->parentid)) { continue; } - // Let's start. - $olditemid = $itemid; - - $childitem = surveypro_get_item($this->cm, $this->surveypro, $itemid, $type, $plugin); - - $parentid = $childitem->get_parentid(); - if (empty($parentid)) { - continue; - } + $itemid = $itemseed->id; + $plugin = $itemseed->plugin; + $type = $itemseed->type; // It is, for sure, SURVEYPRO_TYPEFIELD, // If my parent is already in $disposelist, I have to go to $disposelist FOR SURE. - if (in_array($childitem->get_parentid(), $disposelist)) { - $disposelist[] = $childitem->get_itemid(); + if (in_array($itemseed->parentid, $disposelist)) { + $disposelist[] = $itemseed->id; continue; } - // Call parentitem. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $childitem->get_parentid()); + // Let's start. + // Get parentitem class. + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); $parentpage = $parentitem->get_formpage(); - $childpage = $childitem->get_formpage(); - if ($parentpage == $childpage) { // If parent and child share the same page. - // Pass to parentitem what the child needs to be displayed ($childitem->get_parentvalue()) + if ($parentpage == $submittedformpage) { // If parent and child are both here in the just submitted page. + // Pass to parentitem what the child needs to be enabled ($itemseed->parentvalue) // and compare it with what was answered to parentitem ($dirtydata). - if (!$parentitem->userform_is_child_allowed_dynamic($childitem->get_parentvalue(), $dirtydata)) { + if (!$parentitem->userform_is_child_allowed_dynamic($itemseed->parentvalue, $dirtydata)) { // Parentitem, knowing itself, compares the anwer it received with child needs and provides an answer. - $disposelist[] = $childitem->get_itemid(); + $disposelist[] = $itemseed->id; + } + } else { + // Parent item is somewhere in the previous pages while the child is here, in the just submitted page. + $submissionid = $this->formdata->submissionid; + if (empty($submissionid)) { // The submission is new. + // No answers from previous submission can be found. Carry on. + continue; + } + + // Is there an already saved answer for the item $itemseed->id in the frame of the submission $submissionid? + $sqlparams = ['submissionid' => $submissionid, 'itemid' => $itemseed->id]; + if (!$DB->record_exists('surveypro_answer', $sqlparams)) { + continue; + } + + // Is your parent item still allowing you? + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); + if (!$parentitem->userform_is_child_allowed_static($submissionid, $itemseed)) { + $utilitylayoutman->delete_answers(['submissionid' => $submissionid, 'itemid' => $itemseed->id]); } } } // Check next item. // End of: delete all the values returned by disabled items (that were NOT supposed to be returned: MDL-34815). // If not expected items are here... + $dirtydata = (array)$this->formdata; + $elementnames = array_keys($dirtydata); + if (count($disposelist)) { $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); foreach ($elementnames as $elementname) { if ($matches = utility_item::get_item_parts($elementname)) { - // With the introduction of interactive fieldset... - // those format elements are now equipped with open/close triangle... - // and they submit their own state. - // Drop them out. - $condition = false; - $condition = $condition || ($matches['prefix'] == SURVEYPRO_DONTSAVEMEPREFIX); - $condition = $condition || ($matches['type'] == SURVEYPRO_TYPEFORMAT); - if ($condition) { - continue; // To next foreach. - } $itemid = $matches['itemid']; if (in_array($itemid, $disposelist)) { unset($this->formdata->$elementname); - // If this datum was previously saved (when the item was not disabled) - // now I have to delete from database. - $utilitylayoutman->delete_answers(['submissionid' => $this->formdata->submissionid, 'itemid' => $itemid]); } } } diff --git a/db/access.php b/db/access.php index 24c7d359770..89414d76c50 100644 --- a/db/access.php +++ b/db/access.php @@ -83,11 +83,11 @@ * mod/surveypro:savetopdfownsubmissions * mod/surveypro:savetopdfotherssubmissions * - * File: view.php, $section = 'submissionform' + * File: view.php, $section = 'responsesubmit' * mod/surveypro:submit * mod/surveypro:ignoremaxentries * - * File: view.php, $section = 'searchsubmissions' + * File: view.php, $section = 'responsesearch' * mod/surveypro:searchsubmissions * * ------------------------------------------- diff --git a/db/install.xml b/db/install.xml index 4a5e5687079..d6f28db14aa 100644 --- a/db/install.xml +++ b/db/install.xml @@ -46,6 +46,15 @@ + + + + + + + + + diff --git a/db/upgrade.php b/db/upgrade.php index 340face9d36..1e49b517f18 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -369,5 +369,91 @@ function xmldb_surveypro_upgrade($oldversion) { upgrade_mod_savepoint(true, 2023012600, 'surveypro'); } + if ($oldversion < 2024022700) { + + // Define field contentformat to be added to surveypro_item. + $table = new xmldb_table('surveypro_item'); + $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'plugin'); + + // Conditionally launch add field contentformat. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('content', XMLDB_TYPE_TEXT, null, null, null, null, null, 'plugin'); + + // Conditionally launch add field content. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Surveypro savepoint reached. + upgrade_mod_savepoint(true, 2024022700, 'surveypro'); + } + + if ($oldversion < 2024032700) { + + $table = new xmldb_table('surveypro_item'); + + // 7) Define field extranote to be added to surveypro_item. + $field = new xmldb_field('extranote', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'contentformat'); + + // Conditionally launch add field extranote. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 6) Define field variable to be added to surveypro_item. + $field = new xmldb_field('variable', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'contentformat'); + + // Conditionally launch add field variable. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 5) Define field hideinstructions to be added to surveypro_item. + $field = new xmldb_field('hideinstructions', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field hideinstructions. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 4) Define field customnumber to be added to surveypro_item. + $field = new xmldb_field('customnumber', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'contentformat'); + + // Conditionally launch add field customnumber. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 3) Define field position to be added to surveypro_item. + $field = new xmldb_field('position', XMLDB_TYPE_INTEGER, '4', null, null, null, '0', 'contentformat'); + + // Conditionally launch add field position. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 2) Define field indent to be added to surveypro_item. + $field = new xmldb_field('indent', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field indent. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 1) Define field required to be added to surveypro_item. + $field = new xmldb_field('required', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field required. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Surveypro savepoint reached. + upgrade_mod_savepoint(true, 2024032700, 'surveypro'); + } + return true; } diff --git a/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php b/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php index e5de1b9b531..53200cee157 100644 --- a/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php +++ b/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'age'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginage = new backup_nested_element('surveyprofield_age', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/age/classes/item.php b/field/age/classes/item.php index e1ca457995a..61524d26e97 100644 --- a/field/age/classes/item.php +++ b/field/age/classes/item.php @@ -39,57 +39,29 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; + // Itembase properties. /** - * @var bool O => optional item; 1 => mandatory item; + * @var string Value of the default setting (invite, custom...) */ - protected $required; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var int Lowerbound for the age in unixtime */ - protected $indent; + protected $lowerbound; /** - * @var string Value of the default setting (invite, custom...) + * @var int Upperbound for the age in unixtime */ - protected $defaultoption; + protected $upperbound; - /** - * @var int Defaultvalue for the age in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Year of the defaultvalue for the age @@ -101,11 +73,6 @@ class item extends itembase { */ protected $defaultvaluemonth; - /** - * @var int Lowerbound for the age in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the age in unixtime */ @@ -116,11 +83,6 @@ class item extends itembase { */ protected $lowerboundmonth; - /** - * @var int Upperbound for the age in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the age in unixtime */ @@ -131,6 +93,11 @@ class item extends itembase { */ protected $upperboundmonth; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -164,7 +131,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -196,35 +165,24 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (itembase::item_save($record))). return parent::item_save($record); } /** - * Item add mandatory plugin fields - * Copy mandatory fields to $record + * Set defaults to fields of items * * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Age [yy/mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'age_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue; $record->lowerbound = -2148552000; $record->upperbound = 1193918400; } @@ -249,12 +207,11 @@ public function item_force_coherence($record) { /** * Convert unix time to an age. * - * @param int $time - * @param bool $applyusersettings + * @param int $unixtime * @return void */ - public function item_split_unix_time($time, $applyusersettings=true) { - $getdate = parent::item_split_unix_time($time, $applyusersettings); + public function item_split_unix_time($unixtime) { + $getdate = parent::item_split_unix_time($unixtime); $getdate['year'] -= SURVEYPROFIELD_AGE_YEAROFFSET; if ($getdate['mon'] == 12) { @@ -289,7 +246,7 @@ public function item_age_to_text($agearray) { } /** - * Convert an age to unix time. + * Convert an age to unixtime. * * @param int $year * @param int $month @@ -297,7 +254,8 @@ public function item_age_to_text($agearray) { */ public function item_age_to_unix_time($year, $month) { $year += SURVEYPROFIELD_AGE_YEAROFFSET; - return (mktime(12, 0, 0, $month, 1, $year)); + + return (gmmktime(12, 0, 0, $month, 1, $year)); } /** @@ -326,7 +284,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -349,15 +307,198 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. * - * @return the content of the static property "canbeparent" + * @return $this->upperboundmonth */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_upperboundmonth() { + return $this->upperboundmonth; } /** @@ -369,14 +510,30 @@ public function get_composite_fields() { return ['defaultvalue', 'lowerbound', 'upperbound']; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', 'defaultvalueyear', 'defaultvaluemonth', + 'lowerboundyear', 'lowerboundmonth', 'upperboundyear', 'upperboundmonth', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_age'] = []; return $fieldlist; } @@ -393,29 +550,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -443,7 +581,6 @@ public static function get_plugin_schema() { public function userform_mform_element($mform, $searchform, $readonly) { $stryears = get_string('years'); $strmonths = get_string('months', 'surveyprofield_age'); - $strnoanswer = get_string('noanswer', 'mod_surveypro'); if ($this->position == SURVEYPRO_POSITIONLEFT) { $elementlabel = $this->get_contentwithnumber(); @@ -451,8 +588,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_age_'.$this->sortindex; - // Begin of: element values. $years = []; $months = []; @@ -476,51 +611,69 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - $elementgroup = []; $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_age_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $attributes['class'] = 'indent-'.$this->indent.' age_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($readonly) { $itemname = 'yearlabel_'.$this->itemid; - $attributes['id'] = $idprefix.'_yearseparator'; - $attributes['class'] = 'inline age_static'; - $elementgroup[] = $mform->createElement('mod_surveypro_label', $itemname, '', $stryears, $attributes); + $attributes['id'] = $baseid.'_yearseparator'; + $elementgroup[] = $mform->createElement('static', $itemname, '', $stryears, $attributes); } - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'age_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); if ($readonly) { $itemname = 'monthlabel_'.$this->itemid; - $attributes['id'] = $idprefix.'_monthseparator'; - $attributes['class'] = 'inline age_static'; - $elementgroup[] = $mform->createElement('mod_surveypro_label', $itemname, '', $strmonths, $attributes); + $attributes['id'] = $baseid.'_monthseparator'; + $elementgroup[] = $mform->createElement('static', $itemname, '', $strmonths, $attributes); } if ($this->required) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - if (!$searchform) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; - $mform->_required[] = $starplace; + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + + if (!$searchform) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; + } + } else { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'age_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $strnoanswer, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $attributes['id'] = $baseid.'_noanswer'; + $strnoanswer = get_string('noanswer', 'mod_surveypro'); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $strnoanswer, $attributes); + $separator[] = ' '; + + if (!$searchform) { + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); + } else { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); + } } // End of: mform element. @@ -532,7 +685,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $agearray['mon'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -553,13 +706,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_year', $agearray['year']); - $mform->setDefault($this->itemname.'_month', $agearray['mon']); + $mform->setDefault($basename.'_year', $agearray['year']); + $mform->setDefault($basename.'_month', $agearray['mon']); } else { - $mform->setDefault($this->itemname.'_year', SURVEYPRO_IGNOREMEVALUE); - $mform->setDefault($this->itemname.'_month', SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename.'_year', SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename.'_month', SURVEYPRO_IGNOREMEVALUE); if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -578,7 +731,7 @@ public function userform_mform_validation($data, &$errors, $searchform) { // Because of this, if ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $maximumage = get_config('surveyprofield_age', 'maximumage'); @@ -606,13 +759,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_agenotset', 'surveyprofield_age', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_age_to_unix_time(0, 0)); @@ -632,6 +785,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_age'); } } + + return $errors; } /** @@ -675,7 +830,6 @@ public function userform_get_filling_instructions() { * Starting from the info set by the user in the form * this method calculates what to save in the db * or what to return for the search form. - * I don't set $olduseranswer->contentformat in order to accept the default db value. * * @param array $answer * @param object $olduseranswer @@ -764,8 +918,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/age/db/install.xml b/field/age/db/install.xml index 7d4b8030bb1..5b0776874a9 100644 --- a/field/age/db/install.xml +++ b/field/age/db/install.xml @@ -1,33 +1,17 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -36,3 +20,4 @@
+ diff --git a/field/age/db/upgrade.php b/field/age/db/upgrade.php index a18b341dca0..70eeca21be2 100644 --- a/field/age/db/upgrade.php +++ b/field/age/db/upgrade.php @@ -54,5 +54,67 @@ function xmldb_surveyprofield_age_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'age'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_age. + $table = new xmldb_table('surveyprofield_age'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_age} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'age'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_age'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_age. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_age} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'age'); + } + return true; } diff --git a/field/age/lang/en/surveyprofield_age.php b/field/age/lang/en/surveyprofield_age.php index 49dec284fed..6e73cd6fb7d 100644 --- a/field/age/lang/en/surveyprofield_age.php +++ b/field/age/lang/en/surveyprofield_age.php @@ -25,28 +25,28 @@ $string['and'] = 'and'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the age the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; +$string['defaultoption_help'] = 'This is the age the remote user will find answered by default. The default for this type of question is mandatory.'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest age the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; -$string['maximumage_desc'] = 'The maximun age this software will allow to ever enter'; +$string['lowerbound_help'] = 'The lowest age the user is allowed to enter'; $string['maximumage'] = 'Maximum age'; +$string['maximumage_desc'] = 'The maximun age this software will allow to ever enter'; $string['months'] = 'months'; $string['pluginname'] = 'Age'; +$string['privacy:metadata'] = 'The "Age" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; -$string['uerr_agenotset'] = 'Please choose a age or select the "{$a}" checkbox'; +$string['uerr_agenotset'] = 'Please choose an age or select the "{$a}" checkbox'; $string['uerr_agenotsetrequired'] = 'Age is not correctly defined'; $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest age the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest age the user is allowed to enter'; $string['userfriendlypluginname'] = 'Age [yy/mm]'; -$string['privacy:metadata'] = 'The "Age" field plugin does not store any personal data.'; diff --git a/field/age/lang/it/surveyprofield_age.php b/field/age/lang/it/surveyprofield_age.php new file mode 100644 index 00000000000..75861a487c1 --- /dev/null +++ b/field/age/lang/it/surveyprofield_age.php @@ -0,0 +1,43 @@ +. + +/** + * Strings for component 'surveyprofield_age', language 'en' + * + * @package surveyprofield_age + * @subpackage age + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['and'] = 'e'; +$string['customdefault'] = 'Custom'; +$string['defaultoption'] = 'Default'; +$string['invitemonth'] = 'Seleziona un mese'; +$string['inviteyear'] = 'Seleziona un anno'; +$string['lowerbound'] = 'Limite inferiore'; +$string['lowerbound_help'] = 'La più piccola età che l\'utente può inserire'; +$string['maximumage'] = 'Età massima'; +$string['months'] = 'mesi'; +$string['pluginname'] = 'Età'; +$string['privacy:metadata'] = 'La plugin "Age" con contiene alcun dato personale.'; +$string['restriction_lower'] = 'La risposta deve essere maggiore o uguale a {$a}'; +$string['restriction_lowerupper'] = 'La risposta deve essere compresa fra {$a->lowerbound} e {$a->upperbound}'; +$string['restriction_upper'] = 'La risposta deve essere minore o uguale a {$a}'; +$string['uerr_agenotset'] = 'Si selezioni una età o la checkbox "{$a}"'; +$string['upperbound'] = 'Limite inferiore'; +$string['upperbound_help'] = 'La più grande età che l\'utente può inserire'; +$string['userfriendlypluginname'] = 'Age [yy/mm]'; diff --git a/field/age/tests/behat/itemform.feature b/field/age/tests/behat/itemform.feature index 4994987e65b..737fd30ae8b 100644 --- a/field/age/tests/behat/itemform.feature +++ b/field/age/tests/behat/itemform.feature @@ -91,6 +91,6 @@ Feature: Create an age item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a How old were you when you started cycling?" - Then the field "id_surveypro_field_age_2_year" matches value "14" - Then the field "id_surveypro_field_age_2_month" matches value "7" + Then the field "id_field_age_2_year" matches value "14" + Then the field "id_field_age_2_month" matches value "7" Then I should see "Additional note" diff --git a/field/age/tests/behat/submit_age.feature b/field/age/tests/behat/submit_age.feature index 9c94848db36..25a951da06e 100644 --- a/field/age/tests/behat/submit_age.feature +++ b/field/age/tests/behat/submit_age.feature @@ -46,8 +46,8 @@ Feature: Submit using an age item # student1 submits And I set the following fields to these values: - | id_surveypro_field_age_1_year | 23 | - | id_surveypro_field_age_1_month | 8 | + | id_field_age_1_year | 23 | + | id_field_age_1_month | 8 | And I press "Submit" diff --git a/field/age/tests/behat/use_advanced_elements.feature b/field/age/tests/behat/use_advanced_elements.feature index 92948711dd1..4a03f1a1012 100644 --- a/field/age/tests/behat/use_advanced_elements.feature +++ b/field/age/tests/behat/use_advanced_elements.feature @@ -69,8 +69,8 @@ Feature: Use reserved elements # user submit a surveypro And I set the following fields to these values: - | id_surveypro_field_age_1_year | 8 | - | id_surveypro_field_age_1_month | 2 | + | id_field_age_1_year | 8 | + | id_field_age_1_month | 2 | And I press "Submit" And I log out @@ -83,6 +83,6 @@ Feature: Use reserved elements Then I should see "2 Second age item" And I set the following fields to these values: - | id_surveypro_field_age_2_year | 24 | - | id_surveypro_field_age_2_month | 6 | + | id_field_age_2_year | 24 | + | id_field_age_2_month | 6 | And I press "Submit" diff --git a/field/age/tests/fixtures/usertemplate/age_only_2023103100.xml b/field/age/tests/fixtures/usertemplate/age_only_2024032800.xml similarity index 92% rename from field/age/tests/fixtures/usertemplate/age_only_2023103100.xml rename to field/age/tests/fixtures/usertemplate/age_only_2024032800.xml index da8ea737a3d..d7f3a66d88a 100644 --- a/field/age/tests/fixtures/usertemplate/age_only_2023103100.xml +++ b/field/age/tests/fixtures/usertemplate/age_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>AGE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>age specific setting</b>:</p><ol><li>default.</li></ol><p>and with two more <b>validation options</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>AGE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>age specific setting</b>:</p><ol><li>default.</li></ol><p>and with two more <b>validation options</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>an age has been defined as default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>an age has been defined as default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -42,33 +37,33 @@ 1 0 age_001 + 0 + 0 + 0 + + 1 -1186059600 -2148555600 1193914800 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -77,33 +72,33 @@ 2 0 age_002 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -112,33 +107,33 @@ 3 0 age_003 + 0 + 0 + 0 + + 1 -1033563600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -147,33 +142,33 @@ 4 0 age_004 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -182,33 +177,33 @@ 5 0 age_005 + 0 + 0 + 0 + + 3 -2148555600 -2148555600 1193914800 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>user answer is limited between 20 and 40</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>user answer is limited between 20 and 40</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -217,33 +212,33 @@ 6 0 age_006 + 0 + 0 + 0 + + 1 -1186059600 -1517403600 -886255200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited between 12 years and half and 18</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited between 12 years and half and 18</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -252,33 +247,33 @@ 7 0 age_007 + 0 + 0 + 0 + + 2 -2148555600 -1754139600 -1580562000 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited over 18</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited over 18</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -287,33 +282,33 @@ 8 0 age_008 + 0 + 0 + 0 + + 1 -1033563600 -1580562000 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited between 0 and 3 months</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited between 0 and 3 months</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -322,33 +317,33 @@ 9 0 age_009 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 -2140779600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited between 18 and 65</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited between 18 and 65</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -357,6 +352,11 @@ 10 0 age_010 + 0 + 0 + 0 + + 3 -2148555600 -1580562000 diff --git a/field/age/version.php b/field/age/version.php index c78e1bb9845..06b5cbe21f4 100644 --- a/field/age/version.php +++ b/field/age/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_age'; // Full name of the plugin (used for diagnostics). diff --git a/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php b/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php index fa08c7146ec..d39c3870b76 100644 --- a/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php +++ b/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'autofill'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginautofill = new backup_nested_element('surveyprofield_autofill', ['id'], [ - 'content', 'contentformat', - 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', ]); + 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/autofill/classes/item.php b/field/autofill/classes/item.php index e7a12729fed..2487eae636e 100644 --- a/field/autofill/classes/item.php +++ b/field/autofill/classes/item.php @@ -39,57 +39,39 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; + // Itembase properties. /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH + * @var bool $hiddenfield = is the static text visible in the mform? */ - protected $position; + protected $hiddenfield; /** - * @var string Optional text with item custom note + * @var string Element #1 for $content */ - protected $extranote; + protected $element01; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Element #2 for $content */ - protected $hideinstructions; + protected $element02; /** - * @var string Name of the field storing data in the db table + * @var string Element #3 for $content */ - protected $variable; + protected $element03; /** - * @var int Indent of the item in the form page + * @var string Element #4 for $content */ - protected $indent; + protected $element04; /** - * @var bool $hiddenfield = is the static text visible in the mform? + * @var string Element #5 for $content */ - protected $hiddenfield; + protected $element05; - /** - * @var string Element #1 for $content - */ - protected $element01; + // Service variables. /** * @var string Select of the element #1 @@ -101,11 +83,6 @@ class item extends itembase { */ protected $element01text; - /** - * @var string Element #2 for $content - */ - protected $element02; - /** * @var string Select of the element #2 */ @@ -116,11 +93,6 @@ class item extends itembase { */ protected $element02text; - /** - * @var string Element #3 for $content - */ - protected $element03; - /** * @var string Select of the element #3 */ @@ -131,11 +103,6 @@ class item extends itembase { */ protected $element03text; - /** - * @var string Element #4 for $content - */ - protected $element04; - /** * @var string Select of the element #4 */ @@ -146,11 +113,6 @@ class item extends itembase { */ protected $element04text; - /** - * @var string Element #5 for $content - */ - protected $element05; - /** * @var string Select of the element #5 */ @@ -161,6 +123,11 @@ class item extends itembase { */ protected $element05text; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -193,7 +160,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['required'] = false; $this->insetupform['hideinstructions'] = false; $this->insetupform['parentid'] = false; @@ -227,14 +196,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -247,14 +212,13 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Autofill'; - $record->contentformat = 1; - $record->position = 0; - $record->variable = 'autofill_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->hiddenfield = 0; $record->element01 = 'userid'; + // $record->element02; + // $record->element03; + // $record->element04; + // $record->element05; } /** @@ -292,7 +256,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -327,29 +291,343 @@ public function item_custom_fields_to_db($record) { * * @return whether the item of this plugin can be mandatory */ - public static function item_uses_mandatory_dbfield() { + public static function has_mandatoryattribute() { return false; } + // MARK set. + + /** + * Set hiddenfield. + * + * @param string $hiddenfield + * @return void + */ + public function set_hiddenfield($hiddenfield) { + $this->hiddenfield = $hiddenfield; + } + + /** + * Set element01. + * + * @param string $element01 + * @return void + */ + public function set_element01($element01) { + $this->element01 = $element01; + } + + /** + * Set element02. + * + * @param string $element02 + * @return void + */ + public function set_element02($element02) { + $this->element02 = $element02; + } + + /** + * Set element03. + * + * @param string $element03 + * @return void + */ + public function set_element03($element03) { + $this->element03 = $element03; + } + + /** + * Set element04. + * + * @param string $element04 + * @return void + */ + public function set_element04($element04) { + $this->element04 = $element04; + } + + /** + * Set element05. + * + * @param string $element05 + * @return void + */ + public function set_element05($element05) { + $this->element05 = $element05; + } + + /** + * Set element01select. + * + * @param string $element01select + * @return void + */ + public function set_element01select($element01select) { + $this->element01select = $element01select; + } + + /** + * Set element01text. + * + * @param string $element01text + * @return void + */ + public function set_element01text($element01text) { + $this->element01text = $element01text; + } + + /** + * Set element02select. + * + * @param string $element02select + * @return void + */ + public function set_element02select($element02select) { + $this->element02select = $element02select; + } + + /** + * Set element02text. + * + * @param string $element02text + * @return void + */ + public function set_element02text($element02text) { + $this->element02text = $element02text; + } + + /** + * Set element03select. + * + * @param string $element03select + * @return void + */ + public function set_element03select($element03select) { + $this->element03select = $element03select; + } + + /** + * Set element03text. + * + * @param string $element03text + * @return void + */ + public function set_element03text($element03text) { + $this->element03text = $element03text; + } + + /** + * Set element04select. + * + * @param string $element04select + * @return void + */ + public function set_element04select($element04select) { + $this->element04select = $element04select; + } + + /** + * Set element04text. + * + * @param string $element04text + * @return void + */ + public function set_element04text($element04text) { + $this->element04text = $element04text; + } + + /** + * Set element05select. + * + * @param string $element05select + * @return void + */ + public function set_element05select($element05select) { + $this->element05select = $element05select; + } + + /** + * Set element05text. + * + * @param string $element05text + * @return void + */ + public function set_element05text($element05text) { + $this->element05text = $element05text; + } + // MARK get. /** - * Is this item available as a parent? + * Get hiddenfield. + * + * @return $this->hiddenfield + */ + public function get_hiddenfield() { + return $this->hiddenfield; + } + + /** + * Get element01. * - * @return the content of the static property "canbeparent" + * @return $this->element01 */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_element01() { + return $this->element01; + } + + /** + * Get element02. + * + * @return $this->element02 + */ + public function get_element02() { + return $this->element02; + } + + /** + * Get element03. + * + * @return $this->element03 + */ + public function get_element03() { + return $this->element03; + } + + /** + * Get element04. + * + * @return $this->element04 + */ + public function get_element04() { + return $this->element04; + } + + /** + * Get element05. + * + * @return $this->element05 + */ + public function get_element05() { + return $this->element05; + } + + /** + * Get element01select. + * + * @return $this->element01select + */ + public function get_element01select() { + return $this->element01select; + } + + /** + * Get element01text. + * + * @return $this->element01text + */ + public function get_element01text() { + return $this->element01text; + } + + /** + * Get element02select. + * + * @return $this->element02select + */ + public function get_element02select() { + return $this->element02select; + } + + /** + * Get element02text. + * + * @return $this->element02text + */ + public function get_element02text() { + return $this->element02text; + } + + /** + * Get element03select. + * + * @return $this->element03select + */ + public function get_element03select() { + return $this->element03select; + } + + /** + * Get element03text. + * + * @return $this->element03text + */ + public function get_element03text() { + return $this->element03text; + } + + /** + * Get element04select. + * + * @return $this->element04select + */ + public function get_element04select() { + return $this->element04select; + } + + /** + * Get element04text. + * + * @return $this->element04text + */ + public function get_element04text() { + return $this->element04text; + } + + /** + * Get element05select. + * + * @return $this->element05select + */ + public function get_element05select() { + return $this->element05select; + } + + /** + * Get element05text. + * + * @return $this->element05text + */ + public function get_element05text() { + return $this->element05text; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', + 'element01select', 'element02select', 'element03select', 'element04select', 'element05select', + 'element01text', 'element02text', 'element03text', 'element04text', 'element05text', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_autofill'] = []; return $fieldlist; } @@ -366,27 +644,8 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -438,7 +697,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_autofill_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_autofill_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $basename = $this->itemname; if (!$searchform) { // I can not say: "I can write the content as if the record is new because if the record is not new, @@ -446,52 +709,46 @@ public function userform_mform_element($mform, $searchform, $readonly) { // This is a label! Defults will not be applied. // So, I have to ALWAYS get them now and include them now into the item. - // Is this a new submission or I am editing an old one? + // Is this a new submission? $submissionid = $mform->getElementValue('submissionid'); - if ($submissionid) { // I am editing an old submission. + if ($submissionid) { // I am working on an already saved submission. $wheresql = 'submissionid = :submissionid AND itemid = :itemid'; $whereparams = ['submissionid' => $submissionid, 'itemid' => $this->itemid]; $answer = false; $answer = $DB->get_record('surveypro_answer', $whereparams); if ($answer) { $value = $answer->content; - } else { // This should never be verified. - $message = 'Unexpected lack of answer. '; - $message .= 'The submission id '.$submissionid.' exists '; - $message .= 'but there is not any answer for the item id '.$this->itemid; - debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); - $value = 'NULL'; + } else { + // If the answer does not exist... + // it may be I am saving a new content BUT the autofill item is in the second page of the surveypro. + $value = $this->userform_get_content(0); } } else { // I am editing a new submission. $value = $this->userform_get_content(0); } - $mform->addElement('hidden', $this->itemname, $value); - $mform->setType($this->itemname, PARAM_RAW); - $mform->setDefault($this->itemname, $value); + $mform->addElement('hidden', $basename, $value); + $mform->setType($basename, PARAM_RAW); + $mform->setDefault($basename, $value); if (!$this->hiddenfield) { - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' label_static']; - $mform->addElement('mod_surveypro_label', $this->itemname.'_static', $elementlabel, $value, $attributes); + $attributes = ['id' => $baseid]; + $elementgroup[] = $mform->createElement('static', $basename.'_static', '', $value, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); } } else { - $attributes = []; - $elementgroup = []; - - $itemname = $this->itemname; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' autofill_text'; - $elementgroup[] = $mform->createElement('text', $itemname, '', $attributes); - - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'autofill_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - - $mform->setType($this->itemname, PARAM_RAW); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $basename = $this->itemname; + $attributes['id'] = $baseid; + + $elementgroup[] = $mform->createElement('text', $basename, '', $attributes); + $mform->setType($basename, PARAM_RAW); + + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -505,6 +762,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** @@ -673,8 +931,6 @@ public function userform_get_content($submissionid) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname]; - - return $elementnames; + return []; } } diff --git a/field/autofill/db/install.xml b/field/autofill/db/install.xml index c6ad22960cb..4e354db95a9 100644 --- a/field/autofill/db/install.xml +++ b/field/autofill/db/install.xml @@ -1,35 +1,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/autofill/db/upgrade.php b/field/autofill/db/upgrade.php index 6f7c5a07b9f..77695377c60 100644 --- a/field/autofill/db/upgrade.php +++ b/field/autofill/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyprofield_autofill_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Autofill savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'autofill'); } @@ -63,9 +63,70 @@ function xmldb_surveyprofield_autofill_upgrade($oldversion) { $whereparams = ['parentid' => null, 'parentvalue' => null, 'plugin' => 'autofill']; $DB->execute($sql, $whereparams); - // Surveypro savepoint reached. + // Autofill savepoint reached. upgrade_plugin_savepoint(true, 2024011101, 'surveyprofield', 'autofill'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_autofill. + $table = new xmldb_table('surveyprofield_autofill'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dieing fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_autofill} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Autofill savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'autofill'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_autofill'); + + $fieldnames = ['indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_autofill. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_autofill} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Autofill savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'autofill'); + } + return true; } diff --git a/field/autofill/lang/en/surveyprofield_autofill.php b/field/autofill/lang/en/surveyprofield_autofill.php index e007c76c551..cc7c028fad0 100644 --- a/field/autofill/lang/en/surveyprofield_autofill.php +++ b/field/autofill/lang/en/surveyprofield_autofill.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['contentelement_group_help'] = 'Element building the static text'; $string['contentelement_group'] = 'Content element'; +$string['contentelement_group_help'] = 'Element building the static text'; $string['contentselect_err'] = 'At least one element has to be not null'; $string['courseid'] = 'course ID'; $string['coursename'] = 'course name'; @@ -34,12 +34,13 @@ $string['element03'] = 'Third content element'; $string['element04'] = 'Fourth content element'; $string['element05'] = 'Fifth content element'; -$string['hiddenfield_help'] = 'This option allow you to hide or show this autofill element from the survey form. Selecting this checkbox the element will be added to the form as hidden field so the user will not see it.'; $string['hiddenfield'] = 'Make hidden'; +$string['hiddenfield_help'] = 'This option allow you to hide or show this autofill element from the survey form. Selecting this checkbox the element will be added to the form as hidden field so the user will not see it.'; $string['ierr_contenttext'] = 'The requested text can be null'; $string['label'] = 'static label'; $string['latevalue'] = 'Content will be provided once available'; $string['pluginname'] = 'Autofill'; +$string['privacy:metadata'] = 'The "Autofill" field plugin does not store any personal data.'; $string['submission'] = 'Response'; $string['submissiondate'] = 'response date'; $string['submissiondateandtime'] = 'response date and time'; @@ -54,4 +55,3 @@ $string['usergroupname'] = 'user group name'; $string['userid'] = 'user ID'; $string['userlastname'] = 'user last name'; -$string['privacy:metadata'] = 'The "Autofill" field plugin does not store any personal data.'; diff --git a/field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml b/field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml similarity index 92% rename from field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml rename to field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml index 7c443844ca8..4bb181031b0 100644 --- a/field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml +++ b/field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml @@ -1,74 +1,74 @@ - + + <h5>AUTOFILL</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>autofill specific setting</b>:</p><ol><li>First content element</li><li>Second content element</li><li>Third content element</li><li>Fourth content element</li><li>Fifth content element</li><li>Make hidden</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>AUTOFILL</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>autofill specific setting</b>:</p><ol><li>First content element</li><li>Second content element</li><li>Third content element</li><li>Fourth content element</li><li>Fifth content element</li><li>Make hidden</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is going to be visible in the surveypro page.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is going to be visible in the surveypro page.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Your user ID</p> 1 0 0 autofill_001 + 0 + 0 + 0 + + 0 userid - + + <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is not visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is not going to be visible in the surveypro page. This is the reason why you can not see that element in the surveypro preview page.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is not visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is not going to be visible in the surveypro page. This is the reason why you can not see that element in the surveypro preview page.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Your user ID</p> 1 0 0 autofill_002 + 0 + 0 + 0 + + 1 userid diff --git a/field/autofill/version.php b/field/autofill/version.php index 1d4482b7ea8..1e0445ccf4b 100644 --- a/field/autofill/version.php +++ b/field/autofill/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_autofill'; // Full name of the plugin (used for diagnostics). diff --git a/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php b/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php index af90253987e..4b320d8aece 100644 --- a/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php +++ b/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'boolean'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginboolean = new backup_nested_element('surveyprofield_boolean', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'style', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'style', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/boolean/classes/item.php b/field/boolean/classes/item.php index fd423184a0d..5c30b60c000 100644 --- a/field/boolean/classes/item.php +++ b/field/boolean/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string Value of the default setting (invite, custom...) @@ -88,7 +48,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -102,6 +62,13 @@ class item extends itembase { */ protected $style; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -134,7 +101,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -166,14 +135,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (itembase::item_save($record))). return parent::item_save($record); @@ -186,13 +151,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Boolean'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'boolean_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 1; $record->downloadformat = 'strfbool01'; @@ -215,13 +174,13 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. // 2. Override few values. // Hideinstructions is set by design. - $record->hideinstructions = 1; + // Nothing to do: no checkboxes in this plugin item form. // 3. Set values corresponding to checkboxes. // Take care: 'required', 'hideinstructions' were already considered in get_common_settings. @@ -245,15 +204,84 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set style. + * + * @param string $style + * @return void + */ + public function set_style($style) { + $this->style = $style; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get style. * - * @return the content of the static property "canbeparent" + * @return $this->style */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_style() { + return $this->style; } /** @@ -281,14 +309,27 @@ public function get_friendlyformat() { return 'strfbool01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultoption', 'defaultvalue', 'downloadformat', 'style']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_boolean'] = []; return $fieldlist; } @@ -305,29 +346,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -468,14 +490,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_boolean_'.$this->sortindex; - $yeslabel = get_string('yes'); $nolabel = get_string('no'); $noanswerstr = get_string('noanswer', 'mod_surveypro'); $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' boolean_radio'; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_boolean_'.$this->sortindex; + $basename = $this->itemname; if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { // Begin of: element values. @@ -484,8 +507,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $options[SURVEYPRO_INVITEVALUE] = get_string('choosedots'); } - } else { - $options[SURVEYPRO_IGNOREMEVALUE] = ''; } $options['1'] = $yeslabel; $options['0'] = $nolabel; @@ -495,60 +516,49 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - if ($this->required) { - if (!$searchform) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; - } + $attributes['id'] = $baseid; + $elementgroup[] = $mform->createElement('select', $basename, $elementlabel, $options, $attributes); + + if ($searchform) { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } - $attributes['id'] = $idprefix; - $mform->addElement('select', $this->itemname, $elementlabel, $options, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); // End of: mform element. } else { // SURVEYPROFIELD_BOOLEAN_USERADIOV or SURVEYPROFIELD_BOOLEAN_USERADIOH. $separator = ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOV) ? '
' : ' '; - $elementgroup = []; // Begin of: mform element. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $choosedotsstr = get_string('choosedots'); - $attributes['id'] = $idprefix.'_invite'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; - } + $attributes['id'] = $baseid.'_invite'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); } } else { $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $starstr, SURVEYPRO_IGNOREMEVALUE, $attributes); - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; - } + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $starstr, SURVEYPRO_IGNOREMEVALUE, $attributes); } - $attributes['id'] = $idprefix.'_1'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $yeslabel, '1', $attributes); - - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; + $attributes['id'] = $baseid.'_1'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $yeslabel, '1', $attributes); + $attributes['id'] = $baseid.'_0'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $nolabel, '0', $attributes); + if (!$this->required) { + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); } + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); - $attributes['id'] = $idprefix.'_0'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $nolabel, '0', $attributes); - - if (!$this->required) { - $attributes['id'] = $idprefix.'_noanswer'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); + if ($searchform) { + $mform->setDefault($basename.'_group', SURVEYPRO_IGNOREMEVALUE); } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); // End of: mform element. } @@ -559,15 +569,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - if ($this->position == SURVEYPRO_POSITIONTOP) { - $starplace = $this->itemname.'_extrarow'; - } else { - if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { - $starplace = $this->itemname; - } else { // SURVEYPROFIELD_BOOLEAN_USERADIOV or SURVEYPROFIELD_BOOLEAN_USERADIOH. - $starplace = $this->itemname.'_group'; - } - } + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -603,16 +605,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } - $errorkey = ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) ? $this->itemname : $this->itemname.'_group'; + $fieldname = $this->itemname; + $errorkey = $this->itemname.'_group'; // I need to check value is different from SURVEYPRO_INVITEVALUE even if it is not required. - if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { + if ($data[$fieldname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_booleannotset', 'surveyprofield_boolean'); - return; } + + return $errors; } /** @@ -729,12 +733,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { - $elementnames = [$this->itemname]; - } else { - $elementnames = [$this->itemname.'_group']; - } - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/boolean/db/install.xml b/field/boolean/db/install.xml index bca38258c1c..b997646e51c 100644 --- a/field/boolean/db/install.xml +++ b/field/boolean/db/install.xml @@ -1,33 +1,17 @@ -
- - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/field/boolean/db/upgrade.php b/field/boolean/db/upgrade.php index e77336e1742..5bc5b397da6 100644 --- a/field/boolean/db/upgrade.php +++ b/field/boolean/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_boolean_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Boolean savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'boolean'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_boolean. + $table = new xmldb_table('surveyprofield_boolean'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_boolean} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Boolean savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'boolean'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_boolean'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_boolean. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_boolean} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Boolean savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'boolean'); + } + return true; } diff --git a/field/boolean/lang/en/surveyprofield_boolean.php b/field/boolean/lang/en/surveyprofield_boolean.php index fdb60a64d2d..8db52e977bd 100644 --- a/field/boolean/lang/en/surveyprofield_boolean.php +++ b/field/boolean/lang/en/surveyprofield_boolean.php @@ -23,13 +23,14 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['option'] = 'Option'; $string['parentformat'] = '[0] or [1]'; $string['pluginname'] = 'Boolean'; +$string['privacy:metadata'] = 'The "Boolean" field plugin does not store any personal data.'; $string['strfbool01'] = 'yes/no'; $string['strfbool02'] = 'Yes/No'; $string['strfbool03'] = 'y/n'; @@ -40,11 +41,10 @@ $string['strfbool08'] = 'T/F'; $string['strfbool09'] = '1/0'; $string['strfbool10'] = '+/-'; -$string['style_help'] = 'The style of the field'; $string['style'] = 'Element style'; +$string['style_help'] = 'The style of the field'; $string['uerr_booleannotset'] = 'Please choose a value'; $string['usemenu'] = 'dropdown menu'; $string['useradioh'] = 'horizontal radio buttons'; $string['useradiov'] = 'vertical radio buttons'; $string['userfriendlypluginname'] = 'Boolean'; -$string['privacy:metadata'] = 'The "Boolean" field plugin does not store any personal data.'; diff --git a/field/boolean/tests/behat/itemform.feature b/field/boolean/tests/behat/itemform.feature index e7abe48f499..a8659a209ed 100644 --- a/field/boolean/tests/behat/itemform.feature +++ b/field/boolean/tests/behat/itemform.feature @@ -69,7 +69,7 @@ Feature: Create a boolean item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Is it true?" - Then the field "id_surveypro_field_boolean_2_1" matches value "1" + Then the field "id_field_boolean_2_1" matches value "1" Then I should see "Additional note" And I select "Elements" from the "jump" singleselect @@ -85,5 +85,5 @@ Feature: Create a boolean item And I select "Preview" from the "jump" singleselect Then I should see "II.b Is it true?" - Then the field "id_surveypro_field_boolean_3" matches value "Choose..." + Then the field "id_field_boolean_3" matches value "Choose..." Then I should see "One more additional note" diff --git a/field/boolean/tests/behat/submit_boolean.feature b/field/boolean/tests/behat/submit_boolean.feature index b56646953bc..a3da1623801 100644 --- a/field/boolean/tests/behat/submit_boolean.feature +++ b/field/boolean/tests/behat/submit_boolean.feature @@ -70,8 +70,8 @@ Feature: Submit using a boolean item # student1 submits And I set the following fields to these values: | 4a Is it true? | Yes | - | id_surveypro_field_boolean_2_0 | 1 | - | id_surveypro_field_boolean_3_1 | 1 | + | id_field_boolean_2_0 | 1 | + | id_field_boolean_3_1 | 1 | And I press "Submit" diff --git a/field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml b/field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml similarity index 77% rename from field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml rename to field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml index e24d66eeae5..63a6074ff63 100644 --- a/field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml +++ b/field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>BOOLEAN</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>boolean specific setting</b>:</p><ol><li>Element style</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>BOOLEAN</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>boolean specific setting</b>:</p><ol><li>Element style</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -41,33 +36,33 @@ 0 1 boolean_001 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 Intro 0 0 0 - <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -75,33 +70,33 @@ 0 2 boolean_002 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -109,33 +104,33 @@ 0 3 boolean_003 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -143,33 +138,33 @@ 0 4 boolean_004 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -177,32 +172,33 @@ 0 5 boolean_005 + 0 + 0 + 0 + + 3 + 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -210,33 +206,33 @@ 0 6 boolean_006 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 Intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -244,33 +240,33 @@ 0 7 boolean_007 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -278,33 +274,33 @@ 0 8 boolean_008 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -312,33 +308,33 @@ 0 9 boolean_009 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -346,32 +342,33 @@ 0 10 boolean_010 + 0 + 0 + 0 + + 3 + 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -379,33 +376,33 @@ 0 11 boolean_011 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 12 Intro 0 0 0 - <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 12 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -413,33 +410,33 @@ 0 12 boolean_012 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -447,33 +444,33 @@ 0 13 boolean_013 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 14 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 14 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -481,33 +478,33 @@ 0 14 boolean_014 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 15 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 15 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -515,7 +512,13 @@ 0 15 boolean_015 + 0 + 0 + 0 + + 3 + 1 strfbool01 diff --git a/field/boolean/version.php b/field/boolean/version.php index 7fd3502e7bb..86f0ed1d491 100644 --- a/field/boolean/version.php +++ b/field/boolean/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_boolean'; // Full name of the plugin (used for diagnostics). diff --git a/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php b/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php index b8ccf94d27b..b07d978b747 100644 --- a/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php +++ b/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'character'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugincharacter = new backup_nested_element('surveyprofield_character', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'trimonsave', - 'defaultvalue', 'pattern', 'minlength', 'maxlength', ]); + 'trimonsave', 'defaultvalue', 'pattern', 'minlength', 'maxlength', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/character/classes/item.php b/field/character/classes/item.php index f6949aa662d..596eefed20f 100644 --- a/field/character/classes/item.php +++ b/field/character/classes/item.php @@ -39,60 +39,15 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the user input will be trimmed at save time + * @var bool True if the user input will be trimmed at save time */ protected $trimonsave; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; - - /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -109,19 +64,26 @@ class item extends itembase { protected $pattern; /** - * @var string Required pattern for the text. Mix of: 'A', 'a', '0' + * @var int Minimum allowed text length */ - protected $patterntext; + protected $minlength; /** - * @var int Minimum allowed length + * @var int Maximum allowed text length */ - protected $minlength; + protected $maxlength; + + // Service variables. /** - * @var int Maximum allowed length + * @var string Required pattern for the text. Mix of: 'A', 'a', '0' */ - protected $maxlength; + protected $patterntext; + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -155,7 +117,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -187,14 +151,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -207,16 +167,12 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Character'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'character_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + $record->trimonsave = 0; + // $record->defaultvalue $record->pattern = SURVEYPROFIELD_CHARACTER_FREEPATTERN; $record->minlength = 0; + // $record->maxlength } /** @@ -248,7 +204,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. if ($record->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN) { $record->pattern = $record->patterntext; @@ -281,56 +237,173 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set trimonsave. + * + * @param string $trimonsave + * @return void + */ + public function set_trimonsave($trimonsave) { + $this->trimonsave = $trimonsave; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set pattern. + * + * @param string $pattern + * @return void + */ + public function set_pattern($pattern) { + $this->pattern = $pattern; + } + + /** + * Set minlength. + * + * @param string $minlength + * @return void + */ + public function set_minlength($minlength) { + $this->minlength = $minlength; + } + + /** + * Set maxlength. + * + * @param string $maxlength + * @return void + */ + public function set_maxlength($maxlength) { + $this->maxlength = $maxlength; + } + + /** + * Set patterntext. + * + * @param string $patterntext + * @return void + */ + public function set_patterntext($patterntext) { + $this->patterntext = $patterntext; + } + // MARK get. /** - * Is this item available as a parent? + * Get trimonsave. + * + * @return $this->trimonsave + */ + public function get_trimonsave() { + return $this->trimonsave; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get pattern. + * + * @return $this->pattern + */ + public function get_pattern() { + return $this->pattern; + } + + /** + * Get minlength. + * + * @return $this->minlength + */ + public function get_minlength() { + return $this->minlength; + } + + /** + * Get maxlength. * - * @return the content of the static property "canbeparent" + * @return $this->maxlength */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_maxlength() { + return $this->maxlength; + } + + /** + * Get patterntext. + * + * @return $this->patterntext + */ + public function get_patterntext() { + return $this->patterntext; } /** * Get the requested property. * * @param string $field - * @return the content of the field + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { - if ($field == 'pattern') { - $condition = ($this->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN); - $condition = $condition || ($this->pattern == SURVEYPROFIELD_CHARACTER_REGEXPATTERN); - if ($condition) { - return $this->patterntext; + if (isset($this->{$field})) { + if ($field == 'pattern') { + $condition = ($this->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN); + $condition = $condition || ($this->pattern == SURVEYPROFIELD_CHARACTER_REGEXPATTERN); + if ($condition) { + $return = $this->get_patterntext(); + } else { + $return = $this->get_pattern(); + } } else { - return $this->pattern; + $return = parent::get_generic_property($field); } } else { - return parent::get_generic_property($field); + $return = false; } + + return $return; } /** - * Make the list of multilang plugin fields. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return array of fields + * @return array $data */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'defaultvalue']; + public function get_plugin_presets() { + $pluginproperties = ['trimonsave', 'defaultvalue', 'pattern', 'patterntext', 'minlength', 'maxlength']; + $data = $this->get_base_presets($pluginproperties); - return $fieldlist; + return $data; } /** - * Does the user input need trim? + * Make the list of multilang plugin fields. * - * @return if this plugin requires a user input trim + * @param boolean $includemetafields + * @return array of fields */ - public function get_trimonsave() { - return $this->trimonsave; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_character'] = ['defaultvalue']; + + return $fieldlist; } /** @@ -345,28 +418,9 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - + - - + @@ -422,13 +476,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_character_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_character_'.$this->sortindex; + $basename = $this->itemname; $thresholdsize = 37; $lengthtochar = 1.3; - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' character_text'; + $attributes['id'] = $baseid; if (!empty($this->maxlength)) { $attributes['maxlength'] = $this->maxlength; if ($this->maxlength < $thresholdsize) { @@ -439,33 +495,33 @@ public function userform_mform_element($mform, $searchform, $readonly) { } else { $attributes['size'] = $thresholdsize * $lengthtochar; } + if (!$searchform) { - $mform->addElement('text', $this->itemname, $elementlabel, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - $mform->setDefault($this->itemname, $this->defaultvalue); + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + + $mform->setType($basename, PARAM_RAW); + $mform->setDefault($basename, $this->defaultvalue); if ($this->required) { // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('text', $this->itemname, '', $attributes); + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->setType($basename, PARAM_RAW); - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -479,17 +535,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; + } + + $errorkey = $this->itemname.'_group'; + $fieldname = $this->itemname; + if ($this->trimonsave) { + if (trim($data[$fieldname]) != $data[$fieldname]) { + $warnings[$errorkey] = get_string('uerr_willbetrimmed', 'mod_surveypro'); + } } - $errorkey = $this->itemname; - $userinput = empty($this->trimonsave) ? $data[$this->itemname] : trim($data[$this->itemname]); + $userinput = empty($this->trimonsave) ? $data[$fieldname] : trim($data[$fieldname]); if (empty($userinput)) { if ($this->required) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } $answerlength = \core_text::strlen($userinput); @@ -534,7 +597,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $message = 'Unexpected $this->pattern = '.$this->pattern; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - // Return $errors; is not needed because $errors is passed by reference. + + if ( $errors && isset($warnings) ) { + // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. + $errors += $warnings; + } + + return $errors; } /** @@ -653,8 +722,6 @@ public function userform_get_prefill($fromdb) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname]; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/character/classes/itemsetupform.php b/field/character/classes/itemsetupform.php index da5e8d426f3..0e026f19f99 100644 --- a/field/character/classes/itemsetupform.php +++ b/field/character/classes/itemsetupform.php @@ -61,7 +61,7 @@ public function definition() { $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_character'); $mform->setType($fieldname, PARAM_RAW); - // Item: trimonsave. + // Itembase: trimonsave. $fieldname = 'trimonsave'; $mform->addElement('checkbox', $fieldname, get_string($fieldname, 'surveyprofield_character')); $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_character'); @@ -137,15 +137,16 @@ public function validation($data, $files) { if (!empty($data['defaultvalue'])) { // Maximum characters > length of default. $defaultvaluelength = \core_text::strlen($data['defaultvalue']); - if (!empty($data['maxlength'])) { - if ($defaultvaluelength > $data['maxlength']) { - $errors['defaultvalue'] = get_string('ierr_toolongdefault', 'surveyprofield_character'); + if ($data['pattern'] == SURVEYPROFIELD_CHARACTER_FREEPATTERN) { + if (!empty($data['maxlength'])) { + if ($defaultvaluelength > $data['maxlength']) { + $errors['defaultvalue'] = get_string('ierr_toolongdefault', 'surveyprofield_character'); + } + } + // Minimum characters < length of default. + if ($defaultvaluelength < $data['minlength']) { + $errors['defaultvalue'] = get_string('ierr_tooshortdefault', 'surveyprofield_character'); } - } - - // Minimum characters < length of default. - if ($defaultvaluelength < $data['minlength']) { - $errors['defaultvalue'] = get_string('ierr_tooshortdefault', 'surveyprofield_character'); } // Default has to match the text pattern. diff --git a/field/character/db/install.xml b/field/character/db/install.xml index f8a02e1d0f9..17ffe22c4c7 100644 --- a/field/character/db/install.xml +++ b/field/character/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/character/db/upgrade.php b/field/character/db/upgrade.php index 0d6473a24bc..7da1c228201 100644 --- a/field/character/db/upgrade.php +++ b/field/character/db/upgrade.php @@ -58,6 +58,7 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { // Put any upgrade step following this. if ($oldversion < 2016062401) { + // Define field trimonsave to be added to surveyprofield_character. $table = new xmldb_table('surveyprofield_character'); $field = new xmldb_field('trimonsave', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'required'); @@ -72,7 +73,7 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { } if ($oldversion < 2024020700) { - // Reorder the field if the table. + // Reorder the field in the table. // Define field nexttrimonsave to be added to surveyprofield_character. $table = new xmldb_table('surveyprofield_character'); @@ -104,5 +105,66 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024020700, 'surveyprofield', 'character'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_character. + $table = new xmldb_table('surveyprofield_character'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_character} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Character savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'character'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_character'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_character. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_character} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Character savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'character'); + } + return true; } diff --git a/field/character/lang/en/surveyprofield_character.php b/field/character/lang/en/surveyprofield_character.php index 3d7cae7f713..a736de9e0b4 100644 --- a/field/character/lang/en/surveyprofield_character.php +++ b/field/character/lang/en/surveyprofield_character.php @@ -23,11 +23,11 @@ */ $string['custompattern'] = 'custom pattern'; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['defaultvalue'] = 'Default'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['free'] = 'free pattern'; $string['ierr_defaultbadlength'] = 'Default is not {$a} character long as implicitly declared in the pattern'; -$string['ierr_defaultisnotemail'] = 'Default does not math email pattern'; +$string['ierr_defaultisnotemail'] = 'Default does not match email pattern'; $string['ierr_defaultisnoturl'] = 'Default does not appear a valid URL'; $string['ierr_extracharfound'] = '{$a} characters are not allowed. Please, use only "A", "a", "*" and "0"'; $string['ierr_minexceeds'] = 'Minimum length has to be positive'; @@ -37,15 +37,15 @@ $string['ierr_patternisempty'] = 'pattern is missing'; $string['ierr_toolongdefault'] = 'Default has to be shorter-equal than maximum allowed length'; $string['ierr_tooshortdefault'] = 'Default has to be longer-equal than minimum allowed length'; -$string['length_help'] = 'The width of the field in characters'; $string['length'] = 'Field width in characters'; +$string['length_help'] = 'The width of the field in characters'; $string['mail'] = 'email address'; -$string['maxlength_help'] = 'The maximum number of characters allowed for the answer to this question'; $string['maxlength'] = 'Maximum length (in characters)'; -$string['minlength_help'] = 'The minimum number of characters allowed for the answer to this question'; +$string['maxlength_help'] = 'The maximum number of characters allowed for the answer to this question'; $string['minlength'] = 'Minimum length (in characters)'; -$string['pattern_help'] = 'If the answer is supposed to fit a specific pattern, define it here using
  • "A" for upper case characters;
  • "a" for lower case characters;
  • "0" for numbers;
  • "*" for to include upper case, lower case, numbers or any other character like, for instance: ,_%."$!\' or spaces.
'; +$string['minlength_help'] = 'The minimum number of characters allowed for the answer to this question'; $string['pattern'] = 'Text pattern'; +$string['pattern_help'] = 'If the answer is supposed to fit a specific pattern, define it here using
  • "A" for upper case characters;
  • "a" for lower case characters;
  • "0" for numbers;
  • "*" for to include upper case, lower case, numbers or any other character like, for instance: ,_%."$!\' or spaces.
'; $string['pluginname'] = 'Short text'; $string['privacy:metadata'] = 'The "Character" field plugin does not store any personal data.'; $string['regex'] = 'regular expression'; @@ -57,8 +57,8 @@ $string['restrictions_minmax'] = 'Text length is supposed to range between {$a->minlength} and {$a->maxlength} characters'; $string['restrictions_regex'] = 'Text is supposed to match the following regular expression: "{$a}"'; $string['restrictions_url'] = 'URL is expected here'; -$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['trimonsave'] = 'Clean answer at save time'; +$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['uerr_invalidemail'] = 'Text is not a valid email'; $string['uerr_invalidregex'] = 'Regular expression \'{$a}\' is not valid.'; $string['uerr_invalidurl'] = 'Text is not a valid URL'; diff --git a/field/character/lang/es_mx/surveyprofield_character.php b/field/character/lang/es_mx/surveyprofield_character.php index bebe9a1de99..8d96037c2d6 100644 --- a/field/character/lang/es_mx/surveyprofield_character.php +++ b/field/character/lang/es_mx/surveyprofield_character.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); $string['custompattern'] = 'personalizado'; -$string['defaultvalue_help'] = 'Este es el valor que el usuario remoto encontrará contestado por defecto'; $string['defaultvalue'] = 'Valor por defecto'; +$string['defaultvalue_help'] = 'Este es el valor que el usuario remoto encontrará contestado por defecto'; $string['free'] = 'patrón libre'; $string['ierr_defaultbadlength'] = 'El valor por defecto no es de {$a} caracteres de longitud porque está declarado implícitamente en el patrón'; $string['ierr_defaultisnotemail'] = 'El valor por defecto no coincide con el patrón del Email'; @@ -39,15 +39,15 @@ $string['ierr_patternisempty'] = 'falta el patrón'; $string['ierr_toolongdefault'] = 'El valor por defecto debe de ser menor o igual a la longitud máxima permitida'; $string['ierr_tooshortdefault'] = 'El valor por defecto debe de ser más largo o igual a la longitud mínima permitida'; -$string['length_help'] = 'El ancho del campo en caracteres'; $string['length'] = 'Ancho del campo en caracteres'; +$string['length_help'] = 'El ancho del campo en caracteres'; $string['mail'] = 'dirección Email'; -$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación a esta pregunta'; $string['maxlength'] = 'Longitud máxima (en caracteres)'; -$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; +$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación a esta pregunta'; $string['minlength'] = 'Longitud mínima (en caracteres)'; -$string['pattern_help'] = 'Si se supone que la contestación ajuste a un patrón específico, defínala aquí usando
  • "A" para caracteres en MAYÚSCULAS;
  • "a" para caracteres en minúsculas;
  • "0" para números;
  • "*" para incluir MAYÚSCULAS, minúsculas, números y algun otro caracter como por ejemplo: ,_%."$!\' o espacios.
'; +$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; $string['pattern'] = 'Patrón de texto'; +$string['pattern_help'] = 'Si se supone que la contestación ajuste a un patrón específico, defínala aquí usando
  • "A" para caracteres en MAYÚSCULAS;
  • "a" para caracteres en minúsculas;
  • "0" para números;
  • "*" para incluir MAYÚSCULAS, minúsculas, números y algun otro caracter como por ejemplo: ,_%."$!\' o espacios.
'; $string['pluginname'] = 'Texto corto'; $string['restrictions_custom'] = 'El texto se supone que coincide con el siguiente patrón: "{$a}"'; $string['restrictions_email'] = 'Aquí se espera un Email'; @@ -56,8 +56,8 @@ $string['restrictions_min'] = 'La respuesta se supone que es más larga o igual a {$a} caracteres'; $string['restrictions_minmax'] = 'El rango de la longitud del texto se supone que esté entre {$a->minlength} y {$a->maxlength} caracteres'; $string['restrictions_url'] = 'Aquí se espera una URL'; -$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['trimonsave'] = 'Contestación limpia al momento de guardar'; +$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['uerr_invalidemail'] = 'El texto no es un Email válido'; $string['uerr_invalidurl'] = 'El texto no es una URL válida'; $string['uerr_nopatternmatch'] = 'El texto no coincide con el patrón requerido'; diff --git a/field/character/tests/behat/itemform.feature b/field/character/tests/behat/itemform.feature index f4e9ef9452d..d469efafcca 100644 --- a/field/character/tests/behat/itemform.feature +++ b/field/character/tests/behat/itemform.feature @@ -80,5 +80,5 @@ Feature: Create a character item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a This is a free text" - Then the field "id_surveypro_field_character_2" matches value "simple, but longer, default" + Then the field "id_field_character_2" matches value "simple, but longer, default" Then I should see "Additional note" diff --git a/field/character/tests/behat/trim.feature b/field/character/tests/behat/trim.feature index 4ec4c8088a5..d6cee7482b9 100644 --- a/field/character/tests/behat/trim.feature +++ b/field/character/tests/behat/trim.feature @@ -30,8 +30,8 @@ Feature: Test the use of character trim And I set the following fields to these values: | Content | This is a standard text | | Required | 1 | - | Additional note | This will not be trimmed | | Clean answer at save time | 0 | + | Additional note | This will not be trimmed | | pattern | free pattern | | Minimum length (in characters) | 20 | | Maximum length (in characters) | 30 | @@ -45,8 +45,8 @@ Feature: Test the use of character trim And I set the following fields to these values: | Content | Text to trim | | Required | 1 | - | Additional note | This will be trimmed | | Clean answer at save time | 1 | + | Additional note | This will be trimmed | | pattern | free pattern | | Minimum length (in characters) | 20 | | Maximum length (in characters) | 30 | @@ -60,6 +60,7 @@ Feature: Test the use of character trim And I press "New response" And I set the field "This is a standard text" to " false long text " And I set the field "Text to trim" to " false long text " + And I press "Submit" Then I should see "Text is too short" @@ -74,5 +75,5 @@ Feature: Test the use of character trim And I press "Continue to responses list" And I follow "view_submission_row_1" - Then the field "id_surveypro_field_character_1" matches value " false long text " - Then the field "id_surveypro_field_character_2" matches value "text correctly trimmed" + Then the field "id_field_character_1" matches value " false long text " + Then the field "id_field_character_2" matches value "text correctly trimmed" diff --git a/field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml b/field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml similarity index 87% rename from field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml rename to field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml index 461fa42a441..c2154218660 100644 --- a/field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml +++ b/field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml @@ -1,287 +1,279 @@ - + + <h5>SHORT TEXT<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>short text specifi</b><b>c setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Text pattern<br /></li><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SHORT TEXT<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>short text specifi</b><b>c setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Text pattern<br /></li><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Name</p> 1 0 0 0 - 1 - 0 + 1 character_001 + 0 + 0 + 0 + + 1 PATTERN_FREE 0 - + + <ul><li>not mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to match the pattern.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to match the pattern.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number</p> 1 0 0 0 - 2 - 0 + 1 character_002 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + + <ul><li>not mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be an email address.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be an email address.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Enter your email address</p> 1 0 0 0 - 3 - 0 + 1 character_003 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + + <ul><li>not mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be a web page URL.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be a web page URL.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site</p> 1 0 0 0 - 4 - 0 + 1 character_004 + 0 + 0 + 0 + + 1 PATTERN_URL 0 - + + <ul><li>mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text.</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text.</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Name</p> 1 1 0 0 - 5 - 0 + 1 character_005 + 0 + 0 + 0 + + 1 PATTERN_FREE 0 - + + <ul><li>mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text matching the defined pattern.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text matching the defined pattern.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number</p> 1 1 0 0 - 6 - 0 + 1 character_006 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + + <ul><li>mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a an email address.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a an email address.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Enter your email address</p> 1 1 0 0 - 7 - 0 + 1 character_007 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + + <ul><li>mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a web page URL.</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a web page URL.</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site</p> 1 1 0 0 - 8 - 0 + 1 character_008 + 0 + 0 + 0 + + 1 PATTERN_URL 0 diff --git a/field/character/version.php b/field/character/version.php index 0fd725e4662..10408e78b17 100644 --- a/field/character/version.php +++ b/field/character/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024020700; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_character'; // Full name of the plugin (used for diagnostics). diff --git a/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php b/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php index 28c3c57c104..7acc78543e2 100644 --- a/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php +++ b/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php @@ -40,10 +40,9 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'checkbox'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugincheckbox = new backup_nested_element('surveyprofield_checkbox', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'options', 'labelother', 'defaultvalue', 'noanswerdefault', 'downloadformat', - 'minimumrequired', 'maximumrequired', 'adjustment', ]); + 'minimumrequired', 'maximumrequired', 'adjustment', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/checkbox/classes/item.php b/field/checkbox/classes/item.php index e167cbbe6e9..d3814a2f633 100644 --- a/field/checkbox/classes/item.php +++ b/field/checkbox/classes/item.php @@ -41,68 +41,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - * - * Take in mind that "required" (for checkbox item) means only: "The 'No answer' checkbox is not displayed". - * Each checkbox element is intrinsically required. - * There is noy for a student to jump a standard checkbox element. - * - * Example: "What do you take for breakfast?" milk, bread, jam. - * If the user jumps this element HE/SHE IS STATING THAT HE/SHE DOES NOT TAKE milk AND NOT bread AND NOT jam. - * - * If the editing teacher choose to allow the student to jump this question, he HAS TO leave unchecked the "required" propery. - * In that way the element will be equipped with an additional exclusive "No answer" checkbox. - * This last checkbox privides to the student the possibility to say "I don't tell you what I take for breakfast!" - * - * Note that a checkbox can have $minimumrequired irrespectively of being required or no. - * Alias: a checkbox element can be not $required and have, at the same time, $minimumrequired > 0. - * This is perfectly valid. - * - * Example: "What do you take for breakfast?" milk, bread, jam. - * With: $required = 0 and $minimumrequired = 2 - * - * This means that the student is allowed to select the exclusive "No answer" checkbox and run away BUT - * IF he/she decides to provide an answer THEN he/she has to select at least 2 checkboxes. - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -115,7 +54,7 @@ class item extends itembase { protected $labelother; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -144,6 +83,13 @@ class item extends itembase { */ protected $adjustment; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -176,7 +122,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -208,18 +156,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim trailing spaces from each textarea field. $fieldlist = ['options', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -232,16 +176,12 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Checkbox'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'checkbox_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; $record->noanswerdefault = 0; + // $record->labelother + // $record->defaultvalue + // $record->noanswerdefault $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->minimumrequired = 0; $record->adjustment = 0; @@ -253,7 +193,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -289,7 +229,7 @@ public function item_list_constraints() { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $constraints = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_checkbox'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -303,15 +243,160 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set noanswerdefault. + * + * @param string $noanswerdefault + * @return void + */ + public function set_noanswerdefault($noanswerdefault) { + $this->noanswerdefault = $noanswerdefault; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set minimumrequired. + * + * @param string $minimumrequired + * @return void + */ + public function set_minimumrequired($minimumrequired) { + $this->minimumrequired = $minimumrequired; + } + + /** + * Set maximumrequired. + * + * @param string $maximumrequired + * @return void + */ + public function set_maximumrequired($maximumrequired) { + $this->maximumrequired = $maximumrequired; + } + + /** + * Set adjustment. + * + * @param string $adjustment + * @return void + */ + public function set_adjustment($adjustment) { + $this->adjustment = $adjustment; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. + * + * @return $this->labelother + */ + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get noanswerdefault. + * + * @return $this->noanswerdefault + */ + public function get_noanswerdefault() { + return $this->noanswerdefault; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get minimumrequired. + * + * @return $this->minimumrequired + */ + public function get_minimumrequired() { + return $this->minimumrequired; + } + + /** + * Get maximumrequired. + * + * @return $this->maximumrequired + */ + public function get_maximumrequired() { + return $this->maximumrequired; + } + + /** + * Get adjustment. * - * @return the content of the static property "canbeparent" + * @return $this->adjustment */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_adjustment() { + return $this->adjustment; } /** @@ -329,6 +414,24 @@ public function get_downloadformats() { return $options; } + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } + /** * Get the format recognized (without any really good reason) as friendly. * @@ -338,14 +441,30 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'options', 'labelother', 'defaultvalue', 'noanswerdefault', + 'downloadformat', 'minimumrequired', 'maximumrequired', 'adjustment', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_checkbox'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -371,33 +490,14 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + - + @@ -418,7 +518,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = array_fill(0, count($values), 0); $labels = []; @@ -456,7 +556,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { * return string $childparentcontent */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -505,7 +605,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $expectedcount = count($values); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -541,27 +641,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_checkbox_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_checkbox_'.$this->sortindex; + $basename = $this->itemname; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $utilityitemman = new utility_item($this->cm, $this->surveypro); $defaults = $utilityitemman->multilinetext_to_array($this->defaultvalue); - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' checkbox_check'; $attributes['group'] = 1; $options = ['0', '1']; - $elementgroup = []; $i = 0; foreach ($labels as $label) { - $itemname = $this->itemname.'_'.$i; - $attributes['id'] = $idprefix.'_'.$i; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $itemname, '', $label, $attributes, $options); - - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'checkbox_check'; - } + $itemname = $basename.'_'.$i; + $attributes['id'] = $baseid.'_'.$i; + $elementgroup[] = $mform->createElement('advcheckbox', $itemname, '', $label, $attributes, $options); if (!$searchform) { if (in_array($label, $defaults)) { @@ -573,34 +670,30 @@ public function userform_mform_element($mform, $searchform, $readonly) { if (!empty($this->labelother)) { [$othervalue, $otherlabel] = $this->get_other(); - $itemname = $this->itemname.'_other'; - $attributes['id'] = $idprefix.'_other'; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $itemname, '', $otherlabel, $attributes, $options); + $attributes['id'] = $baseid.'_other'; + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_other', '', $otherlabel, $attributes, $options); unset($attributes['group']); - $attributes['id'] = $idprefix.'_text'; - $attributes['class'] = 'checkbox_check'; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); + $attributes['id'] = $baseid.'_text'; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); if (!$searchform) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); if (in_array($otherlabel, $defaults)) { - $mform->setDefault($this->itemname.'_other', '1'); + $mform->setDefault($basename.'_other', '1'); } } - $mform->disabledIf($this->itemname.'_text', $this->itemname.'_other', 'notchecked'); + $mform->disabledIf($basename.'_text', $basename.'_other', 'notchecked'); } if (!$this->required) { - $elementtype = 'mod_surveypro_advcheckbox'; - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'surveypro'); $options = ['0', '1']; - $elementgroup[] = $mform->createElement($elementtype, $itemname, '', $noanswerstr, $attributes, $options); + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_noanswer', '', $noanswerstr, $attributes, $options); if (!empty($this->noanswerdefault)) { - $mform->setDefault($itemname, '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } @@ -609,20 +702,23 @@ public function userform_mform_element($mform, $searchform, $readonly) { } else { // SURVEYPRO_HORIZONTAL. $separator = ' '; } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); if (!$this->required) { - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } if ($searchform) { - $itemname = $this->itemname.'_ignoreme'; $this->item_add_color_unifier($mform); - $attributes['id'] = $idprefix.'_ignoreme'; - $mform->addElement('mod_surveypro_checkbox', $itemname, '', get_string('star', 'mod_surveypro'), $attributes); + + $elementgroup = []; + $itemname = $basename.'_ignoreme'; + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $itemname, '', get_string('star', 'mod_surveypro'), $attributes); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); $mform->setDefault($itemname, '1'); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); + $mform->disabledIf($basename.'_group', $itemname, 'checked'); } if (!$searchform) { @@ -631,7 +727,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } @@ -648,7 +744,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { * @return array $separator */ public function userform_get_separator(): array { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $optioncount = count($labels); $addother = !empty($this->labelother); $mandatory = $this->required; @@ -664,16 +760,15 @@ public function userform_get_separator(): array { if ($addother) { $separator[] = '
'; // From "Option N" to "Other". $separator[] = ' '; // From "Other" to the corresponding "text field". - if (!$mandatory) { - $separator[] = '
'; // From the "text field" to "No answer". - } - } else { - if (!$mandatory) { - $separator[] = '
'; // From Option N to "No answer". - } } - array_shift($separator); // Bloody workaround: drop first break. + if (!$mandatory) { + $separator[] = '
'; // From "Option N" or "text field" to "No answer". + } + + if (count($separator) > 1) { + array_shift($separator); // Bloody workaround: drop first break. + } return $separator; } @@ -688,10 +783,10 @@ public function userform_get_separator(): array { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (isset($data[$this->itemname.'_noanswer']) && ($data[$this->itemname.'_noanswer'] == 1) ) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -699,12 +794,12 @@ public function userform_mform_validation($data, &$errors, $searchform) { if (!empty($this->labelother)) { if (($data[$this->itemname.'_other']) && empty($data[$this->itemname.'_text']) ) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_checkbox'); - return; + return $errors; } } // Begin of: get answercount. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $answercount = 0; foreach ($labels as $k => $unused) { @@ -736,6 +831,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum_more', 'surveyprofield_checkbox', $this->maximumrequired); } } + + return $errors; } /** @@ -1013,7 +1110,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); foreach ($values as $k => $value) { if ($answers[$k] == 1) { @@ -1036,7 +1133,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($values as $k => $value) { if ($answers[$k] == 1) { @@ -1075,8 +1172,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/checkbox/db/install.xml b/field/checkbox/db/install.xml index e0027681b44..ae940f24199 100644 --- a/field/checkbox/db/install.xml +++ b/field/checkbox/db/install.xml @@ -1,37 +1,21 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/field/checkbox/db/upgrade.php b/field/checkbox/db/upgrade.php index 4f47fa13428..5da0eda1a91 100644 --- a/field/checkbox/db/upgrade.php +++ b/field/checkbox/db/upgrade.php @@ -144,5 +144,66 @@ function xmldb_surveyprofield_checkbox_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2023111401, 'surveyprofield', 'checkbox'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_checkbox. + $table = new xmldb_table('surveyprofield_checkbox'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_checkbox} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Checkbox savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'checkbox'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_checkbox'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_checkbox. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_checkbox} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Checkbox savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'checkbox'); + } + return true; } diff --git a/field/checkbox/lang/en/surveyprofield_checkbox.php b/field/checkbox/lang/en/surveyprofield_checkbox.php index 840ad4f58d4..bd3af947ae8 100644 --- a/field/checkbox/lang/en/surveyprofield_checkbox.php +++ b/field/checkbox/lang/en/surveyprofield_checkbox.php @@ -23,13 +23,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['adjustment'] = 'Adjustment'; +$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['allowed'] = 'allowed'; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default.'; $string['defaultvalue'] = 'Default'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['horizontal'] = 'horizontal'; $string['ierr_defaultsduplicated'] = 'Defaults must be different each other'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; @@ -39,19 +39,20 @@ $string['ierr_minimumrequired'] = 'The minimum number of checkboxes to select must be lower than {$a}'; $string['ierr_optionswithseparator'] = 'Options can not contain "{$a}"'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; -$string['maximumrequired_help'] = 'The maximum number of checkboxes the user can choose in his/her answer'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['maximumrequired'] = 'Maximum allowed options'; -$string['minimumrequired_help'] = 'The minimum number of checkboxes the user is forced to choose in his/her answer'; +$string['maximumrequired_help'] = 'The maximum number of checkboxes the user can choose in his/her answer'; $string['minimumrequired'] = 'Minimum required options'; -$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; +$string['minimumrequired_help'] = 'The minimum number of checkboxes the user is forced to choose in his/her answer'; $string['noanswerdefault'] = '"No answer" as defaults'; +$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding checkbox, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding checkbox, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[One
label
per
line]'; $string['pluginname'] = 'Checkbox'; +$string['privacy:metadata'] = 'The "Checkbox" field plugin does not store any personal data.'; $string['restrictions_maximumrequired_more'] = 'No more than {$a} checkboxes are allowed'; $string['restrictions_maximumrequired_one'] = 'No more than 1 checkbox is allowed'; $string['restrictions_minimumrequired_more'] = 'At least {$a} checkboxes have to be selected'; @@ -66,4 +67,3 @@ $string['uerr_missingothertext'] = 'Please add the text required by your selection'; $string['userfriendlypluginname'] = 'Checkbox'; $string['vertical'] = 'vertical'; -$string['privacy:metadata'] = 'The "Checkbox" field plugin does not store any personal data.'; diff --git a/field/checkbox/mform/advcheckbox.php b/field/checkbox/mform/advcheckbox.php deleted file mode 100644 index bc45fd78af6..00000000000 --- a/field/checkbox/mform/advcheckbox.php +++ /dev/null @@ -1,77 +0,0 @@ -. - -/** - * advcheckbox mform element - * - * Extends the core mform class for advcheckbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/advcheckbox.php'); - -// @codingStandardsIgnoreFile - -/** - * advcheckbox mform element - * - * Extends the core mform class for advcheckbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_advcheckbox extends \MoodleQuickForm_advcheckbox { - - /** - * Class constructor. - * - * @param string $elementName Optional name of the checkbox - * @param string $elementLabel Optional checkbox label - * @param string $text Optional text to put after the checkbox - * @param mixed $attributes optional either a typical HTML attribute string - * or an associative array - * @param mixed $options Optional values to pass if checked or not checked - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $text, $attributes, $options); - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/checkbox/mform/checkbox.php b/field/checkbox/mform/checkbox.php deleted file mode 100644 index 30486698c56..00000000000 --- a/field/checkbox/mform/checkbox.php +++ /dev/null @@ -1,76 +0,0 @@ -. - -/** - * checkbox mform element - * - * Extends the core mform class for checkbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/checkbox.php'); - -// @codingStandardsIgnoreFile - -/** - * checkbox mform element - * - * Extends the core mform class for checkbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_checkbox extends \MoodleQuickForm_checkbox { - - /** - * Constructor. - * - * @param string $elementName Optional name of the checkbox - * @param string $elementLabel Optional checkbox label - * @param string $text Optional text to put after the checkbox - * @param mixed $attributes Optional either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $text, $attributes); - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/checkbox/tests/behat/itemform.feature b/field/checkbox/tests/behat/itemform.feature index 63f783f9204..1ea3bd4fc8b 100644 --- a/field/checkbox/tests/behat/itemform.feature +++ b/field/checkbox/tests/behat/itemform.feature @@ -91,10 +91,10 @@ Feature: Create a checkbox item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a What do you usually get for breakfast?" - Then the field "id_surveypro_field_checkbox_2_0" matches value "0" - Then the field "id_surveypro_field_checkbox_2_1" matches value "1" - Then the field "id_surveypro_field_checkbox_2_2" matches value "0" - Then the field "id_surveypro_field_checkbox_2_3" matches value "1" - Then the field "id_surveypro_field_checkbox_2_other" matches value "1" - Then the field "id_surveypro_field_checkbox_2_text" matches value "specify" + Then the field "id_field_checkbox_2_0" matches value "0" + Then the field "id_field_checkbox_2_1" matches value "1" + Then the field "id_field_checkbox_2_2" matches value "0" + Then the field "id_field_checkbox_2_3" matches value "1" + Then the field "id_field_checkbox_2_other" matches value "1" + Then the field "id_field_checkbox_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/checkbox/tests/behat/settings_configuration_01.feature b/field/checkbox/tests/behat/settings_configuration_01.feature index 7905defa236..01c991da982 100644 --- a/field/checkbox/tests/behat/settings_configuration_01.feature +++ b/field/checkbox/tests/behat/settings_configuration_01.feature @@ -57,8 +57,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -67,8 +67,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions @@ -99,10 +99,10 @@ Feature: Submit using checkbox item and check form validation (1 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -112,8 +112,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -123,8 +123,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_02.feature b/field/checkbox/tests/behat/settings_configuration_02.feature index 7077103792c..f24263dc65a 100644 --- a/field/checkbox/tests/behat/settings_configuration_02.feature +++ b/field/checkbox/tests/behat/settings_configuration_02.feature @@ -57,8 +57,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -67,8 +67,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions @@ -99,7 +99,7 @@ Feature: Submit using checkbox item and check form validation (2 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -109,8 +109,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -119,7 +119,7 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 6: Student chooses "No answer" And I press "New response" Then I should see "At least 2 checkboxes have to be selected" - And I set the field "id_surveypro_field_checkbox_1_noanswer" to "1" + And I set the field "id_field_checkbox_1_noanswer" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_03.feature b/field/checkbox/tests/behat/settings_configuration_03.feature index 029e00191af..a39e6a45954 100644 --- a/field/checkbox/tests/behat/settings_configuration_03.feature +++ b/field/checkbox/tests/behat/settings_configuration_03.feature @@ -58,8 +58,8 @@ Feature: Submit using checkbox item and check form validation (3 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -91,10 +91,10 @@ Feature: Submit using checkbox item and check form validation (3 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_1" to "1" + And I set the field "id_field_checkbox_1_1" to "1" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_2" to "1" + And I set the field "id_field_checkbox_1_2" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -104,8 +104,8 @@ Feature: Submit using checkbox item and check form validation (3 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_04.feature b/field/checkbox/tests/behat/settings_configuration_04.feature index 5c51c9d35d2..fdc719f7401 100644 --- a/field/checkbox/tests/behat/settings_configuration_04.feature +++ b/field/checkbox/tests/behat/settings_configuration_04.feature @@ -58,8 +58,8 @@ Feature: Submit using checkbox item and check form validation (4 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -91,7 +91,7 @@ Feature: Submit using checkbox item and check form validation (4 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,7 +100,7 @@ Feature: Submit using checkbox item and check form validation (4 of 4) # Test number 4: Student submits a standard answer And I press "New response" Then I should see "At least 2 checkboxes have to be selected" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_05.feature b/field/checkbox/tests/behat/settings_configuration_05.feature index 5e2fa3f8476..71b07c38cf0 100644 --- a/field/checkbox/tests/behat/settings_configuration_05.feature +++ b/field/checkbox/tests/behat/settings_configuration_05.feature @@ -40,8 +40,8 @@ Feature: Submit using checkbox item and check form validation And I press "New response" Then I should not see "No more than" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -62,13 +62,13 @@ Feature: Submit using checkbox item and check form validation # Test number 2: Student ticks too many checkboxes And I press "New response" Then I should see "No more than 3 checkboxes are allowed" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" - And I set the field "id_surveypro_field_checkbox_1_1" to "1" - And I set the field "id_surveypro_field_checkbox_1_2" to "1" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_1" to "1" + And I set the field "id_field_checkbox_1_2" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" Then I should see "Please tick no more than 3 options" - And I set the field "id_surveypro_field_checkbox_1_1" to "0" + And I set the field "id_field_checkbox_1_1" to "0" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -77,7 +77,7 @@ Feature: Submit using checkbox item and check form validation # Test number 3: Student submits a standard answer And I press "New response" Then I should see "No more than 3 checkboxes are allowed" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml b/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml similarity index 93% rename from field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml rename to field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml index 2670b5e66e8..de1b71eaf44 100644 --- a/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml +++ b/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>CHECKBOX</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>checkbox specific setting</b>:</p><ol><li>Options</li><li>"Option other"</li><li>Default</li><li>"No answer" as defaults</li><li>Adjustment</li><li>Minimum required options</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>CHECKBOX</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>checkbox specific setting</b>:</p><ol><li>Options</li><li>"Option other"</li><li>Default</li><li>"No answer" as defaults</li><li>Adjustment</li><li>Minimum required options</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -42,6 +37,11 @@ 1 0 checkbox_001 + 0 + 0 + 0 + + milk coffee butter @@ -54,27 +54,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -83,6 +78,11 @@ bread 2 0 checkbox_002 + 0 + 0 + 0 + + milk coffee butter @@ -95,27 +95,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.<br /> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.<br /> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -124,6 +119,11 @@ bread 3 0 checkbox_003 + 0 + 0 + 0 + + milk coffee butter @@ -136,28 +136,23 @@ bread 1 - + - 0 - 0 - 0 - - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.</p> 1 0 4 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 1 @@ -166,6 +161,11 @@ required options is set to 2. So he/she is forced to or select al least two chec 4 0 checkbox_004 + 0 + 0 + 0 + + milk coffee butter @@ -178,27 +178,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -207,6 +202,11 @@ bread 5 0 checkbox_005 + 0 + 0 + 0 + + milk coffee butter @@ -218,27 +218,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -247,6 +242,11 @@ bread 6 0 checkbox_006 + 0 + 0 + 0 + + milk coffee butter @@ -258,27 +258,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -287,6 +282,11 @@ bread 7 0 checkbox_007 + 0 + 0 + 0 + + milk coffee butter @@ -298,27 +298,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -327,6 +322,11 @@ bread 8 0 checkbox_008 + 0 + 0 + 0 + + milk coffee butter @@ -338,27 +338,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -367,6 +362,11 @@ bread 9 0 checkbox_009 + 0 + 0 + 0 + + milk coffee butter @@ -379,27 +379,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -408,6 +403,11 @@ bread 10 0 checkbox_010 + 0 + 0 + 0 + + milk coffee butter @@ -420,13 +420,8 @@ bread 0 - + - 0 - 0 - 0 - - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two @@ -434,16 +429,16 @@ options or to tick the "No answer" checkbox.</p> 1 0 11 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 0 @@ -452,6 +447,11 @@ options or to tick the "No answer" checkbox.</p> 11 0 checkbox_011 + 0 + 0 + 0 + + milk coffee butter @@ -464,27 +464,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -493,6 +488,11 @@ bread 12 0 checkbox_013 + 0 + 0 + 0 + + milk coffee butter @@ -505,27 +505,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -534,6 +529,11 @@ bread 13 0 checkbox_012 + 0 + 0 + 0 + + milk coffee butter @@ -546,27 +546,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to an invalid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 14 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to an invalid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 14 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -575,6 +570,11 @@ bread 14 0 checkbox_014 + 0 + 0 + 0 + + milk coffee butter @@ -587,27 +587,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value <span class="rangySelectionBoundary" style="line-height:0;"></span>so the user can "fly" over this element leaving the proposed default untouched (and the question not read).<br /> + 1 + 0 + 15 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value <span class="rangySelectionBoundary" style="line-height:0;"></span>so the user can "fly" over this element leaving the proposed default untouched (and the question not read).<br /> - 1 - 0 - 15 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -616,6 +611,11 @@ bread 15 0 checkbox_015 + 0 + 0 + 0 + + milk coffee butter @@ -628,28 +628,23 @@ bread 1 - + - 0 - 0 - 0 - - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> 1 0 16 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 0 @@ -658,6 +653,11 @@ options or to tick the "No answer" checkbox.</p> 16 0 checkbox_016 + 0 + 0 + 0 + + milk coffee butter @@ -670,27 +670,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> + 1 + 0 + 17 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> - 1 - 0 - 17 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -699,6 +694,11 @@ bread 17 0 checkbox_017 + 0 + 0 + 0 + + milk coffee butter @@ -710,27 +710,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> + 1 + 0 + 18 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> - 1 - 0 - 18 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -739,6 +734,11 @@ bread 18 0 checkbox_018 + 0 + 0 + 0 + + milk coffee butter @@ -750,27 +750,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" chackbox.</p> + 1 + 0 + 19 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" chackbox.</p> - 1 - 0 - 19 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -779,6 +774,11 @@ bread 19 0 checkbox_019 + 0 + 0 + 0 + + milk coffee butter @@ -790,27 +790,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" checkbox.</p> + 1 + 0 + 20 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" checkbox.</p> - 1 - 0 - 20 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -819,6 +814,11 @@ bread 20 0 checkbox_020 + 0 + 0 + 0 + + milk coffee butter diff --git a/field/checkbox/version.php b/field/checkbox/version.php index edec4f389b7..de38867efca 100644 --- a/field/checkbox/version.php +++ b/field/checkbox/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023111401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_checkbox'; // Full name of the plugin (used for diagnostics). diff --git a/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php b/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php index 9ab1acb14cd..df5f8bcbb30 100644 --- a/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php +++ b/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'date'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugindate = new backup_nested_element('surveyprofield_date', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/date/classes/item.php b/field/date/classes/item.php index a05029b53b8..9ee18e4b441 100644 --- a/field/date/classes/item.php +++ b/field/date/classes/item.php @@ -40,67 +40,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var string Format of the content once downloaded */ - protected $variable; + protected $downloadformat; /** - * @var int Indent of the item in the form page + * @var int Defaultvalue for the item answer */ - protected $indent; + protected $defaultvalue; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the date in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Upperbound for the date in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the date in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Year of the defaultvalue for the date in unixtime @@ -117,11 +84,6 @@ class item extends itembase { */ protected $defaultvalueday; - /** - * @var int Lowerbound for the date in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the date in unixtime */ @@ -137,11 +99,6 @@ class item extends itembase { */ protected $lowerboundday; - /** - * @var int Upperbound for the date in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the date in unixtime */ @@ -157,6 +114,11 @@ class item extends itembase { */ protected $upperboundday; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -193,7 +155,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_date_to_unix_time($this->surveypro->stopyear, 12, 31); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -225,28 +189,15 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } - /** - * Is this item available as a parent? - * - * @return the content of the static property "canbeparent" - */ - public static function get_canbeparent() { - return self::$canbeparent; - } - /** * Item add mandatory plugin fields * Copy mandatory fields to $record @@ -254,14 +205,7 @@ public static function get_canbeparent() { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date [dd/mm/yyyy]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'date_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 43200; $record->downloadformat = 'strftime05'; @@ -278,7 +222,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_date_to_unix_time($year, $month, $day) { - return (mktime(12, 0, 0, $month, $day, $year)); + return (gmmktime(12, 0, 0, $month, $day, $year)); } /** @@ -328,7 +272,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -355,8 +299,276 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + // MARK get. + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; + } + /** * Get the list of composite fields. * @@ -393,14 +605,31 @@ public function get_friendlyformat() { return 'strftime05'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'defaultvalueday', 'lowerboundyear', + 'lowerboundmonth', 'lowerboundday', 'upperboundyear', 'upperboundmonth', 'upperboundday', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_date'] = []; return $fieldlist; } @@ -417,30 +646,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -474,8 +684,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_date_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -513,66 +721,58 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - $attributes = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_date_'.$this->sortindex; $elementgroup = []; + $attributes = []; + $basename = $this->itemname; - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' date_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'date_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + $mform->setType($basename, PARAM_RAW); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'date_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + $mform->setType($basename, PARAM_RAW); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -586,7 +786,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $datearray['year'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -623,13 +823,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $datearray['mday']); - $mform->setDefault($this->itemname.'_month', $datearray['mon']); - $mform->setDefault($this->itemname.'_year', $datearray['year']); + $mform->setDefault($basename.'_day', $datearray['mday']); + $mform->setDefault($basename.'_month', $datearray['mon']); + $mform->setDefault($basename.'_year', $datearray['year']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -693,12 +893,12 @@ public function userform_mform_validation($data, &$errors, $searchform) { if (!utility_item::date_is_valid($userday, $usermonth, $useryear)) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_date_to_unix_time($this->surveypro->startyear, 1, 1)); @@ -719,6 +919,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_date'); } } + + return $errors; } /** @@ -866,8 +1068,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/date/db/install.xml b/field/date/db/install.xml index fce59831c68..4ad6c7df1dc 100644 --- a/field/date/db/install.xml +++ b/field/date/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/date/db/upgrade.php b/field/date/db/upgrade.php index 949c9ac37d3..6265f2a464e 100644 --- a/field/date/db/upgrade.php +++ b/field/date/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_date_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Date savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'date'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_date. + $table = new xmldb_table('surveyprofield_date'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_date} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Date savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'date'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_date'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_date. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_date} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Date savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'date'); + } + return true; } diff --git a/field/date/lang/en/surveyprofield_date.php b/field/date/lang/en/surveyprofield_date.php index a5de32ebe80..7f123739482 100644 --- a/field/date/lang/en/surveyprofield_date.php +++ b/field/date/lang/en/surveyprofield_date.php @@ -25,19 +25,20 @@ $string['currentdatedefault'] = 'Current date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the date the remote user will find answered by default. The default for this type of question is mandatory. If "Current date" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the date the remote user will find answered by default. The default for this type of question is mandatory. If "Current date" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['inviteday'] = 'Choose a day'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['pluginname'] = 'Date'; +$string['privacy:metadata'] = 'The "Date" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -56,7 +57,6 @@ $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date [dd/mm/yyyy]'; -$string['privacy:metadata'] = 'The "Date" field plugin does not store any personal data.'; diff --git a/field/date/tests/behat/itemform.feature b/field/date/tests/behat/itemform.feature index b932043ddd3..f9d80718193 100644 --- a/field/date/tests/behat/itemform.feature +++ b/field/date/tests/behat/itemform.feature @@ -112,7 +112,7 @@ Feature: Create a date item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When were you born?" - Then the field "id_surveypro_field_date_2_day" matches value "1" - Then the field "id_surveypro_field_date_2_month" matches value "January" - Then the field "id_surveypro_field_date_2_year" matches value "1980" + Then the field "id_field_date_2_day" matches value "1" + Then the field "id_field_date_2_month" matches value "January" + Then the field "id_field_date_2_year" matches value "1980" Then I should see "Additional note" diff --git a/field/date/tests/behat/submit_date.feature b/field/date/tests/behat/submit_date.feature index 05dc972463a..644a1ca7874 100644 --- a/field/date/tests/behat/submit_date.feature +++ b/field/date/tests/behat/submit_date.feature @@ -43,9 +43,9 @@ Feature: Submit using a date item # student1 submits And I set the following fields to these values: - | id_surveypro_field_date_1_day | 16 | - | id_surveypro_field_date_1_month | October | - | id_surveypro_field_date_1_year | 1988 | + | id_field_date_1_day | 16 | + | id_field_date_1_month | October | + | id_field_date_1_year | 1988 | And I press "Submit" diff --git a/field/date/tests/fixtures/usertemplate/date_only_2023103100.xml b/field/date/tests/fixtures/usertemplate/date_only_2024032800.xml similarity index 91% rename from field/date/tests/fixtures/usertemplate/date_only_2023103100.xml rename to field/date/tests/fixtures/usertemplate/date_only_2024032800.xml index 7fcd9490203..13e0f5b7a19 100644 --- a/field/date/tests/fixtures/usertemplate/date_only_2023103100.xml +++ b/field/date/tests/fixtures/usertemplate/date_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -42,6 +37,11 @@ 1 0 date_001 + 0 + 0 + 0 + + 2 39600 strftime09 @@ -49,28 +49,23 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - - When did you get your degree? + <p>When did you get your degree?</p> 1 0 0 @@ -78,35 +73,35 @@ 2 0 date_002 + 0 + 0 + 0 + + 1 - 1420110000 + 1420023600 strftime09 1414839600 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - - When did you get your degree? + <p>When did you get your degree?</p> 1 0 0 @@ -114,6 +109,11 @@ 3 0 date_003 + 0 + 0 + 0 + + 4 39600 strftime09 @@ -121,27 +121,22 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -150,6 +145,11 @@ 4 0 date_004 + 0 + 0 + 0 + + 5 39600 strftime09 @@ -157,27 +157,22 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -186,6 +181,11 @@ 5 0 date_005 + 0 + 0 + 0 + + 3 39600 strftime09 @@ -193,27 +193,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -222,6 +217,11 @@ 6 0 date_006 + 0 + 0 + 0 + + 2 39600 strftime09 @@ -229,27 +229,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -258,34 +253,34 @@ 7 0 date_007 + 0 + 0 + 0 + + 1 - 1420110000 + 31489200 strftime09 1414839600 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -294,6 +289,11 @@ 8 0 date_008 + 0 + 0 + 0 + + 4 39600 strftime09 @@ -301,27 +301,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -330,6 +325,11 @@ 9 0 date_009 + 0 + 0 + 0 + + 5 39600 strftime09 diff --git a/field/date/version.php b/field/date/version.php index c549b7b54b7..ff766dd14d2 100644 --- a/field/date/version.php +++ b/field/date/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_date'; // Full name of the plugin (used for diagnostics). diff --git a/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php b/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php index 71ad0f6c81a..4eff204d942 100644 --- a/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php +++ b/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'datetime'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugindatetime = new backup_nested_element('surveyprofield_datetime', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/datetime/classes/item.php b/field/datetime/classes/item.php index 37c4a8e7d2f..a229302423f 100644 --- a/field/datetime/classes/item.php +++ b/field/datetime/classes/item.php @@ -40,52 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Step for minutes drop down menu @@ -103,10 +58,22 @@ class item extends itembase { protected $downloadformat; /** - * @var int Defaultvalue for the datetime in unixtime + * @var int Defaultvalue for the item answer */ protected $defaultvalue; + /** + * @var int Lowerbound for the datetime in unixtime + */ + protected $lowerbound; + + /** + * @var int Upperbound for the datetime in unixtime + */ + protected $upperbound; + + // Service variables. + /** * @var int Year of the defaultvalue for the datetime in unixtime */ @@ -132,11 +99,6 @@ class item extends itembase { */ protected $defaultvalueminute; - /** - * @var int Lowerbound for the datetime in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the datetime in unixtime */ @@ -162,11 +124,6 @@ class item extends itembase { */ protected $lowerboundminute; - /** - * @var int Upperbound for the datetime in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the datetime in unixtime */ @@ -192,6 +149,11 @@ class item extends itembase { */ protected $upperboundminute; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -228,7 +190,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_datetime_to_unix_time($this->surveypro->stopyear, 12, 31, 23, 59); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -260,14 +224,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -280,14 +240,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date and time [dd/mm/yyyy;hh:mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'datetime_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->step = 1; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; @@ -307,7 +260,9 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_datetime_to_unix_time($year, $month, $day, $hour, $minute) { - return (mktime($hour, $minute, 0, $month, $day, $year)); + $unixtime = gmmktime($hour, $minute, 0, $month, $day, $year); + + return $unixtime; } /** @@ -360,7 +315,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -392,15 +347,407 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set step. + * + * @param string $step + * @return void + */ + public function set_step($step) { + $this->step = $step; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set defaultvaluehour. + * + * @param string $defaultvaluehour + * @return void + */ + public function set_defaultvaluehour($defaultvaluehour) { + $this->defaultvaluehour = $defaultvaluehour; + } + + /** + * Set defaultvalueminute. + * + * @param string $defaultvalueminute + * @return void + */ + public function set_defaultvalueminute($defaultvalueminute) { + $this->defaultvalueminute = $defaultvalueminute; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set lowerboundhour. + * + * @param string $lowerboundhour + * @return void + */ + public function set_lowerboundhour($lowerboundhour) { + $this->lowerboundhour = $lowerboundhour; + } + + /** + * Set lowerboundminute. + * + * @param string $lowerboundminute + * @return void + */ + public function set_lowerboundminute($lowerboundminute) { + $this->lowerboundminute = $lowerboundminute; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + + /** + * Set upperboundhour. + * + * @param string $upperboundhour + * @return void + */ + public function set_upperboundhour($upperboundhour) { + $this->upperboundhour = $upperboundhour; + } + + /** + * Set upperboundminute. + * + * @param string $upperboundminute + * @return void + */ + public function set_upperboundminute($upperboundminute) { + $this->upperboundminute = $upperboundminute; + } + // MARK get. /** - * Is this item available as a parent? + * Get step. + * + * @return $this->step + */ + public function get_step() { + return $this->step; + } + + /** + * Get defaultoption. * - * @return the content of the static property "canbeparent" + * @return $this->defaultoption */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get defaultvaluehour. + * + * @return $this->defaultvaluehour + */ + public function get_defaultvaluehour() { + return $this->defaultvaluehour; + } + + /** + * Get defaultvalueminute. + * + * @return $this->defaultvalueminute + */ + public function get_defaultvalueminute() { + return $this->defaultvalueminute; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get lowerboundhour. + * + * @return $this->lowerboundhour + */ + public function get_lowerboundhour() { + return $this->lowerboundhour; + } + + /** + * Get lowerboundminute. + * + * @return $this->lowerboundminute + */ + public function get_lowerboundminute() { + return $this->lowerboundminute; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; + } + + /** + * Get upperboundhour. + * + * @return $this->upperboundhour + */ + public function get_upperboundhour() { + return $this->upperboundhour; + } + + /** + * Get upperboundminute. + * + * @return $this->upperboundminute + */ + public function get_upperboundminute() { + return $this->upperboundminute; } /** @@ -439,14 +786,32 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'defaultvalueday', 'defaultvaluehour', 'defaultvalueminute', + 'lowerboundyear', 'lowerboundmonth', 'lowerboundday', 'lowerboundhour', 'lowerboundminute', + 'upperboundyear', 'upperboundmonth', 'upperboundday', 'upperboundhour', 'upperboundminute', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_datetime'] = []; return $fieldlist; } @@ -463,31 +828,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - - + + + @@ -521,8 +867,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_datetime_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -595,28 +939,20 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; - - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' datetime_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); - - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'datetime_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); - - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); - - $itemname = $this->itemname.'_hour'; - $attributes['id'] = $idprefix.'_hour'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $hours, $attributes); - - $itemname = $this->itemname.'_minute'; - $attributes['id'] = $idprefix.'_minute'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $minutes, $attributes); + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_datetime_'.$this->sortindex; + $basename = $this->itemname; + + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); + $attributes['id'] = $baseid.'_hour'; + $elementgroup[] = $mform->createElement('select', $basename.'_hour', '', $hours, $attributes); + $attributes['id'] = $baseid.'_minute'; + $elementgroup[] = $mform->createElement('select', $basename.'_minute', '', $minutes, $attributes); $separator = [' ', ' ']; $nextseparator = \html_writer::tag('div', ',', ['class' => 'datetime_separator_comma']); @@ -626,48 +962,40 @@ public function userform_mform_element($mform, $searchform, $readonly) { if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'datetime_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); $separator[] = ' '; if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -683,7 +1011,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $datetimearray['minutes'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -722,15 +1050,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $datetimearray['mday']); - $mform->setDefault($this->itemname.'_month', $datetimearray['mon']); - $mform->setDefault($this->itemname.'_year', $datetimearray['year']); - $mform->setDefault($this->itemname.'_hour', $datetimearray['hours']); - $mform->setDefault($this->itemname.'_minute', $datetimearray['minutes']); + $mform->setDefault($basename.'_day', $datetimearray['mday']); + $mform->setDefault($basename.'_month', $datetimearray['mon']); + $mform->setDefault($basename.'_year', $datetimearray['year']); + $mform->setDefault($basename.'_hour', $datetimearray['hours']); + $mform->setDefault($basename.'_minute', $datetimearray['minutes']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -749,13 +1077,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -797,18 +1125,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_datetimenotset', 'surveyprofield_datetime', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if (!utility_item::date_is_valid($userday, $usermonth, $useryear)) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_datetime_to_unix_time($this->surveypro->startyear, 1, 1, 0, 0)); @@ -829,6 +1157,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_datetime'); } } + + return $errors; } /** @@ -988,8 +1318,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/datetime/db/install.xml b/field/datetime/db/install.xml index 99c032be40c..7b5488e3cfc 100644 --- a/field/datetime/db/install.xml +++ b/field/datetime/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/datetime/db/upgrade.php b/field/datetime/db/upgrade.php index e3c173d356a..ece59f8e32d 100644 --- a/field/datetime/db/upgrade.php +++ b/field/datetime/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_datetime_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Datetime savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'datetime'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_datetime. + $table = new xmldb_table('surveyprofield_datetime'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_datetime} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Datetime savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'datetime'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_datetime'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_datetime. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_datetime} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Datetime savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'datetime'); + } + return true; } diff --git a/field/datetime/lang/en/surveyprofield_datetime.php b/field/datetime/lang/en/surveyprofield_datetime.php index 5a5a7954dae..8af4b2455cb 100644 --- a/field/datetime/lang/en/surveyprofield_datetime.php +++ b/field/datetime/lang/en/surveyprofield_datetime.php @@ -25,10 +25,10 @@ $string['currentdatetimedefault'] = 'Current date and time'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the date and time the remote user will find answered by default. The default for this type of question is mandatory. If "Current date and time" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the date and time the remote user will find answered by default. The default for this type of question is mandatory. If "Current date and time" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['fifteenminutes'] = 'fifteen minutes'; $string['fiveminutes'] = 'five minutes'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; @@ -39,15 +39,16 @@ $string['inviteminute'] = 'Choose a minute'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date and time the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date and time the user is allowed to enter'; $string['oneminute'] = 'one minute'; $string['pluginname'] = 'Date and time'; +$string['privacy:metadata'] = 'The "Date and time" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; -$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['step'] = 'Step'; +$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['strftime01'] = '%A, %d %B %Y, %H:%M'; $string['strftime02'] = '%A, %d %B %Y, %I:%M %p'; $string['strftime03'] = '%a, %d %b %Y, %H:%M'; @@ -68,7 +69,6 @@ $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest date and time the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date and time the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date and time [dd/mm/yyyy;hh:mm]'; -$string['privacy:metadata'] = 'The "Date and time" field plugin does not store any personal data.'; diff --git a/field/datetime/tests/behat/itemform.feature b/field/datetime/tests/behat/itemform.feature index d04171b14b3..4bf000248c7 100644 --- a/field/datetime/tests/behat/itemform.feature +++ b/field/datetime/tests/behat/itemform.feature @@ -136,9 +136,9 @@ Feature: Create a datetime item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Please, write down date and time of your last flight to Los Angeles." - Then the field "id_surveypro_field_datetime_2_day" matches value "1" - Then the field "id_surveypro_field_datetime_2_month" matches value "January" - Then the field "id_surveypro_field_datetime_2_year" matches value "1980" - Then the field "id_surveypro_field_datetime_2_hour" matches value "0" - Then the field "id_surveypro_field_datetime_2_minute" matches value "0" + Then the field "id_field_datetime_2_day" matches value "1" + Then the field "id_field_datetime_2_month" matches value "January" + Then the field "id_field_datetime_2_year" matches value "1980" + Then the field "id_field_datetime_2_hour" matches value "0" + Then the field "id_field_datetime_2_minute" matches value "0" Then I should see "Additional note" diff --git a/field/datetime/tests/behat/submit_datetime.feature b/field/datetime/tests/behat/submit_datetime.feature index 45ffd8cc0ca..f2982c12a94 100644 --- a/field/datetime/tests/behat/submit_datetime.feature +++ b/field/datetime/tests/behat/submit_datetime.feature @@ -43,11 +43,11 @@ Feature: Submit using a datetime item # student1 submits And I set the following fields to these values: - | id_surveypro_field_datetime_1_day | 23 | - | id_surveypro_field_datetime_1_month | August | - | id_surveypro_field_datetime_1_year | 2010 | - | id_surveypro_field_datetime_1_hour | 17 | - | id_surveypro_field_datetime_1_minute | 35 | + | id_field_datetime_1_day | 23 | + | id_field_datetime_1_month | August | + | id_field_datetime_1_year | 2010 | + | id_field_datetime_1_hour | 17 | + | id_field_datetime_1_minute | 35 | And I press "Submit" diff --git a/field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml b/field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml similarity index 88% rename from field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml rename to field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml index c0fe8b25843..446785b16cf 100644 --- a/field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml +++ b/field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>DATETIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>datetime specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>DATETIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>datetime specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 1 - 0 + 1 datetime_001 + 0 + 0 + 0 + + 1 2 -3600 @@ -50,35 +49,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 2 - 0 + 1 datetime_002 + 0 + 0 + 0 + + 1 1 1442758320 @@ -87,35 +85,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 3 - 0 + 1 datetime_003 + 0 + 0 + 0 + + 1 4 -3600 @@ -124,35 +121,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date and time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date and time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 4 - 0 + 1 datetime_004 + 0 + 0 + 0 + + 1 5 -3600 @@ -161,35 +157,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 5 - 0 + 1 datetime_005 + 0 + 0 + 0 + + 1 3 -3600 @@ -198,35 +193,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 6 - 0 + 1 datetime_006 + 0 + 0 + 0 + + 1 2 -3600 @@ -235,35 +229,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 7 - 0 + 1 datetime_007 + 0 + 0 + 0 + + 1 1 1442758320 @@ -272,35 +265,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 8 - 0 + 1 datetime_008 + 0 + 0 + 0 + + 1 4 -3600 @@ -309,35 +301,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 9 - 0 + 1 datetime_009 + 0 + 0 + 0 + + 1 5 -3600 diff --git a/field/datetime/version.php b/field/datetime/version.php index 7716c4e99de..7ae855ed948 100644 --- a/field/datetime/version.php +++ b/field/datetime/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_datetime'; // Full name of the plugin (used for diagnostics). diff --git a/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php b/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php index 0f73a57b256..c0755eb23f5 100644 --- a/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php +++ b/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php @@ -42,9 +42,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'fileupload'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginfileupload = new backup_nested_element('surveyprofield_fileupload', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'maxfiles', 'maxbytes', 'filetypes', ]); + 'maxfiles', 'maxbytes', 'filetypes', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/fileupload/classes/item.php b/field/fileupload/classes/item.php index 4a38c701b35..debfb67c5a9 100644 --- a/field/fileupload/classes/item.php +++ b/field/fileupload/classes/item.php @@ -39,47 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Maximum number of files allowed to upload @@ -96,6 +56,13 @@ class item extends itembase { */ protected $filetypes; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -128,9 +95,11 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. - $this->insetupform['insearchform'] = false; + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -159,14 +128,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -178,7 +143,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -199,37 +164,94 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Attachment'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'fileupload_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->maxfiles = 1; $record->maxbytes = 1048576; $record->filetypes = '*'; } + // MARK set. + + /** + * Set maxfiles. + * + * @param string $maxfiles + * @return void + */ + public function set_maxfiles($maxfiles) { + $this->maxfiles = $maxfiles; + } + + /** + * Set maxbytes. + * + * @param string $maxbytes + * @return void + */ + public function set_maxbytes($maxbytes) { + $this->maxbytes = $maxbytes; + } + + /** + * Set filetypes. + * + * @param string $filetypes + * @return void + */ + public function set_filetypes($filetypes) { + $this->filetypes = $filetypes; + } + // MARK get. /** - * Is this item available as a parent? + * Get maxfiles. + * + * @return $this->maxfiles + */ + public function get_maxfiles() { + return $this->maxfiles; + } + + /** + * Get maxbytes. * - * @return the content of the static property "canbeparent" + * @return $this->maxbytes */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_maxbytes() { + return $this->maxbytes; + } + + /** + * Get filetypes. + * + * @return $this->filetypes + */ + public function get_filetypes() { + return $this->filetypes; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['maxfiles', 'maxbytes', 'filetypes']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_fileupload'] = []; return $fieldlist; } @@ -246,28 +268,9 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -290,34 +293,69 @@ public static function get_plugin_schema() { public function userform_mform_element($mform, $searchform, $readonly) { // This plugin has $this->insetupform['insearchform'] = false; so it will never be part of a search form. - $fieldname = $this->itemname.'_filemanager'; + $useinline = true; + if (!$useinline) { + $fieldname = $this->itemname.'_filemanager'; + + if ($this->position == SURVEYPRO_POSITIONLEFT) { + $elementlabel = $this->get_contentwithnumber(); + } else { + $elementlabel = ' '; + } + + $idprefix = 'id_surveypro_field_fileupload_'.$this->sortindex; + + $filetypes = array_map('trim', explode(',', $this->filetypes)); - if ($this->position == SURVEYPRO_POSITIONLEFT) { - $elementlabel = $this->get_contentwithnumber(); + $attributes = []; + $attributes['id'] = $idprefix; + $attributes['class'] = 'indent-'.$this->indent.' fileupload_filemanager'; // Does not work: MDL-28194. + $attributes['maxbytes'] = $this->maxbytes; + $attributes['accepted_types'] = $filetypes; + $attributes['subdirs'] = false; + $attributes['maxfiles'] = $this->maxfiles; + $mform->addElement('filemanager', $fieldname, $elementlabel, null, $attributes); + + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $mform->_required[] = $starplace; + } } else { - $elementlabel = ' '; - } + if ($this->position == SURVEYPRO_POSITIONLEFT) { + $elementlabel = $this->get_contentwithnumber(); + } else { + $elementlabel = ' '; + } - $idprefix = 'id_surveypro_field_fileupload_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_fileupload_'.$this->sortindex; + $basename = $this->itemname; - $filetypes = array_map('trim', explode(',', $this->filetypes)); + $filetypes = array_map('trim', explode(',', $this->filetypes)); - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' fileupload_filemanager'; // Does not work: MDL-28194. - $attributes['maxbytes'] = $this->maxbytes; - $attributes['accepted_types'] = $filetypes; - $attributes['subdirs'] = false; - $attributes['maxfiles'] = $this->maxfiles; - $mform->addElement('mod_surveypro_fileupload', $fieldname, $elementlabel, null, $attributes); + $attributes['id'] = $baseid; + $attributes['maxbytes'] = $this->maxbytes; + $attributes['accepted_types'] = $filetypes; + $attributes['subdirs'] = false; + $attributes['maxfiles'] = $this->maxfiles; - if ($this->required) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; + $elementgroup[] = $mform->createElement('filemanager', $basename.'_filemanager', $elementlabel, null, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); + + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; + } } } @@ -331,7 +369,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if ($this->required) { @@ -340,9 +378,10 @@ public function userform_mform_validation($data, &$errors, $searchform) { $fieldname = $this->itemname.'_filemanager'; if (empty($data[$fieldname])) { $errors[$errorkey] = get_string('required'); - return; } } + + return $errors; } /** @@ -365,8 +404,10 @@ public function userform_get_user_answer($answer, &$olduseranswer, $searchform) $attributes['accepted_types'] = $this->filetypes; $attributes['subdirs'] = false; $attributes['maxfiles'] = $this->maxfiles; - file_save_draft_area_files($answer['filemanager'], $context->id, 'surveyprofield_fileupload', - 'fileuploadfiles', $olduseranswer->id, $attributes); + file_save_draft_area_files( + $answer['filemanager'], $context->id, 'surveyprofield_fileupload', + 'fileuploadfiles', $olduseranswer->id, $attributes + ); $olduseranswer->content = ''; // Nothing is expected here. } @@ -388,7 +429,7 @@ public function userform_get_prefill($fromdb) { $context = \context_module::instance($this->cm->id); $fieldname = $this->itemname.'_filemanager'; - $draftitemid = 0; + $draftitemid = file_get_submitted_draft_itemid('surveyprofield_fileupload'); // ???? $attributes = []; $attributes['maxbytes'] = $this->maxbytes; $attributes['accepted_types'] = $this->filetypes; @@ -432,8 +473,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_filemanager']; - - return $elementnames; + return [$this->itemname.'_filemanager']; } } diff --git a/field/fileupload/db/install.xml b/field/fileupload/db/install.xml index 14e27e774d4..fd2c1bf3eb5 100644 --- a/field/fileupload/db/install.xml +++ b/field/fileupload/db/install.xml @@ -1,32 +1,16 @@ -
- - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/field/fileupload/db/upgrade.php b/field/fileupload/db/upgrade.php index 69707b74462..8c8a5d900ea 100644 --- a/field/fileupload/db/upgrade.php +++ b/field/fileupload/db/upgrade.php @@ -95,5 +95,66 @@ function xmldb_surveyprofield_fileupload_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2018060501, 'surveyprofield', 'fileupload'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_fileupload. + $table = new xmldb_table('surveyprofield_fileupload'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_fileupload} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Fileupload savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'fileupload'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_fileupload'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_fileupload. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_fileupload} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Fileupload savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'fileupload'); + } + return true; } diff --git a/field/fileupload/lang/en/surveyprofield_fileupload.php b/field/fileupload/lang/en/surveyprofield_fileupload.php index 3fc24982295..e704f401ec8 100644 --- a/field/fileupload/lang/en/surveyprofield_fileupload.php +++ b/field/fileupload/lang/en/surveyprofield_fileupload.php @@ -23,18 +23,18 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['filetypes_help'] = 'The comma separated list of allowed file extension'; -$string['filetypes'] = 'Allowed file types (comma separated)'; $string['fileextensions'] = 'Allowed file extensions: '; +$string['filetypes'] = 'Allowed file types (comma separated)'; +$string['filetypes_help'] = 'The comma separated list of allowed file extension'; +$string['ierr_dirtyextension'] = 'Only lower case letters and numbers are allowed into file extensions'; $string['ierr_extensionisempty'] = 'File extensions can not be empty. Probabily you typed a comma twice.'; $string['ierr_extensionmissingdot'] = 'File extensions must start with a dot'; $string['ierr_extensiononlyonedot'] = 'Only one dot is allowed per each file extension'; -$string['ierr_dirtyextension'] = 'Only lower case letters and numbers are allowed into file extensions'; $string['ierr_staramongextensions'] = '\'*\' is meaningful only if used individually'; -$string['maxbytes_help'] = 'Maximum size of the file to upload'; $string['maxbytes'] = 'Maximum file size'; -$string['maxfiles_help'] = 'Maximum uploadable attachments'; +$string['maxbytes_help'] = 'Maximum size of the file to upload'; $string['maxfiles'] = 'Maximum files'; +$string['maxfiles_help'] = 'Maximum uploadable attachments'; $string['pluginname'] = 'File upload'; -$string['userfriendlypluginname'] = 'Attachment'; $string['privacy:metadata'] = 'The "Fileupload" field plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Attachment'; diff --git a/field/fileupload/mform/fileupload.php b/field/fileupload/mform/fileupload.php deleted file mode 100644 index 8e485f1a668..00000000000 --- a/field/fileupload/mform/fileupload.php +++ /dev/null @@ -1,159 +0,0 @@ -. - -/** - * filemanager mform element - * - * Extends the core mform class for filemanager element - * - * @package surveyprofield_fileupload - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/filemanager.php'); - -// @codingStandardsIgnoreFile - -/** - * filemanager mform element - * - * Extends the core mform class for filemanager element - * - * @package surveyprofield_fileupload - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_fileupload extends \MoodleQuickForm_filemanager { - - /** - * Constructor. - * - * @param string $elementName Optional name of the filemanager - * @param string $elementLabel Optional filemanager label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filemanager - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - $this->_options['class'] = !isset($options['class']) ? 'indent-0' : $options['class']; - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * I want to change at the beginning: - *
- * to - *
- * - * @return string $output - */ - public function toHtml() { - $output = parent::toHtml(); // Core code. - - // I need to trim the code because mform library add a newline at the beginning. - $output = trim($output); - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
_options['class']; - $replacement = $tabs.'
dirroot/repository/lib.php"); - - $id = $this->_attributes['id']; - // $elname = $this->_attributes['name']; - // $subdirs = $this->_options['subdirs']; - // $maxbytes = $this->_options['maxbytes']; - $draftitemid = $this->getValue(); - $accepted_types = $this->_options['accepted_types']; - - if (empty($draftitemid)) { - // No existing area info provided - let's use fresh new draft area. - require_once($CFG->libdir/filelib.php); - $this->setValue(file_get_unused_draft_itemid()); - $draftitemid = $this->getValue(); - } - - $client_id = uniqid(); - - // Filemanager options. - $options = new \stdClass(); - $options->mainfile = $this->_options['mainfile']; - $options->maxbytes = $this->_options['maxbytes']; - $options->maxfiles = $this->getMaxfiles(); - $options->client_id = $client_id; - $options->itemid = $draftitemid; - $options->subdirs = $this->_options['subdirs']; - $options->target = $id; - $options->accepted_types = $accepted_types; - $options->return_types = $this->_options['return_types']; - $options->context = $PAGE->context; - $options->areamaxbytes = $this->_options['areamaxbytes']; - - $class = $this->_options['class']; - - $fm = new form_filemanager($options); - - $return = ''; - $attachmentcount = count($fm->options->list); - $attachmentcount -= 1; - foreach ($fm->options->list as $list) { - $return .= \html_writer::start_tag('div', ['class' => $class]); - - // $return .= ''; - $return .= \html_writer::start_tag('a', ['title' => s($list->filename), 'href' => $list->url]); - $return .= \html_writer::empty_tag('img', ['src' => $list->thumbnail]); - $return .= \html_writer::end_tag('a'); - - // $return .= ''.s($list->filename).'
'; - $return .= \html_writer::start_tag('a', ['title' => s($list->filename), 'href' => $list->url]); - $return .= s($list->filename); - $return .= \html_writer::end_tag('a'); - - $return .= \html_writer::end_tag('div'); - } - - return $return; - } -} diff --git a/field/fileupload/tests/behat/submit_attachment.feature b/field/fileupload/tests/behat/submit_attachment.feature index a6ebc777d51..28c39cbbc1d 100644 --- a/field/fileupload/tests/behat/submit_attachment.feature +++ b/field/fileupload/tests/behat/submit_attachment.feature @@ -13,13 +13,13 @@ Feature: Submit using a fileupload item | username | firstname | lastname | email | | teacher1 | Teacher | teacher | teacher1@nowhere.net | | student1 | Student1 | user1 | student1@nowhere.net | + And the following "user preferences" exist: + | user | preference | value | + | teacher1 | htmleditor | textarea | And the following "course enrolments" exist: | user | course | role | | teacher1 | Attachment submission test | editingteacher | | student1 | Attachment submission test | student | - And the following "user preferences" exist: - | user | preference | value | - | teacher1 | htmleditor | textarea | And the following "activities" exist: | activity | name | intro | course | | surveypro | Attachment test | To test submission of attachment item | Attachment submission test | @@ -30,20 +30,22 @@ Feature: Submit using a fileupload item And I expand all fieldsets And I set the following fields to these values: - | Content | Please upload your CV | - | Required | 1 | - | Indent | 0 | - | Question position | left | + | Content | Upload your CV | + | Required | 1 | + | Indent | 0 | + | Question position | left | And I press "Add" And I log out # student1 logs in + When I am on the "Attachment test" "surveypro activity" page logged in as student1 And I press "New response" # student1 submits - And I upload "mod/surveypro/tests/fixtures/dummyCV.pdf" file to "Please upload your CV" filemanager + # And I pause scenario execution + And I upload "mod/surveypro/tests/fixtures/dummyCV.pdf" file to "Upload your CV" filemanager And I press "Submit" diff --git a/field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml b/field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml similarity index 90% rename from field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml rename to field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml index b1a805df5e9..3bfed02f075 100644 --- a/field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml +++ b/field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml @@ -1,49 +1,47 @@ - + + <h5>ATTACHMENT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with three <b>file upload specific setting</b>:</p><ol><li>Maximum files</li><li>Maximum file size</li><li>Allowed file types</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>ATTACHMENT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with three <b>file upload specific setting</b>:</p><ol><li>Maximum files</li><li>Maximum file size</li><li>Allowed file types</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + - 0 - 0 - 0 - - <p>Upload your CV, please.</p> 1 0 0 0 fileupload_001 + 0 + 0 + + 1 0 .pdf, .docx - + - 0 - 0 - 0 - - <p>Please, upload the menu of the next week using a specific file per each working day.</p> 1 0 0 0 fileupload_002 + 0 + 0 + + 5 512000 .pdf diff --git a/field/fileupload/version.php b/field/fileupload/version.php index 9e252ee3d07..91b6fe82326 100644 --- a/field/fileupload/version.php +++ b/field/fileupload/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2018060501; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_fileupload'; // Full name of the plugin (used for diagnostics). diff --git a/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php b/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php index d32a34f652f..622d6dbd6d1 100644 --- a/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php +++ b/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'integer'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugininteger = new backup_nested_element('surveyprofield_integer', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/integer/classes/item.php b/field/integer/classes/item.php index 4b3d93d6405..74f8a56e97a 100644 --- a/field/integer/classes/item.php +++ b/field/integer/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string Value of the default setting (invite, custom...) @@ -88,7 +48,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -102,6 +62,13 @@ class item extends itembase { */ protected $upperbound; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -135,7 +102,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -165,14 +134,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -184,7 +149,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -205,13 +170,7 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Integer (small)'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'integer_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; $record->lowerbound = 0; @@ -249,25 +208,107 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return the content of the static property "canbeparent" + * @return array $data */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_plugin_presets() { + $pluginproperties = ['defaultoption', 'defaultvalue', 'lowerbound', 'upperbound']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_integer'] = []; return $fieldlist; } @@ -284,29 +325,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -438,8 +460,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_integer_'.$this->sortindex; - // Begin of: element values. $integers = []; if (!$searchform) { @@ -456,17 +476,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: element values. - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' integer_select']; - $elementgroup = [$mform->createElement('select', $this->itemname, '', $integers, $attributes)]; - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false); + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_integer_'.$this->sortindex; + $basename = $this->itemname; + + $attributes = ['id' => $baseid]; + $elementgroup[] = $mform->createElement('select', $basename, '', $integers, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); + $attributes = ['id' => $baseid]; if (!$searchform) { if ($this->required) { // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } @@ -474,7 +501,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Default section. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); } else { switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: @@ -484,10 +511,10 @@ public function userform_mform_element($mform, $searchform, $readonly) { $defaultinteger = SURVEYPRO_NOANSWERVALUE; break; } - $mform->setDefault($this->itemname, "$defaultinteger"); + $mform->setDefault($basename, "$defaultinteger"); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } } @@ -501,7 +528,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } // This plugin displays as dropdown menu. It will never return empty values. @@ -520,14 +547,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_integernotset', 'surveyprofield_integer', $a); } - return; + return $errors; } $haslowerbound = ($this->lowerbound != 0); $hasupperbound = ($this->upperbound != $maximuminteger); if ($userinput == SURVEYPRO_NOANSWERVALUE) { - return; + return $errors; } if ($haslowerbound && $hasupperbound) { // Internal range. @@ -542,6 +569,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_integer'); } } + + return $errors; } /** @@ -652,8 +681,6 @@ public function userform_get_prefill($fromdb) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/integer/db/install.xml b/field/integer/db/install.xml index c8e19e68803..209e887f5e3 100644 --- a/field/integer/db/install.xml +++ b/field/integer/db/install.xml @@ -1,33 +1,17 @@ -
- - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/field/integer/db/upgrade.php b/field/integer/db/upgrade.php index e8cf700fc79..c78f1472b05 100644 --- a/field/integer/db/upgrade.php +++ b/field/integer/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'integer'); } @@ -64,7 +64,7 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2014090401, 'surveyprofield', 'integer'); } @@ -78,9 +78,70 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->add_field($table, $field); } - // Fileupload savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2016072001, 'surveyprofield', 'integer'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_integer. + $table = new xmldb_table('surveyprofield_integer'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_integer} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Integer savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'integer'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_integer'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_integer. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_integer} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Integer savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'integer'); + } + return true; } diff --git a/field/integer/lang/en/surveyprofield_integer.php b/field/integer/lang/en/surveyprofield_integer.php index 94edfe04b1c..d8e346f0185 100644 --- a/field/integer/lang/en/surveyprofield_integer.php +++ b/field/integer/lang/en/surveyprofield_integer.php @@ -24,17 +24,18 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the integer the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; +$string['defaultoption_help'] = 'This is the integer the remote user will find answered by default. The default for this type of question is mandatory.'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; -$string['lowerbound_help'] = 'The lowest integer the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; -$string['maximuminteger_desc'] = 'The maximun integer this software will allow to ever enter'; +$string['lowerbound_help'] = 'The lowest integer the user is allowed to enter'; $string['maximuminteger'] = 'Maximum integer'; +$string['maximuminteger_desc'] = 'The maximun integer this software will allow to ever enter'; $string['parentformat'] = '[an integer]'; $string['pluginname'] = 'Integer'; +$string['privacy:metadata'] = 'The "Integer" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -43,7 +44,6 @@ $string['uerr_integernotsetrequired'] = 'Please choose a value'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest integer the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest integer the user is allowed to enter'; $string['userfriendlypluginname'] = 'Integer (small)'; -$string['privacy:metadata'] = 'The "Integer" field plugin does not store any personal data.'; diff --git a/field/integer/lang/it/surveyprofield_integer.php b/field/integer/lang/it/surveyprofield_integer.php index c5f55ce0101..b751dc1e7a0 100644 --- a/field/integer/lang/it/surveyprofield_integer.php +++ b/field/integer/lang/it/surveyprofield_integer.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['uerr_integernotsetrequired'] = 'Si selezioni un valore'; -$string['uerr_integernotset'] = 'Si selezioni un valore oppure l\'ultima voce: "{$a}"'; $string['restriction_lower'] = 'La risposta deve essere maggiore o uguale a {$a}'; $string['restriction_lowerupper'] = 'La risposta deve essere compresa fra {$a->lowerbound} e {$a->upperbound}'; $string['restriction_upper'] = 'La risposta deve essere minore o uguale a {$a}'; +$string['uerr_integernotset'] = 'Si selezioni un valore oppure l\'ultima voce: "{$a}"'; +$string['uerr_integernotsetrequired'] = 'Si selezioni un valore'; diff --git a/field/integer/tests/behat/itemform.feature b/field/integer/tests/behat/itemform.feature index ec353ed5610..016cd4450f6 100644 --- a/field/integer/tests/behat/itemform.feature +++ b/field/integer/tests/behat/itemform.feature @@ -87,5 +87,5 @@ Feature: Create an integer item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a How many people does your family counts?" - Then the field "id_surveypro_field_integer_2" matches value "5" + Then the field "id_field_integer_2" matches value "5" Then I should see "Additional note" diff --git a/field/integer/tests/behat/submit_integer.feature b/field/integer/tests/behat/submit_integer.feature index 41dede4af0d..3a2d7d36062 100644 --- a/field/integer/tests/behat/submit_integer.feature +++ b/field/integer/tests/behat/submit_integer.feature @@ -41,7 +41,7 @@ Feature: Submit using an integer item And I press "New response" # student1 submits - And I set the field "id_surveypro_field_integer_1" to "3" + And I set the field "id_field_integer_1" to "3" And I press "Submit" diff --git a/field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml b/field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml similarity index 88% rename from field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml rename to field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml index c7893ef0e86..802d11c11eb 100644 --- a/field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml +++ b/field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml @@ -1,155 +1,154 @@ - + + <h5>INTEGER</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>integer specific setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>INTEGER</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>integer specific setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 1 0 0 - 1 - 0 + 1 integer_001 Include yourself in the count + 0 + 0 + 0 + + 2 + 0 1 19 - + + <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. + 1 + 0 + 2 info 0 0 0 - <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 1 0 0 - 2 - 0 + 1 integer_002b Include yourself in the count + 0 + 0 + 0 + + 1 + 0 1 19 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is upper limited to 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this item leaving the proposed default untouched (and the question not read) or select the "No answer" item. + 1 + 0 + 3 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is upper limited to 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this item leaving the proposed default untouched (and the question not read) or select the "No answer" item. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 0 0 0 - 3 - 0 + 1 integer_003 Include yourself in the count + 0 + 0 + 0 + + 1 1 1 19 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 0 0 0 - 4 - 0 + 1 integer_004 Include yourself in the count + 0 + 0 + 0 + + 2 + 0 1 19 diff --git a/field/integer/version.php b/field/integer/version.php index 98bb89361aa..a866d702863 100644 --- a/field/integer/version.php +++ b/field/integer/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_integer'; // Full name of the plugin (used for diagnostics). diff --git a/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php b/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php index b1ebea6458d..255b0e0297b 100644 --- a/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php +++ b/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php @@ -40,10 +40,9 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'multiselect'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginmultiselect = new backup_nested_element('surveyprofield_multiselect', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'options', 'defaultvalue', 'noanswerdefault', 'downloadformat', - 'minimumrequired', 'maximumrequired', 'heightinrows', ]); + 'minimumrequired', 'maximumrequired', 'heightinrows', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/multiselect/classes/item.php b/field/multiselect/classes/item.php index f14d60eacb7..91ecc49f76b 100644 --- a/field/multiselect/classes/item.php +++ b/field/multiselect/classes/item.php @@ -40,57 +40,27 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var string Name of the field storing data in the db table + * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" */ - protected $variable; + protected $options; /** - * @var int Indent of the item in the form page + * @var int Defaultvalue for the item answer */ - protected $indent; + protected $defaultvalue; /** - * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" + * @var string Format of the content once downloaded */ - protected $options; + protected $downloadformat; /** - * @var string Format of the content once downloaded + * @var string noanswerdefault */ - protected $downloadformat; + protected $noanswerdefault; /** * @var int Height of the multiselect in rows @@ -107,6 +77,13 @@ class item extends itembase { */ protected $maximumrequired; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -139,7 +116,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -169,18 +148,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -192,7 +167,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -216,17 +191,13 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Multiple selection'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'multiselect_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->defaultvalue + // $record->noanswerdefault $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->minimumrequired = 0; + // $record->maximumrequired $record->heightinrows = 4; } @@ -239,7 +210,7 @@ public function item_list_constraints() { $constraints = []; $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_multiselect'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -248,15 +219,141 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set noanswerdefault. + * + * @param string $noanswerdefault + * @return void + */ + public function set_noanswerdefault($noanswerdefault) { + $this->noanswerdefault = $noanswerdefault; + } + + /** + * Set heightinrows. + * + * @param string $heightinrows + * @return void + */ + public function set_heightinrows($heightinrows) { + $this->heightinrows = $heightinrows; + } + + /** + * Set minimumrequired. + * + * @param string $minimumrequired + * @return void + */ + public function set_minimumrequired($minimumrequired) { + $this->minimumrequired = $minimumrequired; + } + + /** + * Set maximumrequired. + * + * @param string $maximumrequired + * @return void + */ + public function set_maximumrequired($maximumrequired) { + $this->maximumrequired = $maximumrequired; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get noanswerdefault. * - * @return the content of the static property "canbeparent" + * @return $this->noanswerdefault */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_noanswerdefault() { + return $this->noanswerdefault; + } + + /** + * Get heightinrows. + * + * @return $this->heightinrows + */ + public function get_heightinrows() { + return $this->heightinrows; + } + + /** + * Get minimumrequired. + * + * @return $this->minimumrequired + */ + public function get_minimumrequired() { + return $this->minimumrequired; + } + + /** + * Get maximumrequired. + * + * @return $this->maximumrequired + */ + public function get_maximumrequired() { + return $this->maximumrequired; } /** @@ -283,14 +380,29 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'options', 'defaultvalue', 'noanswerdefault', 'downloadformat', 'minimumrequired', 'maximumrequired', 'heightinrows', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_multiselect'] = ['options', 'defaultvalue']; return $fieldlist; } @@ -316,32 +428,13 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + - + @@ -362,7 +455,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = array_fill(0, count($values), 0); $labels = []; @@ -400,7 +493,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { * return string $childparentcontent */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -449,7 +542,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optioncount = count($values); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -494,65 +587,65 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_multiselect_'.$this->sortindex; - - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' multiselect_select'; + $elementgroup = []; + $baseid = 'id_field_multiselect_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $basename = $this->itemname; + + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); + $attributes['id'] = $baseid; $attributes['size'] = $this->heightinrows; + + $select = $mform->createElement('select', $basename, '', $labels, $attributes); + $select->setMultiple(true); + $elementgroup[] = $select; + + unset($attributes['size']); // No longer needed. + if (!$searchform) { if ($this->required) { - $select = $mform->addElement('select', $this->itemname, $elementlabel, $labels, $attributes); - $select->setMultiple(true); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); } else { - $elementgroup = []; - $select = $mform->createElement('select', $this->itemname, '', $labels, $attributes); - $select->setMultiple(true); - $elementgroup[] = $select; - - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'multiselect_check'; - unset($attributes['size']); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); // Multiselect uses a special syntax - // that is different from the syntax of all the other mform groups with disabilitation chechbox. - // $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked');. - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_noanswer', 'checked'); + // that is different from all the other mform group with disabilitation chechbox syntax. + // $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked');. + $mform->disabledIf($basename.'[]', $basename.'_noanswer', 'checked'); } } else { - $elementgroup = []; - $select = $mform->createElement('select', $this->itemname, '', $labels, $attributes); - $select->setMultiple(true); - $elementgroup[] = $select; - - $attributes['class'] = 'multiselect_check'; - unset($attributes['size']); - if (!$this->required) { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); } - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'multiselect_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '
', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '
', false, $class); if (!$this->required) { // Multiselect uses a special syntax - // that is different from the syntax of all the other mform groups with disabilitation chechbox. - // $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked');. - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_noanswer', 'checked'); + // that is different from all the other mform group with disabilitation chechbox syntax. + // $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked');. + $mform->disabledIf($basename.'[]', $basename.'_noanswer', 'checked'); + } + $mform->disabledIf($basename.'[]', $basename.'_ignoreme', 'checked'); + $mform->disabledIf($basename.'_noanswer', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); + } + + if (!$searchform) { + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; } - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_ignoreme', 'checked'); - $mform->disabledIf($this->itemname.'_noanswer', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); } // Begin of: defaults. @@ -562,16 +655,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { foreach ($defaults as $default) { $defaultkeys[] = array_search($default, $labels); } - $mform->setDefault($this->itemname, $defaultkeys); + $mform->setDefault($basename, $defaultkeys); } - $itemname = $this->itemname.'_noanswer'; if (!empty($this->noanswerdefault)) { - $mform->setDefault($itemname, '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } // End of: defaults. - // This last item is needed because the check for the not empty field is performed in the validation routine (not by JS). + // This last item is needed because the check for "not empty" field is performed in the validation routine (not by JS). // For multiselect element, nothing is submitted if no option is selected // so, if the user neglects the mandatory multiselect AT ALL, it is not submitted and, as conseguence, not validated. // TO ALWAYS SUBMIT A MULTISELECT I add a dummy hidden item. @@ -581,17 +673,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $placeholderitemname = SURVEYPRO_PLACEHOLDERPREFIX.'_'.$this->type.'_'.$this->plugin.'_'.$this->itemid; $mform->addElement('hidden', $placeholderitemname, 1); $mform->setType($placeholderitemname, PARAM_INT); - - if (!$searchform) { - if ($this->required) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; - } - } } /** @@ -604,13 +685,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (isset($data[$this->itemname.'_noanswer']) && ($data[$this->itemname.'_noanswer'] == 1) ) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } - $errorkey = $this->required ? $this->itemname : $this->itemname.'_group'; + $errorkey = $this->itemname.'_group'; // I don't care if this element is required or not. // If the user provides an answer, it has to be compliant with the field validation rules. @@ -631,6 +712,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum_more', 'surveyprofield_multiselect', $a); } } + + return $errors; } /** @@ -774,13 +857,13 @@ public function userform_get_user_answer($answer, &$olduseranswer, $searchform) } if (!isset($answer['mainelement'])) { // Only placeholder arrived here. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $olduseranswer->content = implode(SURVEYPRO_DBMULTICONTENTSEPARATOR, array_fill(1, count($labels), '0')); } else { // Here $answer is an array with the keys of the selected elements. $olduseranswer->content = implode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $answer['mainelement']); - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $itemcount = count($labels); $contentarray = array_fill(0, $itemcount, 0); foreach ($answer['mainelement'] as $k) { @@ -860,7 +943,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); foreach ($answers as $k => $answer) { if ($answer == 1) { $output[] = $values[$k]; @@ -871,7 +954,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($answers as $k => $answer) { if ($answer == 1) { diff --git a/field/multiselect/db/install.xml b/field/multiselect/db/install.xml index 6bb2b0fb687..7ae6ec42f6e 100644 --- a/field/multiselect/db/install.xml +++ b/field/multiselect/db/install.xml @@ -1,36 +1,20 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/field/multiselect/db/upgrade.php b/field/multiselect/db/upgrade.php index b4a6eed4535..2ca244e7e99 100644 --- a/field/multiselect/db/upgrade.php +++ b/field/multiselect/db/upgrade.php @@ -148,5 +148,66 @@ function xmldb_surveyprofield_multiselect_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2023111401, 'surveyprofield', 'multiselect'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_multiselect. + $table = new xmldb_table('surveyprofield_multiselect'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_multiselect} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Multiselect savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'multiselect'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_multiselect'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_multiselect. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_multiselect} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Multiselect savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'multiselect'); + } + return true; } diff --git a/field/multiselect/lang/en/surveyprofield_multiselect.php b/field/multiselect/lang/en/surveyprofield_multiselect.php index 449d02bd07c..e24d94e9742 100644 --- a/field/multiselect/lang/en/surveyprofield_multiselect.php +++ b/field/multiselect/lang/en/surveyprofield_multiselect.php @@ -23,12 +23,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['defaultvalue'] = 'Default'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['downloadformat'] = 'Download format'; -$string['heightinrows_help'] = 'The number of rows the multiselect will show'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['heightinrows'] = 'Height in rows'; +$string['heightinrows_help'] = 'The number of rows the multiselect will show'; $string['ierr_defaultsduplicated'] = 'Defaults must be different each other'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; $string['ierr_labelsduplicated'] = 'Options must be different each other'; @@ -37,21 +37,22 @@ $string['ierr_minimumrequired'] = 'The minimum number of items to select must be lower than {$a} (options count)'; $string['ierr_optionswithseparator'] = 'Options can not contain "{$a}"'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['maximumrequired_help'] = 'The maximum number of items the user can choose in his/her answer'; $string['maximumrequired'] = 'Maximum allowed options'; -$string['minimumrequired_help'] = 'The minimum number of items the user is forced to choose in his/her answer'; +$string['maximumrequired_help'] = 'The maximum number of items the user can choose in his/her answer'; $string['minimumrequired'] = 'Minimum required items'; -$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; +$string['minimumrequired_help'] = 'The minimum number of items the user is forced to choose in his/her answer'; $string['noanswerdefault'] = '"No answer" as defaults'; +$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the element list, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the element list, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[One
label
per
line]'; $string['pluginname'] = 'Multiple selection'; -$string['restrictions_maximumrequired_more'] = 'No more than {$a} items are allowed'; -$string['restrictions_maximumrequired_one'] = 'No more than 1 item is allowed'; -$string['restrictions_minimumrequired_more'] = 'At least {$a} items have to be selected'; -$string['restrictions_minimumrequired_one'] = 'At least 1 item has to be selected'; +$string['privacy:metadata'] = 'The "Multiselect" field plugin does not store any personal data.'; +$string['restrictions_maximumrequired_more'] = 'No more than {$a} options are allowed'; +$string['restrictions_maximumrequired_one'] = 'No more than 1 option is allowed'; +$string['restrictions_minimumrequired_more'] = 'At least {$a} options have to be selected'; +$string['restrictions_minimumrequired_one'] = 'At least 1 option has to be selected'; $string['returnlabels'] = 'label of selected items'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected items'; @@ -60,4 +61,3 @@ $string['uerr_lowerthanminimum_more'] = 'Please select at least {$a} options'; $string['uerr_lowerthanminimum_one'] = 'Please select at least 1 option'; $string['userfriendlypluginname'] = 'Multiple selection'; -$string['privacy:metadata'] = 'The "Multiselect" field plugin does not store any personal data.'; diff --git a/field/multiselect/tests/behat/itemform.feature b/field/multiselect/tests/behat/itemform.feature index 4320c312941..1b0263e28f1 100644 --- a/field/multiselect/tests/behat/itemform.feature +++ b/field/multiselect/tests/behat/itemform.feature @@ -88,5 +88,5 @@ Feature: Create a multiselect item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a What do you usually get for breakfast?" - Then the field "id_surveypro_field_multiselect_2" matches value "coffee, bread" + Then the field "id_field_multiselect_2" matches value "coffee, bread" Then I should see "Additional note" diff --git a/field/multiselect/tests/behat/settings_configuration_01.feature b/field/multiselect/tests/behat/settings_configuration_01.feature index 5f1923a6a56..30d25a7567f 100644 --- a/field/multiselect/tests/behat/settings_configuration_01.feature +++ b/field/multiselect/tests/behat/settings_configuration_01.feature @@ -56,7 +56,7 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -65,7 +65,7 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 | milk, bread | + | id_field_multiselect_1 | milk, bread | | No answer | 1 | And I press "Submit" And I press "Continue to responses list" @@ -94,13 +94,13 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 4: Student flies over the answer And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -108,8 +108,8 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 5: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -117,10 +117,10 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 6: Student chooses "No answer" And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 |milk, bread | - | No answer | 1 | + | id_field_multiselect_1 |milk, bread | + | No answer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_02.feature b/field/multiselect/tests/behat/settings_configuration_02.feature index 361a8188854..7e1d645ae84 100644 --- a/field/multiselect/tests/behat/settings_configuration_02.feature +++ b/field/multiselect/tests/behat/settings_configuration_02.feature @@ -56,7 +56,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -65,7 +65,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 |milk, bread | + | id_field_multiselect_1 |milk, bread | | No answer | 1 | And I press "Submit" And I press "Continue to responses list" @@ -94,10 +94,10 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 4: Student flies over the answer And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -105,8 +105,8 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 5: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -114,7 +114,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 6: Student chooses "No answer" And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I set the field "No answer" to "1" And I press "Submit" And I press "Continue to responses list" diff --git a/field/multiselect/tests/behat/settings_configuration_03.feature b/field/multiselect/tests/behat/settings_configuration_03.feature index 522b8079645..818b11f3b6a 100644 --- a/field/multiselect/tests/behat/settings_configuration_03.feature +++ b/field/multiselect/tests/behat/settings_configuration_03.feature @@ -57,7 +57,7 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -86,13 +86,13 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 3: Student flies over the answer And I press "New response" Then I should not see "No answer" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,7 +100,7 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 4: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_04.feature b/field/multiselect/tests/behat/settings_configuration_04.feature index 2b9e2f2368a..0c57e9af92f 100644 --- a/field/multiselect/tests/behat/settings_configuration_04.feature +++ b/field/multiselect/tests/behat/settings_configuration_04.feature @@ -57,7 +57,7 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -86,13 +86,13 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 3: Student flies over the answer And I press "New response" Then I should not see "No answer" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,8 +100,8 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 4: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "bread, coffee" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "bread, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_05.feature b/field/multiselect/tests/behat/settings_configuration_05.feature index 2f0fdc828b5..5ec1414ea78 100644 --- a/field/multiselect/tests/behat/settings_configuration_05.feature +++ b/field/multiselect/tests/behat/settings_configuration_05.feature @@ -39,7 +39,7 @@ Feature: Submit using multiselect item and check form validation # Test number 1: Student submits a standard answer And I press "New response" Then I should not see "No more than" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -59,11 +59,11 @@ Feature: Submit using multiselect item and check form validation # Test number 2: Student ticks too many items And I press "New response" - Then I should see "No more than 3 items are allowed" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee, butter, bread" + Then I should see "No more than 3 options are allowed" + And I set the field "id_field_multiselect_1" to "milk, coffee, butter, bread" And I press "Submit" Then I should see "Please tick no more than 3 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee, bread" + And I set the field "id_field_multiselect_1" to "milk, coffee, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -71,8 +71,8 @@ Feature: Submit using multiselect item and check form validation # Test number 3: Student submits a standard answer And I press "New response" - Then I should see "No more than 3 items are allowed" - And I set the field "id_surveypro_field_multiselect_1" to "coffee" + Then I should see "No more than 3 options are allowed" + And I set the field "id_field_multiselect_1" to "coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml b/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml similarity index 87% rename from field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml rename to field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml index d8d5bf6fe00..9cd5bfdade2 100644 --- a/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml +++ b/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>MULTISELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some<b>multiple selection specific setting</b>:</p><ol><li>Options</li><li>Default</li><li>Height in rows</li><li>Minimum required items</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>MULTISELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some<b>multiple selection specific setting</b>:</p><ol><li>Options</li><li>Default</li><li>Height in rows</li><li>Minimum required items</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least one item. + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least one item. - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 1 - 0 + 1 multiselect_001 + 0 + 0 + 0 + + milk sugar jam @@ -53,35 +52,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 2 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 2 - 0 + 1 multiselect_002 + 0 + 0 + 0 + + milk sugar jam @@ -95,35 +93,34 @@ jam 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least one item or to select the "No answer" checkbox. + 1 + 0 + 3 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least one item or to select the "No answer" checkbox. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 3 - 0 + 1 multiselect_003 + 0 + 0 + 0 + + milk sugar jam @@ -135,35 +132,34 @@ chocolate 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 4 - 0 + 1 multiselect_004 + 0 + 0 + 0 + + milk sugar jam @@ -176,35 +172,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least two items. + 1 + 0 + 5 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least two items. - 1 - 0 - 5 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 5 - 0 + 1 multiselect_005 + 0 + 0 + 0 + + milk sugar jam @@ -216,36 +211,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value but the user can not "fly" over this element because the minimum required options is set to 2.<br /> + 1 + 0 + 6 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value but the user can not "fly" over this element because the minimum -required options is set to 2.<br /> - 1 - 0 - 6 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 6 - 0 + 1 multiselect_006 + 0 + 0 + 0 + + milk sugar jam @@ -259,35 +252,34 @@ jam 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least two items or to select the "No answer" checkbox. + 1 + 0 + 7 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least two items or to select the "No answer" checkbox. - 1 - 0 - 7 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 7 - 0 + 1 multiselect_007 + 0 + 0 + 0 + + milk sugar jam @@ -299,35 +291,34 @@ chocolate 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. + 1 + 0 + 8 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. - 1 - 0 - 8 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 8 - 0 + 1 multiselect_008 + 0 + 0 + 0 + + milk sugar jam diff --git a/field/multiselect/version.php b/field/multiselect/version.php index fdf57da80d1..1dfcca3f7d9 100644 --- a/field/multiselect/version.php +++ b/field/multiselect/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023111401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_multiselect'; // Full name of the plugin (used for diagnostics). diff --git a/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php b/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php index 6f327472a5a..7910f852293 100644 --- a/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php +++ b/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'numeric'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginnumeric = new backup_nested_element('surveyprofield_numeric', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals', ]); + 'defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/numeric/classes/item.php b/field/numeric/classes/item.php index 076584ab52f..877bd4af124 100644 --- a/field/numeric/classes/item.php +++ b/field/numeric/classes/item.php @@ -40,82 +40,46 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH + * @var int Defaultvalue for the item answer */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; + protected $defaultvalue; /** - * @var bool 0 => optional item; 1 => mandatory item; + * @var bool Is the number signed? */ - protected $required; + protected $signed; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var int Number lowerbound */ - protected $hideinstructions; + protected $lowerbound; /** - * @var string Name of the field storing data in the db table + * @var int Number upperbound */ - protected $variable; + protected $upperbound; /** - * @var int Indent of the item in the form page + * @var int Number of decimals allowed for this number */ - protected $indent; + protected $decimals; - /** - * @var string Value of the field when the form is initially displayed - */ - protected $defaultvalue; + // Service variables. /** * @var string Decimal separator */ protected $decimalseparator; - /** - * @var bool Is the number signed? - */ - protected $signed; - - /** - * @var int Number lowerbound - */ - protected $lowerbound; - - /** - * @var int Number upperbound - */ - protected $upperbound; + // Service variables. /** - * @var int Number of decimals allowed for this number + * @var bool Does this item use the child table surveypro(field|format)_plugin? */ - protected $decimals; + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -149,7 +113,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -181,14 +147,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -201,15 +163,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Numeric'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'numeric_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + // $record->defaultvalue $record->signed = 0; + // $record->lowerbound + // $record->upperbound $record->decimals = 0; } @@ -223,12 +181,12 @@ public function item_custom_fields_to_form() { // Nothing to do: they don't exist in this plugin. // 2. float numbers need more attention because I can write them using , or . - if (core_text::strlen($this->defaultvalue)) { - $this->defaultvalue = format_float($this->defaultvalue, $this->decimals); + $numericfields = ['defaultvalue', 'lowerbound', 'upperbound']; + foreach ($numericfields as $numericfield) { + if (core_text::strlen($this->{$numericfield})) { + $this->{$numericfield} = format_float($this->{$numericfield}, $this->decimals); + } } - // Note: $this->lowerbound and $this->upperbound comes from db and are correctly written. - // I am not going to put them in a field so I can leave them well written... - // ...instead of changing them according to the local language. } /** @@ -237,7 +195,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -249,39 +207,139 @@ public function item_custom_fields_to_db($record) { // Nothing to do: no checkboxes in this plugin item form. // 4. Other: float numbers need more attention because I can write them using , or . - if (core_text::strlen($record->defaultvalue)) { - $record->defaultvalue = $this->get_international_number($record->defaultvalue); - } else { - $record->defaultvalue = null; - } - if (core_text::strlen($record->lowerbound)) { - $record->lowerbound = $this->get_international_number($record->lowerbound); - } else { - $record->lowerbound = null; - } - if (core_text::strlen($record->upperbound)) { - $record->upperbound = $this->get_international_number($record->upperbound); - } else { - $record->upperbound = null; + $numericfields = ['defaultvalue', 'lowerbound', 'upperbound']; + foreach ($numericfields as $numericfield) { + if (core_text::strlen($record->{$numericfield})) { + $record->{$numericfield} = $this->get_international_number($record->{$numericfield}); + } else { + $record->{$numericfield} = null; + } } } + // MARK set. + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set signed. + * + * @param string $signed + * @return void + */ + public function set_signed($signed) { + $this->signed = $signed; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set decimals. + * + * @param string $decimals + * @return void + */ + public function set_decimals($decimals) { + $this->decimals = $decimals; + } + + /** + * Set decimalseparator. + * + * @param string $decimalseparator + * @return void + */ + public function set_decimalseparator($decimalseparator) { + $this->decimalseparator = $decimalseparator; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get signed. + * + * @return $this->signed + */ + public function get_signed() { + return $this->signed; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get decimals. + * + * @return $this->decimals + */ + public function get_decimals() { + return $this->decimals; + } + + /** + * Get decimalseparator. * - * @return the content of the static property "canbeparent" + * @return $this->decimalseparator */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_decimalseparator() { + return $this->decimalseparator; } /** * Get the requested property. * * @param string $field - * @return the content of the field or false if the field is not set. + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { if (isset($this->{$field})) { @@ -292,7 +350,8 @@ public function get_generic_property($field) { if ($condition) { $return = $this->get_international_number($this->{$field}); } else { - $return = $this->{$field}; + $method = 'get_'.$field; + $return = $this->{$method}(); } } else { $return = false; @@ -303,32 +362,52 @@ public function get_generic_property($field) { /** * get_international_number - * starting from justanumber written using local decimal separator, + * starting from localnumber written using local decimal separator, * this function returns the same number written using the dot as decimal separator. * - * @param double $localnumber + * @param double|bool $localnumber false in case of error * @return void or double $internationalnumber */ public function get_international_number($localnumber) { $localnumber = trim($localnumber); - $internationalnumber = str_replace($this->decimalseparator, '.', $localnumber); - if (is_numeric($internationalnumber)) { - $return = $internationalnumber; - } else { + $condition = ($this->decimals > 0); + $condition = $condition && (strpos($localnumber, $this->decimalseparator) === false); + if ($condition) { $return = false; + } else { + // It does not matter if $this->decimalseparator is not onboard. It could be. + $internationalnumber = str_replace($this->decimalseparator, '.', $localnumber); + if (is_numeric($internationalnumber)) { + $return = $internationalnumber; + } else { + $return = false; + } } return $return; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_numeric'] = []; return $fieldlist; } @@ -345,30 +424,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - + @@ -396,21 +456,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_numeric_'.$this->sortindex; - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' numeric_text'; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_numeric_'.$this->sortindex; + $basename = $this->itemname; + $attributes['id'] = $baseid; // Cool for browsers supporting html 5. // $attributes['type'] = 'number'; // But it doesn't work because "type" property is reserved to mform library. if (!$searchform) { - $mform->addElement('text', $this->itemname, $elementlabel, $attributes); - $mform->setType($this->itemname, PARAM_RAW); // See: moodlelib.php lines 133+. + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename, PARAM_RAW); // See: moodlelib.php lines 133+. + if (core_text::strlen($this->defaultvalue)) { - $mform->setDefault($this->itemname, "$this->defaultvalue"); + $mform->setDefault($basename, "$this->defaultvalue"); } if ($this->required) { @@ -418,22 +481,18 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('text', $this->itemname, '', $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'numeric_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $elementgroup[] = $mform->createElement('text', $basename, '', $attributes); + $mform->setType($basename, PARAM_RAW); + + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -447,24 +506,25 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } - $errorkey = $this->itemname; + $errorkey = $this->itemname.'_group'; $draftuserinput = $data[$this->itemname]; if (!core_text::strlen($draftuserinput)) { if (!empty($this->required)) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } $userinput = $this->get_international_number($draftuserinput); + if (!is_numeric($userinput)) { // It is not a number, shouts. $errors[$errorkey] = get_string('uerr_notanumber', 'surveyprofield_numeric'); - return; + return $errors; } else { // If it is < 0 but has been defined as unsigned, shouts. if (!$this->signed && ($userinput < 0)) { @@ -503,6 +563,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_numeric'); } } + + return $errors; } /** @@ -615,13 +677,4 @@ public function userform_get_root_elements_name() { return $elementnames; } - - /** - * Does the user input need trim? - * - * @return if this plugin requires a user input trim - */ - public static function userform_input_needs_trim() { - return true; - } } diff --git a/field/numeric/db/install.xml b/field/numeric/db/install.xml index a30fada2cdd..109fd7f4cc1 100644 --- a/field/numeric/db/install.xml +++ b/field/numeric/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/numeric/db/upgrade.php b/field/numeric/db/upgrade.php index 48eb38db66d..7533742b7d9 100644 --- a/field/numeric/db/upgrade.php +++ b/field/numeric/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_numeric_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Numeric savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'numeric'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_numeric. + $table = new xmldb_table('surveyprofield_numeric'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_numeric} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Numeric savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'numeric'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_numeric'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_numeric. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_numeric} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Numeric savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'numeric'); + } + return true; } diff --git a/field/numeric/lang/en/surveyprofield_numeric.php b/field/numeric/lang/en/surveyprofield_numeric.php index 2929f21162b..7ae0eedfec0 100644 --- a/field/numeric/lang/en/surveyprofield_numeric.php +++ b/field/numeric/lang/en/surveyprofield_numeric.php @@ -25,11 +25,11 @@ $string['allowed'] = 'allowed'; $string['decimalautofix'] = 'exceeding or missing decimals will be dropped out or filled with zeroes'; -$string['decimals_help'] = 'The number of decimals places of the request number'; $string['decimals'] = 'Decimal positions'; +$string['decimals_help'] = 'The number of decimals places of the request number'; $string['declaredecimalseparator'] = 'decimal separator is supposed to be \'{$a}\''; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default. Blank to leave default unassigned.'; $string['defaultvalue'] = 'Default'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default. Blank to leave default unassigned.'; $string['ierr_default_notinteger'] = 'Default is not an integer'; $string['ierr_default_outofrange'] = 'Default does not fall within the specified range'; $string['ierr_defaultsignnotallowed'] = 'Default is supposed to be unsigned'; @@ -39,25 +39,25 @@ $string['ierr_notanumber'] = 'This is not a number'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['ierr_uppernegative'] = 'Upper bound is supposed to be unsigned'; -$string['lowerbound_help'] = 'The minimum allowed value. Blank to leave minimum unassigned.'; $string['lowerbound'] = 'Minimum value'; +$string['lowerbound_help'] = 'The minimum allowed value. Blank to leave minimum unassigned.'; $string['number'] = 'Number '; $string['pluginname'] = 'Numeric'; -$string['restriction_hasdecimals'] = 'is supposed to have {$a} decimal positions'; +$string['privacy:metadata'] = 'The "Numeric" field plugin does not store any personal data.'; +$string['restriction_hasdecimals'] = 'it is supposed to have {$a} decimal positions'; $string['restriction_hassign'] = 'can be negative'; -$string['restriction_isinteger'] = 'is supposed to be an integer'; +$string['restriction_isinteger'] = 'it is supposed to be an integer'; $string['restriction_lower'] = 'Answer is supposed be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed be lower-equal than {$a}'; -$string['signed_help'] = 'Is the expected number supposed to be signed?'; $string['signed'] = 'Signed value'; +$string['signed_help'] = 'Is the expected number supposed to be signed?'; $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_negative'] = 'Provided value is supposed to be unsigned'; $string['uerr_notanumber'] = 'Provided value is not a number'; $string['uerr_notinteger'] = 'Provided value is supposed to be integer'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest number the user is allowed to enter.'; $string['upperbound'] = 'Maximum value'; +$string['upperbound_help'] = 'The biggest number the user is allowed to enter.'; $string['userfriendlypluginname'] = 'Numeric'; -$string['privacy:metadata'] = 'The "Numeric" field plugin does not store any personal data.'; diff --git a/field/numeric/tests/behat/itemform.feature b/field/numeric/tests/behat/itemform.feature index 86e729acdb9..9584664507b 100644 --- a/field/numeric/tests/behat/itemform.feature +++ b/field/numeric/tests/behat/itemform.feature @@ -87,5 +87,5 @@ Feature: Create a numeric item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Type the best approximation of π you know" - Then the field "id_surveypro_field_numeric_2" matches value "3.14" + Then the field "id_field_numeric_2" matches value "3.14" Then I should see "Additional note" diff --git a/field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml b/field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml similarity index 84% rename from field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml rename to field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml index 73262741681..14da0541a47 100644 --- a/field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml +++ b/field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml @@ -1,157 +1,153 @@ - + + <h5>NUMERIC</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one<b> </b><b>numeric specific setting</b>:</p><ol><li>Default</li></ol><p>and with some more <b>validation options</b></p><ol><li>Signed value</li><li>Decimal positions</li><li>Minimum value</li><li>Maximum value</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>NUMERIC</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one<b> </b><b>numeric specific setting</b>:</p><ol><li>Default</li></ol><p>and with some more <b>validation options</b></p><ol><li>Signed value</li><li>Decimal positions</li><li>Minimum value</li><li>Maximum value</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 1 0 0 - 1 - 0 + 1 numeric_001 - 3.1 + 0 + 0 + 0 + + + 3.1000 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>not mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or blank the field. + 1 + 0 + 2 info 0 0 0 - <ul><li>not mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or blank the field. - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 0 0 0 - 2 - 0 + 1 numeric_002 - 3.1 + 0 + 0 + 0 + + + 3.1000 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory but the default is unset. The user will be forced to choose a value. + 1 + 0 + 3 info 0 0 0 - <ul><li>mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory but the default is unset. The user will be forced to choose a value. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 1 0 0 - 3 - 0 + 1 numeric_003 + 0 + 0 + 0 + + 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>not mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 0 0 0 - 4 - 0 + 1 numeric_004 + 0 + 0 + 0 + + 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 diff --git a/field/numeric/version.php b/field/numeric/version.php index 3bc0801fca9..642ae66ba6a 100644 --- a/field/numeric/version.php +++ b/field/numeric/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_numeric'; // Full name of the plugin (used for diagnostics). diff --git a/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php b/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php index 6988434c917..ac7e01b435c 100644 --- a/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php +++ b/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'radiobutton'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginradiobutton = new backup_nested_element('surveyprofield_radiobutton', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment', ]); + 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/radiobutton/classes/item.php b/field/radiobutton/classes/item.php index b04e1b1d6bb..a8599398f24 100644 --- a/field/radiobutton/classes/item.php +++ b/field/radiobutton/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -88,17 +48,17 @@ class item extends itembase { protected $options; /** - * @var string Value of the default setting (invite, custom...) + * @var string Text label for the optional option "other" in the form of "$value SURVEYPRO_OTHERSEPARATOR $label" */ - protected $defaultoption; + protected $labelother; /** - * @var string Text label for the optional option "other" in the form of "$value SURVEYPRO_OTHERSEPARATOR $label" + * @var string Value of the default setting (invite, custom...) */ - protected $labelother; + protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -112,6 +72,13 @@ class item extends itembase { */ protected $adjustment; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -144,7 +111,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -176,18 +145,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim trialing spaces from each row of each textarea field. $fieldlist = ['options']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -200,15 +165,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Radio buttons'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'radiobutton_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->labelother $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->adjustment = SURVEYPRO_VERTICAL; } @@ -229,7 +190,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -253,7 +214,7 @@ public function item_list_constraints() { $constraints = []; $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_radiobutton'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -267,15 +228,122 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set adjustment. + * + * @param string $adjustment + * @return void + */ + public function set_adjustment($adjustment) { + $this->adjustment = $adjustment; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. + * + * @return $this->labelother + */ + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get adjustment. + * + * @return $this->adjustment + */ + public function get_adjustment() { + return $this->adjustment; } /** @@ -302,14 +370,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_radiobutton'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -335,31 +416,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - + + @@ -380,7 +442,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = []; $labels = []; @@ -418,7 +480,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -464,7 +526,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -507,61 +569,45 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_radiobutton_'.$this->sortindex; - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' radiobutton_radio'; - $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_radiobutton_'.$this->sortindex; + $basename = $this->itemname; // Begin of: mform element. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { - $attributes['id'] = $idprefix.'_invite'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_invite'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); } } else { - $attributes['id'] = $idprefix.'_ignoreme'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $starsstr, SURVEYPRO_IGNOREMEVALUE, $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $starsstr, SURVEYPRO_IGNOREMEVALUE, $attributes); } - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($labels as $k => $label) { - $attributes['id'] = $idprefix.'_'.$k; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $label, "$k", $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_'.$k; + $elementgroup[] = $mform->createElement('radio', $basename, '', $label, "$k", $attributes); } if (!empty($this->labelother)) { [$othervalue, $otherlabel] = $this->get_other(); $labels['other'] = $otherlabel; - $attributes['id'] = $idprefix.'_other'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $otherlabel, 'other', $attributes); + $attributes['id'] = $baseid.'_other'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $otherlabel, 'other', $attributes); - $attributes['id'] = $idprefix.'_text'; - $attributes['class'] = 'radiobutton_radio'; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); - $mform->disabledIf($this->itemname.'_text', $this->itemname, 'neq', 'other'); + $attributes['id'] = $baseid.'_text'; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); + $mform->disabledIf($basename.'_text', $basename, 'neq', 'other'); } if (!$this->required) { - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'indent-'.$this->indent.' radiobutton_radio'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); } // End of: mform element. @@ -573,7 +619,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: definition of separator. - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); // Begin of: default section. if (!$searchform) { @@ -582,7 +628,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -590,25 +636,25 @@ public function userform_mform_element($mform, $searchform, $readonly) { case SURVEYPRO_CUSTOMDEFAULT: $key = array_search($this->defaultvalue, $labels); if ($key !== false) { - $mform->setDefault($this->itemname, "$key"); + $mform->setDefault($basename, "$key"); } break; case SURVEYPRO_INVITEDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_NOANSWERVALUE); + $mform->setDefault($basename, SURVEYPRO_NOANSWERVALUE); break; default: $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } - // Note: $this->itemname.'_text' has to ALWAYS get a default (if it exists) even if it is not selected. + // Note: $basename.'_text' has to ALWAYS get a default (if it exists) even if it is not selected. if (!empty($this->labelother)) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); } // End of: default section. } @@ -619,7 +665,8 @@ public function userform_mform_element($mform, $searchform, $readonly) { * @return array $separator */ public function userform_get_separator(): array { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); + $optioncount = count($labels); $invitation = ($this->defaultoption == SURVEYPRO_INVITEDEFAULT); $addother = !empty($this->labelother); @@ -680,21 +727,22 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } $errorkey = $this->itemname.'_group'; if ( ($data[$this->itemname] == 'other') && empty($data[$this->itemname.'_text']) ) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_radiobutton'); - return; + return $errors; } // I need to check value is different from SURVEYPRO_INVITEVALUE even if it is not required. if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_optionnotset', 'surveyprofield_radiobutton'); - return; } + + return $errors; } /** @@ -807,7 +855,7 @@ public function userform_get_prefill($fromdb) { } if (isset($fromdb->content)) { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($fromdb->content, $labels)) { $prefill[$this->itemname] = $fromdb->content; } else { @@ -852,7 +900,7 @@ public function userform_db_to_export($answer, $format='') { // Output. switch ($format) { case SURVEYPRO_ITEMSRETURNSVALUES: - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -860,7 +908,7 @@ public function userform_db_to_export($answer, $format='') { } break; case SURVEYPRO_ITEMRETURNSLABELS: - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -888,4 +936,24 @@ public function userform_get_root_elements_name() { return $elementnames; } + + // MARK other. + + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } } diff --git a/field/radiobutton/classes/itemsetupform.php b/field/radiobutton/classes/itemsetupform.php index 56c984b5570..617263a2ecc 100644 --- a/field/radiobutton/classes/itemsetupform.php +++ b/field/radiobutton/classes/itemsetupform.php @@ -86,7 +86,6 @@ public function definition() { // Item: defaultvalue. $fieldname = 'defaultvalue'; - $elementgroup = []; $mform->addElement('text', $fieldname, ''); $mform->disabledIf($fieldname, 'defaultoption', 'neq', SURVEYPRO_CUSTOMDEFAULT); $mform->setType($fieldname, PARAM_RAW); @@ -166,6 +165,10 @@ public function validation($data, $files) { if (count($values) != count($arrayunique)) { $errors['options'] = get_string('ierr_valuesduplicated', 'surveyprofield_radiobutton'); } + // A single option is not allowed. + if (count($arrayunique) == 1) { + $errors['options'] = get_string('ierr_singleoption', 'surveyprofield_radiobutton'); + } // Each single label has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { diff --git a/field/radiobutton/db/install.xml b/field/radiobutton/db/install.xml index 333829bbf39..0cb502e502c 100644 --- a/field/radiobutton/db/install.xml +++ b/field/radiobutton/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/radiobutton/db/upgrade.php b/field/radiobutton/db/upgrade.php index f12d0ff9e1d..45261971031 100644 --- a/field/radiobutton/db/upgrade.php +++ b/field/radiobutton/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_radiobutton_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Radiobutton savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'radiobutton'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_radiobutton. + $table = new xmldb_table('surveyprofield_radiobutton'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_radiobutton} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Radiobutton savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'radiobutton'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_radiobutton'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_radiobutton. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_radiobutton} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Radiobutton savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'radiobutton'); + } + return true; } diff --git a/field/radiobutton/lang/en/surveyprofield_radiobutton.php b/field/radiobutton/lang/en/surveyprofield_radiobutton.php index 566a6abb490..c3ce45f290c 100644 --- a/field/radiobutton/lang/en/surveyprofield_radiobutton.php +++ b/field/radiobutton/lang/en/surveyprofield_radiobutton.php @@ -23,26 +23,28 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['adjustment'] = 'Adjustment'; +$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['allowed'] = 'allowed'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['horizontal'] = 'horizontal'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; -$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_labelsduplicated'] = 'Labels must be different each other'; +$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; +$string['ierr_singleoption'] = 'A single option is not allowed'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding radio button, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding radio button, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[label]'; $string['pluginname'] = 'Radio button'; +$string['privacy:metadata'] = 'The "Radio button" field plugin does not store any personal data.'; $string['returnlabels'] = 'label of selected items'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected items'; @@ -50,4 +52,3 @@ $string['uerr_optionnotset'] = 'Please choose an option'; $string['userfriendlypluginname'] = 'Radio buttons'; $string['vertical'] = 'vertical'; -$string['privacy:metadata'] = 'The "Radio button" field plugin does not store any personal data.'; diff --git a/field/radiobutton/mform/radiobutton.php b/field/radiobutton/mform/radiobutton.php deleted file mode 100644 index c15ba2a7624..00000000000 --- a/field/radiobutton/mform/radiobutton.php +++ /dev/null @@ -1,85 +0,0 @@ -. - -/** - * radio mform element - * - * Extends the core mform class for a radio type element - * - * @package surveyprofield_radiobutton - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -global $CFG; - -require_once($CFG->libdir.'/form/radio.php'); - -// @codingStandardsIgnoreFile - -/** - * radio form element - * - * HTML class for a radio type element - * - * @package surveyprofield_radiobutton - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_radiobutton extends \MoodleQuickForm_radio { - - /** - * Class constructor. - * - * @param string $elementName Optional name of the radio element - * @param string $elementLabel Optional label for radio element - * @param string $text Optional Text to put after the radio element - * @param string $value Optional default value - * @param mixed $attributes Optional Either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $text, $value, $attributes); - } - - /** - * Slightly different container template when frozen. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns the disabled field. Accessibility: the return "( )" from parent - * class is not acceptable for screenreader users, and we DO want a label - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/radiobutton/tests/behat/itemform.feature b/field/radiobutton/tests/behat/itemform.feature index ac4eb59ee49..36a14ae166f 100644 --- a/field/radiobutton/tests/behat/itemform.feature +++ b/field/radiobutton/tests/behat/itemform.feature @@ -85,11 +85,11 @@ Feature: Create a radiobutton item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Which summer holidays place do you prefer?" - Then the field "id_surveypro_field_radiobutton_2_0" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_1" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_2" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_3" matches value "1" - Then the field "id_surveypro_field_radiobutton_2_4" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_other" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_text" matches value "specify" + Then the field "id_field_radiobutton_2_0" matches value "0" + Then the field "id_field_radiobutton_2_1" matches value "0" + Then the field "id_field_radiobutton_2_2" matches value "0" + Then the field "id_field_radiobutton_2_3" matches value "1" + Then the field "id_field_radiobutton_2_4" matches value "0" + Then the field "id_field_radiobutton_2_other" matches value "0" + Then the field "id_field_radiobutton_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/radiobutton/tests/behat/submit_radiobutton.feature b/field/radiobutton/tests/behat/submit_radiobutton.feature index d671c7a535c..339338d397a 100644 --- a/field/radiobutton/tests/behat/submit_radiobutton.feature +++ b/field/radiobutton/tests/behat/submit_radiobutton.feature @@ -58,8 +58,8 @@ Feature: Submit using a radiobutton item # student1 submits And I set the following fields to these values: - | id_surveypro_field_radiobutton_1_3 | 1 | - | id_surveypro_field_radiobutton_2_2 | 1 | + | id_field_radiobutton_1_3 | 1 | + | id_field_radiobutton_2_2 | 1 | And I press "Submit" diff --git a/field/radiobutton/tests/behat/two_option_test.feature b/field/radiobutton/tests/behat/two_option_test.feature index e5ceed28398..51ef7cf6171 100644 --- a/field/radiobutton/tests/behat/two_option_test.feature +++ b/field/radiobutton/tests/behat/two_option_test.feature @@ -1,8 +1,8 @@ @mod @mod_surveypro -Feature: Load and apply mum_or_dad_test usertemplates to test preview do not rise up errors +Feature: Load and apply mum_or_dad usertemplates to test preview do not rise up errors In order to test correct preview As teacher1 - I load mum_or_dad_test usertemplates and ask for preview + I load mum_or_dad usertemplates and ask for preview @javascript @_file_upload Scenario: Test mum or dad displays correctly @@ -23,7 +23,7 @@ Feature: Load and apply mum_or_dad_test usertemplates to test preview do not ris # now I am in the "Manage" page And I select "Import" from the "jump" singleselect - And I upload "mod/surveypro/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml" file to "Choose files to import" filemanager + And I upload "mod/surveypro/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml" file to "Choose files to import" filemanager And I set the field "Sharing level" to "This course" And I press "Import" @@ -33,7 +33,7 @@ Feature: Load and apply mum_or_dad_test usertemplates to test preview do not ris And I select "Apply" from the "jump" singleselect And I set the following fields to these values: - | User templates | (This course) mum_or_dad_test.xml | + | User templates | (This course) mum_or_dad.xml | | id_action_0 | 1 | And I press "Apply" diff --git a/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml b/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml similarity index 90% rename from field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml rename to field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml index f2c052a2032..10d4b42896b 100644 --- a/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml +++ b/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml @@ -1,18 +1,18 @@ - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_test_01 + 0 + 0 + 0 + + Mum Dad 1 @@ -21,19 +21,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_02 + 0 + 0 + 0 + + Mum Dad 2 @@ -41,19 +41,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_04 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -63,19 +63,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_05 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -84,19 +84,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_07 + 0 + 0 + 0 + + Mum Dad 1 @@ -105,19 +105,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_08 + 0 + 0 + 0 + + Mum Dad 2 @@ -125,19 +125,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_09 + 0 + 0 + 0 + + Mum Dad 3 @@ -145,19 +145,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_10 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -167,19 +167,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_11 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -188,19 +188,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_12 + 0 + 0 + 0 + + Mum Dad Other (please, specify) diff --git a/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml b/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml similarity index 92% rename from field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml rename to field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml index 9e2102cb8b9..35857f36e42 100644 --- a/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml +++ b/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>RADIO BUTTON</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>radio button specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li><li>Adjustment</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RADIO BUTTON</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>radio button specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li><li>Adjustment</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -41,6 +36,11 @@ 0 1 radiobutton_001 + 0 + 0 + 0 + + sea mountain lake @@ -51,27 +51,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -79,6 +74,11 @@ desert 0 2 radiobutton_002 + 0 + 0 + 0 + + sea mountain lake @@ -89,27 +89,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -117,6 +112,11 @@ desert 0 3 radiobutton_003 + 0 + 0 + 0 + + sea mountain lake @@ -127,27 +127,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -155,6 +150,11 @@ desert 0 4 radiobutton_004 + 0 + 0 + 0 + + sea mountain lake @@ -166,27 +166,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -194,6 +189,11 @@ desert 0 5 radiobutton_005 + 0 + 0 + 0 + + sea mountain lake @@ -205,27 +205,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -233,6 +228,11 @@ desert 0 6 radiobutton_006 + 0 + 0 + 0 + + sea mountain lake @@ -244,27 +244,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -272,6 +267,11 @@ desert 0 7 radiobutton_007 + 0 + 0 + 0 + + sea mountain lake @@ -283,27 +283,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -311,6 +306,11 @@ desert 0 8 radiobutton_008 + 0 + 0 + 0 + + sea mountain lake @@ -322,27 +322,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -350,6 +345,11 @@ desert 0 9 radiobutton_009 + 0 + 0 + 0 + + sea mountain lake @@ -362,27 +362,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -390,6 +385,11 @@ desert 0 10 radiobutton_010 + 0 + 0 + 0 + + sea mountain lake @@ -402,27 +402,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the defaultis set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the defaultis set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -430,6 +425,11 @@ desert 0 11 radiobutton_012 + 0 + 0 + 0 + + sea mountain lake @@ -442,27 +442,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -470,6 +465,11 @@ desert 0 12 radiobutton_011 + 0 + 0 + 0 + + sea mountain lake @@ -482,27 +482,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -510,6 +505,11 @@ desert 0 13 radiobutton_013 + 0 + 0 + 0 + + sea mountain lake diff --git a/field/radiobutton/version.php b/field/radiobutton/version.php index a225b45b524..15a0a646125 100644 --- a/field/radiobutton/version.php +++ b/field/radiobutton/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_radiobutton'; // Full name of the plugin (used for diagnostics). diff --git a/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php b/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php index f2f5d09882a..20d6c0c3724 100644 --- a/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php +++ b/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'rate'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginrate = new backup_nested_element('surveyprofield_rate', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates', ]); + 'options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/rate/classes/item.php b/field/rate/classes/item.php index bed770ad029..a407009ab3d 100644 --- a/field/rate/classes/item.php +++ b/field/rate/classes/item.php @@ -40,52 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -103,7 +58,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -122,6 +77,13 @@ class item extends itembase { */ protected $differentrates; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -154,9 +116,11 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['insearchform'] = false; - $this->insetupform['position'] = SURVEYPRO_POSITIONLEFT; + // $this->insetupform['position'] = SURVEYPRO_POSITIONLEFT; <-- What does it mean? if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -187,19 +151,15 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. + // Set custom fields values as defined by this specific plugin. // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options', 'rates', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -212,17 +172,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Rate'; - $record->contentformat = 1; - $record->position = 1; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'rate_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; $record->rates = "up\ndown"; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->style = 0; $record->differentrates = 0; @@ -244,7 +198,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -254,7 +208,7 @@ public function item_custom_fields_to_db($record) { // 3. Set values corresponding to checkboxes. // Take care: 'required', 'hideinstructions' were already considered in get_common_settings. - $checkboxes = ['hideinstructions', 'differentrates']; + $checkboxes = ['differentrates']; foreach ($checkboxes as $checkbox) { $record->{$checkbox} = (isset($record->{$checkbox})) ? 1 : 0; } @@ -271,15 +225,141 @@ public function item_left_position_allowed() { return false; } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set rates. + * + * @param string $rates + * @return void + */ + public function set_rates($rates) { + $this->rates = $rates; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set style. + * + * @param string $style + * @return void + */ + public function set_style($style) { + $this->style = $style; + } + + /** + * Set differentrates. + * + * @param string $differentrates + * @return void + */ + public function set_differentrates($differentrates) { + $this->differentrates = $differentrates; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get rates. + * + * @return $this->rates + */ + public function get_rates() { + return $this->rates; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get style. + * + * @return $this->style + */ + public function get_style() { + return $this->style; + } + + /** + * Get differentrates. + * + * @return $this->differentrates + */ + public function get_differentrates() { + return $this->differentrates; } /** @@ -306,14 +386,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'rates', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_rate'] = ['options', 'rates', 'defaultvalue']; return $fieldlist; } @@ -330,32 +423,13 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - - + + + @@ -381,10 +455,14 @@ public function userform_mform_element($mform, $searchform, $readonly) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $options = $utilityitemman->multilinetext_to_array($this->options); $optioncount = count($options) - 1; - $rates = $this->get_content_array(SURVEYPRO_LABELS, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_LABELS, 'rates'); $defaultvalues = $utilityitemman->multilinetext_to_array($this->defaultvalue); - $idprefix = 'id_surveypro_field_rate_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_rate_'.$this->sortindex; + $elementgroup = []; + $attributes = []; + $basename = $this->itemname; if (($this->defaultoption == SURVEYPRO_INVITEDEFAULT)) { if ($this->style == SURVEYPROFIELD_RATE_USERADIO) { @@ -394,18 +472,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { } } - $attributes = []; if ($this->style == SURVEYPROFIELD_RATE_USERADIO) { foreach ($options as $row => $option) { - $attributes['class'] = 'indent-'.$this->indent.' rate_radio'; - $uniquename = $this->itemname.'_'.$row; $elementgroup = []; + $uniquename = $basename.'_'.$row; foreach ($rates as $col => $rate) { - $attributes['id'] = $idprefix.'_'.$row.'_'.$col; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $uniquename, '', $rate, $col, $attributes); - $attributes['class'] = 'rate_radio'; + $attributes['id'] = $baseid.'_'.$row.'_'.$col; + $elementgroup[] = $mform->createElement('radio', $uniquename, '', $rate, $col, $attributes); } - $mform->addGroup($elementgroup, $uniquename.'_group', $option, ' ', false); + $mform->addGroup($elementgroup, $uniquename.'_group', $option, ' ', false, $class); // Don' add a colorunifier div after the last rate element. if ($row < $optioncount) { @@ -415,12 +490,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { } if ($this->style == SURVEYPROFIELD_RATE_USESELECT) { - $attributes['class'] = 'indent-'.$this->indent.' rate_select'; foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; - $attributes['id'] = $idprefix.'_'.$row; - $elementgroup = [$mform->createElement('select', $uniquename, '', $rates, $attributes)]; - $mform->addGroup($elementgroup, $uniquename.'_group', $option, '', false); + $elementgroup = []; + $uniquename = $basename.'_'.$row; + $attributes['id'] = $baseid.'_'.$row; + $elementgroup[] = $mform->createElement('select', $uniquename, '', $rates, $attributes); + $mform->addGroup($elementgroup, $uniquename.'_group', $option, '', false, $class); // Don't add a colorunifier div after the last rate element. if ($row < $optioncount) { @@ -432,14 +507,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { if (!$this->required) { // This is the last if it exists. $this->item_add_color_unifier($mform); - // Bloody hack to align the noanswer checkbox according to the indent. $elementgroup = []; - $uniquename = 'checkbox'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'indent-'.$this->indent.' rate_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $uniquename, '', $noanswerstr, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_noanswer'); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_noanswer', '', $noanswerstr, $attributes); + $mform->addGroup($elementgroup, $basename.'_noanswer_group', $noanswerstr, '', false, $class); } if ($this->required) { @@ -447,35 +519,35 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $mform->_required[] = $this->itemname.'_extrarow'; + $mform->_required[] = $basename.'_extrarow_group'; } else { - // Disable if $this->itemname.'_noanswer' is selected. + // Disable if $basename.'_noanswer' is selected. $optionindex = 0; foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row.'_group'; - $mform->disabledIf($uniquename, $this->itemname.'_noanswer[checkbox]', 'checked'); + $uniquename = $basename.'_'.$row; + $mform->disabledIf($uniquename, $basename.'_noanswer', 'checked'); } if ($this->defaultoption == SURVEYPRO_NOANSWERDEFAULT) { - $mform->setDefault($this->itemname.'_noanswer[checkbox]', '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; + $uniquename = $basename.'_'.$row; $defaultindex = array_search($defaultvalues[$row], $rates); $mform->setDefault($uniquename, "$defaultindex"); } break; case SURVEYPRO_INVITEDEFAULT: foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; + $uniquename = $basename.'_'.$row; $mform->setDefault($uniquename, SURVEYPRO_INVITEVALUE); } break; case SURVEYPRO_NOANSWERDEFAULT: - $uniquename = $this->itemname.'_noanswer[checkbox]'; + $uniquename = $basename.'_noanswer[checkbox]'; $mform->setDefault($uniquename, 1); break; default: @@ -497,14 +569,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } // If different rates were requested, it is time to verify this. $utilityitemman = new utility_item($this->cm, $this->surveypro); $options = $utilityitemman->multilinetext_to_array($this->options); if ((isset($data[$this->itemname.'_noanswer']['checkbox'])) && ($data[$this->itemname.'_noanswer']['checkbox'] == 1)) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $return = false; @@ -517,11 +589,11 @@ public function userform_mform_validation($data, &$errors, $searchform) { } } if ($return) { - return; + return $errors; } if (!empty($this->differentrates)) { - $optionscount = count($this->get_content_array(SURVEYPRO_LABELS, 'options')); + $optionscount = count($this->get_textarea_content(SURVEYPRO_LABELS, 'options')); $rates = []; for ($i = 0; $i < $optionscount; $i++) { $rates[] = $data[$this->itemname.'_'.$i]; @@ -535,6 +607,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$elementname] = get_string('uerr_duplicaterate', 'surveyprofield_rate'); } } + + return $errors; } /** @@ -638,9 +712,9 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); - $rates = $this->get_content_array(SURVEYPRO_VALUES, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_VALUES, 'rates'); foreach ($labels as $col => $label) { $index = $answers[$col]; $output[] = $label.SURVEYPROFIELD_RATE_VALUERATESEPARATOR.$rates[$index]; @@ -650,9 +724,9 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); - $rates = $this->get_content_array(SURVEYPRO_LABELS, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_LABELS, 'rates'); foreach ($labels as $col => $label) { $index = $answers[$col]; $output[] = $label.SURVEYPROFIELD_RATE_VALUERATESEPARATOR.$rates[$index]; @@ -688,7 +762,7 @@ public function userform_get_root_elements_name() { } if (!$this->required) { - $elementnames[] = $this->itemname.'_noanswer[checkbox]'; + $elementnames[] = $this->itemname.'_noanswer'; } return $elementnames; diff --git a/field/rate/classes/itemsetupform.php b/field/rate/classes/itemsetupform.php index cdc5e34f24b..1c0e4f8e5c4 100644 --- a/field/rate/classes/itemsetupform.php +++ b/field/rate/classes/itemsetupform.php @@ -160,13 +160,21 @@ public function validation($data, $files) { // Each single label has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { - $errors['rates'] = get_string('ierr_labelsduplicated', 'surveyprofield_rate'); + $errors['options'] = get_string('ierr_labelsduplicated', 'surveyprofield_rate'); + } + // A single option is not allowed. + if (count($cleanoptions) == 1) { + $errors['options'] = get_string('ierr_singleoption', 'surveyprofield_rate'); } // Each single value has to be unique. $arrayunique = array_unique($values); if (count($values) != count($arrayunique)) { $errors['rates'] = get_string('ierr_valuesduplicated', 'surveyprofield_rate'); } + // A single rate is not allowed. + if (count($cleanrates) == 1) { + $errors['rates'] = get_string('ierr_singlerate', 'surveyprofield_rate'); + } // Each single option has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { diff --git a/field/rate/db/install.xml b/field/rate/db/install.xml index 6bb9162820b..1ed46323ef0 100644 --- a/field/rate/db/install.xml +++ b/field/rate/db/install.xml @@ -1,36 +1,20 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/field/rate/db/upgrade.php b/field/rate/db/upgrade.php index 0f40b3a2c97..a3e2263f0d3 100644 --- a/field/rate/db/upgrade.php +++ b/field/rate/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_rate_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Rate savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'rate'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_rate. + $table = new xmldb_table('surveyprofield_rate'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_rate} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Rate savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'rate'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_rate'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_rate. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_rate} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Rate savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'rate'); + } + return true; } diff --git a/field/rate/lang/en/surveyprofield_rate.php b/field/rate/lang/en/surveyprofield_rate.php index bdfa6eabe58..edcbf0c3563 100644 --- a/field/rate/lang/en/surveyprofield_rate.php +++ b/field/rate/lang/en/surveyprofield_rate.php @@ -24,33 +24,35 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['differentrates_help'] = 'Force the user to rate each element with a different value'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['differentrates'] = 'Force different rates'; +$string['differentrates_help'] = 'Force the user to rate each element with a different value'; $string['diffratesrequired'] = 'Scores are supposed to be different each other'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['ierr_defaultsduplicated'] = 'Defaults have to be different when different rates is required'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among rates'; $string['ierr_invaliddefaultscount'] = 'Number of defaults has to be equal to the number of options'; +$string['ierr_labelsduplicated'] = 'Rates must be different each other'; $string['ierr_notenoughrates'] = 'Number of rates is not enough to force different rates'; -$string['ierr_defaultsduplicated'] = 'Defaults have to be different when different rates is required'; -$string['options_help'] = 'The list of the options for this item.'; +$string['ierr_optionsduplicated'] = 'Options must be different each other'; +$string['ierr_singleoption'] = 'A single option is not allowed'; +$string['ierr_singlerate'] = 'A single rate is not allowed'; +$string['ierr_valuesduplicated'] = 'Values must be different each other'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item.'; $string['pluginname'] = 'Rate'; -$string['rates_help'] = 'The list of values to rate the options of this question. You can choose to write them with the format: value::label. The label will be displayed on the screen, the value will be stored in the survey field. If you only specify one word per line, value and label will both be valued to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; +$string['privacy:metadata'] = 'The "Rate" field plugin does not store any personal data.'; $string['rates'] = 'Rates'; +$string['rates_help'] = 'The list of values to rate the options of this question. You can choose to write them with the format: value::label. The label will be displayed on the screen, the value will be stored in the survey field. If you only specify one word per line, value and label will both be valued to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['returnlabels'] = 'list of options with corresponding labels of rates'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'list of options with corresponding values of rates'; -$string['style_help'] = 'You can choose whether you want to allow the rate of elements using drop down menus or radio button. The overall result will be affected by this option.'; $string['style'] = 'Element style'; +$string['style_help'] = 'You can choose whether you want to allow the rate of elements using drop down menus or radio button. The overall result will be affected by this option.'; $string['uerr_duplicaterate'] = 'Duplicate rate is not allowed'; $string['uerr_optionnotset'] = 'Please choose an option'; $string['usemenu'] = 'dropdown menu'; $string['useradio'] = 'radio buttons'; $string['userfriendlypluginname'] = 'Rate'; -$string['ierr_labelsduplicated'] = 'Rates must be different each other'; -$string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['ierr_optionsduplicated'] = 'Options must be different each other'; -$string['privacy:metadata'] = 'The "Rate" field plugin does not store any personal data.'; diff --git a/field/rate/tests/behat/itemform.feature b/field/rate/tests/behat/itemform.feature index a324b1a30bd..127694baaa7 100644 --- a/field/rate/tests/behat/itemform.feature +++ b/field/rate/tests/behat/itemform.feature @@ -42,9 +42,9 @@ Feature: Create a rate item | Parent content | 1 | | Element style | dropdown menu | And I set the multiline field "Options" to "\nItalian\n\n\n Spanish\nEnglish\nFrench\n\n\nGerman\n\nDeutch\n\n" - And I set the multiline field "Rates" to " Mother tongue\nVery confident\n\nNot enought\n\n\n\n\nCompletely unknown\n\n" + And I set the multiline field "Rates" to " Mother tongue\nVery confident\n\nSomewhat confident\n\n\n\n\nNot confident at all\n\n" And I set the field "id_defaultoption_1" to "1" - And I set the multiline field "id_defaultvalue" to "Not enought\n\n\n Not enought\n\n\n\nNot enought\nNot enought\n\n\n" + And I set the multiline field "id_defaultvalue" to "Somewhat confident\n\n\n Somewhat confident\n\n\n\nSomewhat confident\nSomewhat confident\n\n\n" And I set the following fields to these values: | Download format | list of options with corresponding values of rates | | Force different rates | 1 | @@ -52,16 +52,16 @@ Feature: Create a rate item Then I should see "Number of rates is not enough to force different rates" Then I should see "Defaults have to be different when different rates is required" - And I set the multiline field "Rates" to "\n\n Mother tongue\nVery confident\n\n\n100 words vocabulary\n\nNot enought\nReally ridicolous\n\nCompletely unknown\n\n\n" - And I set the multiline field "id_defaultvalue" to "\n\nCompletely unknown\n\n Absolutely ridicolous\nNot enought\n\n\n100 words vocabulary\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\nVery confident\n\n\n100 words vocabulary\n\nSomewhat confident\nReally ridicolous\n\nNot confident at all\n\n\n" + And I set the multiline field "id_defaultvalue" to "\n\nNot confident at all\n\n Absolutely ridicolous\nSomewhat confident\n\n\n100 words vocabulary\n" And I press "Add" Then I should see "The default item \"Absolutely ridicolous\" was not found among rates" - And I set the multiline field "id_defaultvalue" to "\n Completely unknown\nReally ridicolous\n\n\nNot enought\n\n\n100 words vocabulary\n" + And I set the multiline field "id_defaultvalue" to "\n Not confident at all\nReally ridicolous\n\n\nSomewhat confident\n\n\n100 words vocabulary\n" And I press "Add" Then I should see "Number of defaults has to be equal to the number of options" - And I set the multiline field "id_defaultvalue" to "\n Completely unknown\nReally ridicolous\n\n\nNot enought\n\n\n100 words vocabulary\nVery confident\nMother tongue\n\n\n\n\n" + And I set the multiline field "id_defaultvalue" to "\n Not confident at all\nReally ridicolous\n\n\nSomewhat confident\n\n\n100 words vocabulary\nVery confident\nMother tongue\n\n\n\n\n" And I press "Add" And I follow "edit_item_2" @@ -91,16 +91,16 @@ Feature: Create a rate item Mother tongue Very confident 100 words vocabulary - Not enought + Somewhat confident Really ridicolous - Completely unknown + Not confident at all """ Then the field "id_defaultoption_1" matches value "1" Then the field "defaultvalue" matches multiline: """ - Completely unknown + Not confident at all Really ridicolous - Not enought + Somewhat confident 100 words vocabulary Very confident Mother tongue @@ -113,12 +113,12 @@ Feature: Create a rate item And I select "Preview" from the "jump" singleselect Then I should see "II.a" Then I should see "How confident are you with the following languages?" - Then the field "id_surveypro_field_rate_2_0" matches value "Completely unknown" - Then the field "id_surveypro_field_rate_2_1" matches value "Really ridicolous" - Then the field "id_surveypro_field_rate_2_2" matches value "Not enought" - Then the field "id_surveypro_field_rate_2_3" matches value "100 words vocabulary" - Then the field "id_surveypro_field_rate_2_4" matches value "Very confident" - Then the field "id_surveypro_field_rate_2_5" matches value "Mother tongue" + Then the field "id_field_rate_2_0" matches value "Not confident at all" + Then the field "id_field_rate_2_1" matches value "Really ridicolous" + Then the field "id_field_rate_2_2" matches value "Somewhat confident" + Then the field "id_field_rate_2_3" matches value "100 words vocabulary" + Then the field "id_field_rate_2_4" matches value "Very confident" + Then the field "id_field_rate_2_5" matches value "Mother tongue" Then I should see "Additional note" And I select "Elements" from the "jump" singleselect @@ -137,45 +137,45 @@ Feature: Create a rate item And I select "Preview" from the "jump" singleselect Then I should see "II.b" - Then the field "id_surveypro_field_rate_3_0_0" matches value "0" - Then the field "id_surveypro_field_rate_3_0_1" matches value "0" - Then the field "id_surveypro_field_rate_3_0_2" matches value "0" - Then the field "id_surveypro_field_rate_3_0_3" matches value "0" - Then the field "id_surveypro_field_rate_3_0_4" matches value "0" - Then the field "id_surveypro_field_rate_3_0_5" matches value "1" + Then the field "id_field_rate_3_0_0" matches value "0" + Then the field "id_field_rate_3_0_1" matches value "0" + Then the field "id_field_rate_3_0_2" matches value "0" + Then the field "id_field_rate_3_0_3" matches value "0" + Then the field "id_field_rate_3_0_4" matches value "0" + Then the field "id_field_rate_3_0_5" matches value "1" - Then the field "id_surveypro_field_rate_3_1_0" matches value "0" - Then the field "id_surveypro_field_rate_3_1_1" matches value "0" - Then the field "id_surveypro_field_rate_3_1_2" matches value "0" - Then the field "id_surveypro_field_rate_3_1_3" matches value "0" - Then the field "id_surveypro_field_rate_3_1_4" matches value "1" - Then the field "id_surveypro_field_rate_3_1_5" matches value "0" + Then the field "id_field_rate_3_1_0" matches value "0" + Then the field "id_field_rate_3_1_1" matches value "0" + Then the field "id_field_rate_3_1_2" matches value "0" + Then the field "id_field_rate_3_1_3" matches value "0" + Then the field "id_field_rate_3_1_4" matches value "1" + Then the field "id_field_rate_3_1_5" matches value "0" - Then the field "id_surveypro_field_rate_3_2_0" matches value "0" - Then the field "id_surveypro_field_rate_3_2_1" matches value "0" - Then the field "id_surveypro_field_rate_3_2_2" matches value "0" - Then the field "id_surveypro_field_rate_3_2_3" matches value "1" - Then the field "id_surveypro_field_rate_3_2_4" matches value "0" - Then the field "id_surveypro_field_rate_3_2_5" matches value "0" + Then the field "id_field_rate_3_2_0" matches value "0" + Then the field "id_field_rate_3_2_1" matches value "0" + Then the field "id_field_rate_3_2_2" matches value "0" + Then the field "id_field_rate_3_2_3" matches value "1" + Then the field "id_field_rate_3_2_4" matches value "0" + Then the field "id_field_rate_3_2_5" matches value "0" - Then the field "id_surveypro_field_rate_3_3_0" matches value "0" - Then the field "id_surveypro_field_rate_3_3_1" matches value "0" - Then the field "id_surveypro_field_rate_3_3_2" matches value "1" - Then the field "id_surveypro_field_rate_3_3_3" matches value "0" - Then the field "id_surveypro_field_rate_3_3_4" matches value "0" - Then the field "id_surveypro_field_rate_3_3_5" matches value "0" + Then the field "id_field_rate_3_3_0" matches value "0" + Then the field "id_field_rate_3_3_1" matches value "0" + Then the field "id_field_rate_3_3_2" matches value "1" + Then the field "id_field_rate_3_3_3" matches value "0" + Then the field "id_field_rate_3_3_4" matches value "0" + Then the field "id_field_rate_3_3_5" matches value "0" - Then the field "id_surveypro_field_rate_3_4_0" matches value "0" - Then the field "id_surveypro_field_rate_3_4_1" matches value "1" - Then the field "id_surveypro_field_rate_3_4_2" matches value "0" - Then the field "id_surveypro_field_rate_3_4_3" matches value "0" - Then the field "id_surveypro_field_rate_3_4_4" matches value "0" - Then the field "id_surveypro_field_rate_3_4_5" matches value "0" + Then the field "id_field_rate_3_4_0" matches value "0" + Then the field "id_field_rate_3_4_1" matches value "1" + Then the field "id_field_rate_3_4_2" matches value "0" + Then the field "id_field_rate_3_4_3" matches value "0" + Then the field "id_field_rate_3_4_4" matches value "0" + Then the field "id_field_rate_3_4_5" matches value "0" - Then the field "id_surveypro_field_rate_3_5_0" matches value "1" - Then the field "id_surveypro_field_rate_3_5_1" matches value "0" - Then the field "id_surveypro_field_rate_3_5_2" matches value "0" - Then the field "id_surveypro_field_rate_3_5_3" matches value "0" - Then the field "id_surveypro_field_rate_3_5_4" matches value "0" - Then the field "id_surveypro_field_rate_3_5_5" matches value "0" + Then the field "id_field_rate_3_5_0" matches value "1" + Then the field "id_field_rate_3_5_1" matches value "0" + Then the field "id_field_rate_3_5_2" matches value "0" + Then the field "id_field_rate_3_5_3" matches value "0" + Then the field "id_field_rate_3_5_4" matches value "0" + Then the field "id_field_rate_3_5_5" matches value "0" Then I should see "One more additional note" diff --git a/field/rate/tests/behat/submit_rate.feature b/field/rate/tests/behat/submit_rate.feature index b09630f98e1..b9856b7998e 100644 --- a/field/rate/tests/behat/submit_rate.feature +++ b/field/rate/tests/behat/submit_rate.feature @@ -33,7 +33,7 @@ Feature: Submit using a rate item | Element number | 13a | | Element style | radio buttons | And I set the multiline field "Options" to " Italian\nSpanish\n\n\n English\n\n\nFrench\n\nGerman\n\n\n" - And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nNot enought\n\nCompletely unknown\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nSomewhat confident\n\nNot confident at all\n" And I press "Add" And I set the field "typeplugin" to "Rate" @@ -47,7 +47,7 @@ Feature: Submit using a rate item | Element number | 13b | | Element style | dropdown menu | And I set the multiline field "Options" to " Italian\nSpanish\n\n\n English\n\n\nFrench\n\nGerman\n\n\n" - And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nNot enought\n\nCompletely unknown\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nSomewhat confident\n\nNot confident at all\n" And I press "Add" And I log out @@ -58,16 +58,16 @@ Feature: Submit using a rate item # student1 submits And I set the following fields to these values: - | id_surveypro_field_rate_1_0_0 | 1 | - | id_surveypro_field_rate_1_1_1 | 1 | - | id_surveypro_field_rate_1_2_2 | 1 | - | id_surveypro_field_rate_1_3_3 | 1 | - | id_surveypro_field_rate_1_4_2 | 1 | - | id_surveypro_field_rate_2_0 | Mother tongue | - | id_surveypro_field_rate_2_1 | Very confident | - | id_surveypro_field_rate_2_2 | Not enought | - | id_surveypro_field_rate_2_3 | Completely unknown | - | id_surveypro_field_rate_2_4 | Not enought | + | id_field_rate_1_0_0 | 1 | + | id_field_rate_1_1_1 | 1 | + | id_field_rate_1_2_2 | 1 | + | id_field_rate_1_3_3 | 1 | + | id_field_rate_1_4_2 | 1 | + | id_field_rate_2_0 | Mother tongue | + | id_field_rate_2_1 | Very confident | + | id_field_rate_2_2 | Somewhat confident | + | id_field_rate_2_3 | Not confident at all | + | id_field_rate_2_4 | Somewhat confident | And I press "Submit" And I press "Continue to responses list" diff --git a/field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml b/field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml similarity index 89% rename from field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml rename to field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml index b7516012abe..dd56a35bfc0 100644 --- a/field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml +++ b/field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>RATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>rate</b><b> specific setting</b>:</p><ol><li>Element style</li><li>Options</li><li>Rates</li><li>Default</li><li>Download format</li></ol><p>and one <b>validaion option</b></p><ol><li>Force different rate</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>rate</b><b> specific setting</b>:</p><ol><li>Element style</li><li>Options</li><li>Rates</li><li>Default</li><li>Download format</li></ol><p>and one <b>validaion option</b></p><ol><li>Force different rate</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 @@ -42,6 +37,10 @@ 1 1 rate_001 + 0 + 0 + + EN ES IT @@ -56,35 +55,34 @@ unknown 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 2 + 1 1 rate_002 + 0 + 0 + + EN ES IT @@ -99,35 +97,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 3 + 1 1 rate_003 + 0 + 0 + + EN ES IT @@ -146,35 +143,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 4 + 1 1 rate_004 + 0 + 0 + + EN ES IT @@ -193,35 +189,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 5 + 1 1 rate_005 + 0 + 0 + + EN ES IT @@ -236,35 +231,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 6 + 1 1 rate_006 + 0 + 0 + + EN ES IT @@ -279,35 +273,34 @@ unknown 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 7 + 1 1 rate_007 + 0 + 0 + + EN ES IT @@ -322,35 +315,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 8 + 1 1 rate_008 + 0 + 0 + + EN ES IT @@ -369,35 +361,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 9 + 1 1 rate_009 + 0 + 0 + + EN ES IT @@ -416,27 +407,22 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -445,6 +431,10 @@ mother tongue 10 1 rate_010 + 0 + 0 + + EN ES IT diff --git a/field/rate/version.php b/field/rate/version.php index 40f60ada718..fee628b60b8 100644 --- a/field/rate/version.php +++ b/field/rate/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_rate'; // Full name of the plugin (used for diagnostics). diff --git a/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php b/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php index 34ff862d34a..75e9db5bedc 100644 --- a/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php +++ b/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'recurrence'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginrecurrence = new backup_nested_element('surveyprofield_recurrence', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/recurrence/classes/item.php b/field/recurrence/classes/item.php index 3bdcab9ba2c..57c40608745 100644 --- a/field/recurrence/classes/item.php +++ b/field/recurrence/classes/item.php @@ -40,67 +40,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; + // Itembase properties. /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var string Format of the content once downloaded */ - protected $indent; + protected $downloadformat; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the recurrence in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Upperbound for the recurrence in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the recurrence in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Month of the defaultvalue for the recurrence @@ -112,11 +79,6 @@ class item extends itembase { */ protected $defaultvalueday; - /** - * @var int Lowerbound for the recurrence in unixtime - */ - protected $lowerbound; - /** * @var int Month of the lowerbound for the recurrence */ @@ -127,11 +89,6 @@ class item extends itembase { */ protected $lowerboundday; - /** - * @var int Upperbound for the recurrence in unixtime - */ - protected $upperbound; - /** * @var int Month of the upperbound for the recurrence */ @@ -142,6 +99,13 @@ class item extends itembase { */ protected $upperboundday; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -176,7 +140,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -208,14 +174,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -228,16 +190,9 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Recurrence [dd/mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'recurrence_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; - $record->defaultvalue = 43200; + // $record->defaultvalue $record->downloadformat = 'strftime03'; $record->lowerbound = 43200; $record->upperbound = 31492800; @@ -251,7 +206,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_recurrence_to_unix_time($month, $day) { - return (mktime(12, 0, 0, $month, $day, SURVEYPROFIELD_RECURRENCE_YEAROFFSET)); + return (gmmktime(12, 0, 0, $month, $day, SURVEYPROFIELD_RECURRENCE_YEAROFFSET)); } /** @@ -280,7 +235,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -303,15 +258,217 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; } /** @@ -350,14 +507,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvaluemonth', 'defaultvalueday', 'lowerboundmonth', 'lowerboundday', 'upperboundmonth', 'upperboundday', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_recurrence'] = []; return $fieldlist; } @@ -374,30 +547,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -431,8 +585,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_recurrence_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -466,60 +618,50 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $baseid = 'id_field_recurrence_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $basename = $this->itemname; - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' recurrence_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); - - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'recurrence_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'recurrence_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -532,7 +674,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $recurrencearray['mon'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -568,12 +710,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $recurrencearray['mday']); - $mform->setDefault($this->itemname.'_month', $recurrencearray['mon']); + $mform->setDefault($basename.'_day', $recurrencearray['mday']); + $mform->setDefault($basename.'_month', $recurrencearray['mon']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -592,13 +734,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -625,18 +767,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_recurrencenotset', 'surveyprofield_recurrence', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if (!utility_item::date_is_valid($data[$this->itemname.'_day'], $data[$this->itemname.'_month'])) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_recurrence_to_unix_time(1, 1)); @@ -670,6 +812,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_recurrence'); } } + + return $errors; } /** diff --git a/field/recurrence/db/install.xml b/field/recurrence/db/install.xml index 8c6b86abc60..6bd334cb249 100644 --- a/field/recurrence/db/install.xml +++ b/field/recurrence/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/recurrence/db/upgrade.php b/field/recurrence/db/upgrade.php index 70d6109dea4..640c8ac4384 100644 --- a/field/recurrence/db/upgrade.php +++ b/field/recurrence/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_recurrence_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Recurrence savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'recurrence'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_recurrence. + $table = new xmldb_table('surveyprofield_recurrence'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_recurrence} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Recurrence savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'recurrence'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_recurrence'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_recurrence. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_recurrence} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Recurrence savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'recurrence'); + } + return true; } diff --git a/field/recurrence/lang/en/surveyprofield_recurrence.php b/field/recurrence/lang/en/surveyprofield_recurrence.php index 0ecebbb9c2b..0d3ca93dd68 100644 --- a/field/recurrence/lang/en/surveyprofield_recurrence.php +++ b/field/recurrence/lang/en/surveyprofield_recurrence.php @@ -25,19 +25,20 @@ $string['currentrecurrencedefault'] = 'Current date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the recurrence the remote user will find answered by default. The default for this type of question is mandatory. If "Current recurrence" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the recurrence the remote user will find answered by default. The default for this type of question is mandatory. If "Current recurrence" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; -$string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['ierr_outofexternalrangedefault'] = 'Default does not fall within the specified range (see "{$a}" help)'; +$string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['inviteday'] = 'Choose a day'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest recurrence the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest recurrence the user is allowed to enter'; $string['pluginname'] = 'Recurrence'; +$string['privacy:metadata'] = 'The "Recurrence" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed be lower-equal than {$a}'; @@ -50,7 +51,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_recurrencenotset'] = 'Please choose a recurrence or select the "{$a}" checkbox'; $string['uerr_recurrencenotsetrequired'] = 'Recurrence is not correctly defined'; -$string['upperbound_help'] = 'The biggest recurrence the user is allowed to enter.

Maximum and minimum values define a range.
If "minimum value" is lower than "maximum value" the user is forced to enter a value falling into the range.
If "minimum value" is greater than "maximum value" the user input is forced out from the range. i.e. the user input is supposed to be lower-equal than the minimum value OR grater-equal than the maximum value.'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest recurrence the user is allowed to enter.

Maximum and minimum values define a range.
If "minimum value" is lower than "maximum value" the user is forced to enter a value falling into the range.
If "minimum value" is greater than "maximum value" the user input is forced out from the range. i.e. the user input is supposed to be lower-equal than the minimum value OR grater-equal than the maximum value.'; $string['userfriendlypluginname'] = 'Recurrence [dd/mm]'; -$string['privacy:metadata'] = 'The "Recurrence" field plugin does not store any personal data.'; diff --git a/field/recurrence/tests/behat/itemform.feature b/field/recurrence/tests/behat/itemform.feature index f139e899940..d76bfa2b3b1 100644 --- a/field/recurrence/tests/behat/itemform.feature +++ b/field/recurrence/tests/behat/itemform.feature @@ -102,6 +102,6 @@ Feature: Create a recurrence item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When do you usually celebrate your name-day?" - Then the field "id_surveypro_field_recurrence_2_day" matches value "1" - Then the field "id_surveypro_field_recurrence_2_month" matches value "February" + Then the field "id_field_recurrence_2_day" matches value "1" + Then the field "id_field_recurrence_2_month" matches value "February" Then I should see "Additional note" diff --git a/field/recurrence/tests/behat/submit_recurrence.feature b/field/recurrence/tests/behat/submit_recurrence.feature index 7d360e06711..2e52d47493c 100644 --- a/field/recurrence/tests/behat/submit_recurrence.feature +++ b/field/recurrence/tests/behat/submit_recurrence.feature @@ -43,8 +43,8 @@ Feature: Submit using a recurrence item # student1 submits And I set the following fields to these values: - | id_surveypro_field_recurrence_1_day | 7 | - | id_surveypro_field_recurrence_1_month | June | + | id_field_recurrence_1_day | 7 | + | id_field_recurrence_1_month | June | And I press "Submit" diff --git a/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml b/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml similarity index 87% rename from field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml rename to field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml index bea3e273d7d..f66e90a2bf8 100644 --- a/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml +++ b/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>RECURRENCE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>and two <b>validaion option</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RECURRENCE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>and two <b>validaion option</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different drecurrenceate or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different drecurrenceate or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 1 - 0 + 1 recurrence_001 + 0 + 0 + 0 + + 2 39600 strftime03 @@ -49,35 +48,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 2 - 0 + 1 recurrence_002 + 0 + 0 + 0 + + 1 13600800 strftime03 @@ -85,35 +83,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 3 - 0 + 1 recurrence_003 + 0 + 0 + 0 + + 4 39600 strftime03 @@ -121,35 +118,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 4 - 0 + 1 recurrence_004 + 0 + 0 + 0 + + 5 39600 strftime03 @@ -157,35 +153,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 5 - 0 + 1 recurrence_005 + 0 + 0 + 0 + + 3 39600 strftime03 @@ -193,35 +188,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 6 - 0 + 1 recurrence_006 + 0 + 0 + 0 + + 2 39600 strftime03 @@ -229,35 +223,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 7 - 0 + 1 recurrence_007 + 0 + 0 + 0 + + 1 13600800 strftime03 @@ -265,35 +258,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 8 - 0 + 1 recurrence_008 + 0 + 0 + 0 + + 4 39600 strftime03 @@ -301,35 +293,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 9 - 0 + 1 recurrence_009 + 0 + 0 + 0 + + 5 39600 strftime03 diff --git a/field/recurrence/version.php b/field/recurrence/version.php index cef76cac69a..39718c4f71a 100644 --- a/field/recurrence/version.php +++ b/field/recurrence/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_recurrence'; // Full name of the plugin (used for diagnostics). diff --git a/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php b/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php index 5fa2e88fcb0..f653fd22f26 100644 --- a/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php +++ b/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'select'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginselect = new backup_nested_element('surveyprofield_select', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', ]); + 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/select/classes/item.php b/field/select/classes/item.php index 5a6191a9f87..f6155a9efdf 100644 --- a/field/select/classes/item.php +++ b/field/select/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -98,7 +58,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -107,6 +67,13 @@ class item extends itembase { */ protected $downloadformat; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -139,7 +106,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -171,18 +140,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -195,15 +160,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Select'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'select_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->labelother $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; } @@ -223,7 +184,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -247,7 +208,7 @@ public function item_list_constraints() { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $constraints = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_select'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -261,15 +222,103 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. * - * @return the content of the static property "canbeparent" + * @return $this->labelother */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; } /** @@ -296,14 +345,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_select'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -329,30 +391,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - + @@ -373,7 +416,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = []; $labels = []; @@ -411,7 +454,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -457,7 +500,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -497,10 +540,14 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_select_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_select_'.$this->sortindex; + $basename = $this->itemname; // Begin of: element values. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $labels = [SURVEYPRO_INVITEVALUE => get_string('choosedots')] + $labels; @@ -517,16 +564,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: element values. - $elementgroup = []; - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' select_select']; - $elementgroup[] = $mform->createElement('select', $this->itemname, '', $labels, $attributes); + $attributes = ['id' => $baseid, 'class' => 'indent-'.$this->indent.' select_select']; + $elementgroup[] = $mform->createElement('select', $basename, '', $labels, $attributes); if ($this->labelother) { - $attributes = ['id' => $idprefix.'_text', 'class' => 'select_select']; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); - $mform->disabledIf($this->itemname.'_text', $this->itemname, 'neq', 'other'); + $attributes = ['id' => $baseid.'_text']; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); + $mform->disabledIf($basename.'_text', $basename, 'neq', 'other'); } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); if (!$searchform) { if ($this->required) { @@ -534,11 +580,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - if ($this->position == SURVEYPRO_POSITIONTOP) { - $starplace = $this->itemname.'_extrarow'; - } else { - $starplace = ($this->labelother) ? $this->itemname.'_group' : $this->itemname; - } + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -546,27 +588,27 @@ public function userform_mform_element($mform, $searchform, $readonly) { switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: if ($key = array_search($this->defaultvalue, $labels)) { - $mform->setDefault($this->itemname, "$key"); + $mform->setDefault($basename, "$key"); } else { - $mform->setDefault($this->itemname, 'other'); + $mform->setDefault($basename, 'other'); } break; case SURVEYPRO_INVITEDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_NOANSWERVALUE); + $mform->setDefault($basename, SURVEYPRO_NOANSWERVALUE); break; default: $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } - // Note: $this->itemname.'_text' has to ALWAYS get a default (if required) even if it is not selected. + // Note: $basename.'_text' has to ALWAYS get a default (if required) even if it is not selected. if (!empty($this->labelother)) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); } } @@ -583,14 +625,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } $errorkey = $this->itemname.'_group'; if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_optionnotset', 'surveyprofield_select'); - return; + return $errors; } if (!empty($this->labelother)) { @@ -598,6 +640,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_select'); } } + + return $errors; } /** @@ -702,7 +746,7 @@ public function userform_get_prefill($fromdb) { } if (isset($fromdb->content)) { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($fromdb->content, $labels)) { $prefill[$this->itemname] = $fromdb->content; } else { @@ -747,7 +791,7 @@ public function userform_db_to_export($answer, $format='') { // Output. switch ($format) { case SURVEYPRO_ITEMSRETURNSVALUES: - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -755,7 +799,7 @@ public function userform_db_to_export($answer, $format='') { } break; case SURVEYPRO_ITEMRETURNSLABELS: - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -783,4 +827,24 @@ public function userform_get_root_elements_name() { return $elementnames; } + + // MARK other. + + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } } diff --git a/field/select/classes/itemsetupform.php b/field/select/classes/itemsetupform.php index ad8c80f8745..d9107836237 100644 --- a/field/select/classes/itemsetupform.php +++ b/field/select/classes/itemsetupform.php @@ -86,7 +86,6 @@ public function definition() { // Item: defaultvalue. $fieldname = 'defaultvalue'; - $elementgroup = []; $mform->addElement('text', $fieldname, null); $mform->setType($fieldname, PARAM_RAW); $mform->disabledIf($fieldname, 'defaultoption', 'neq', SURVEYPRO_CUSTOMDEFAULT); diff --git a/field/select/db/install.xml b/field/select/db/install.xml index be54e5716cc..53513e8c414 100644 --- a/field/select/db/install.xml +++ b/field/select/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/select/db/upgrade.php b/field/select/db/upgrade.php index 7ab7ec5911c..e525d1251f3 100644 --- a/field/select/db/upgrade.php +++ b/field/select/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_select_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Select savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'select'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_select. + $table = new xmldb_table('surveyprofield_select'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_select} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Select savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'select'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_select'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_select. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_select} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Select savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'select'); + } + return true; } diff --git a/field/select/lang/en/surveyprofield_select.php b/field/select/lang/en/surveyprofield_select.php index e765a16e140..6ed5dff5f27 100644 --- a/field/select/lang/en/surveyprofield_select.php +++ b/field/select/lang/en/surveyprofield_select.php @@ -25,25 +25,25 @@ $string['allowed'] = 'allowed'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; -$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_labelsduplicated'] = 'Labels must be different each other'; +$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the drop down menu, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the drop down menu, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[label]'; $string['pluginname'] = 'Select'; +$string['privacy:metadata'] = 'The "Select" field plugin does not store any personal data.'; $string['returnlabels'] = 'label of selected item'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected item'; $string['uerr_missingothertext'] = 'Please add the text required by your selection'; $string['uerr_optionnotset'] = 'Please choose an option'; $string['userfriendlypluginname'] = 'Select'; -$string['privacy:metadata'] = 'The "Select" field plugin does not store any personal data.'; diff --git a/field/select/lang/it/surveyprofield_select.php b/field/select/lang/it/surveyprofield_select.php index 75e650b7755..c1a08f58d2d 100644 --- a/field/select/lang/it/surveyprofield_select.php +++ b/field/select/lang/it/surveyprofield_select.php @@ -23,5 +23,5 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['uerr_optionnotset'] = 'Si selezioni una opzione'; $string['uerr_missingothertext'] = 'Si aggiunga un contenuto al campo corrispondente alla selezione'; +$string['uerr_optionnotset'] = 'Si selezioni una opzione'; diff --git a/field/select/tests/behat/itemform.feature b/field/select/tests/behat/itemform.feature index 5293a317c04..0873a1f1090 100644 --- a/field/select/tests/behat/itemform.feature +++ b/field/select/tests/behat/itemform.feature @@ -83,6 +83,6 @@ Feature: Create a select item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Which summer holidays place do you prefer?" - Then the field "id_surveypro_field_select_2" matches value "other" - Then the field "id_surveypro_field_select_2_text" matches value "specify" + Then the field "id_field_select_2" matches value "other" + Then the field "id_field_select_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/select/tests/behat/submit_select.feature b/field/select/tests/behat/submit_select.feature index a2446591428..90857352654 100644 --- a/field/select/tests/behat/submit_select.feature +++ b/field/select/tests/behat/submit_select.feature @@ -40,17 +40,17 @@ Feature: Submit using a select item And I press "New response" # student1 submits - And I set the field "id_surveypro_field_select_1" to "hills" + And I set the field "id_field_select_1" to "hills" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions # student1 submits And I press "New response" - And I set the field "id_surveypro_field_select_1" to "other (specify)" + And I set the field "id_field_select_1" to "other (specify)" And I press "Submit" Then I should see "Please add the text required by your selection" - And I set the field "id_surveypro_field_select_1_text" to "flying in the sky" + And I set the field "id_field_select_1_text" to "flying in the sky" And I press "Submit" And I press "Continue to responses list" diff --git a/field/select/tests/fixtures/usertemplate/select_only_2015123000.xml b/field/select/tests/fixtures/usertemplate/select_only_2024032800.xml similarity index 92% rename from field/select/tests/fixtures/usertemplate/select_only_2015123000.xml rename to field/select/tests/fixtures/usertemplate/select_only_2024032800.xml index 0dea9b2573f..c5e85aed1d0 100644 --- a/field/select/tests/fixtures/usertemplate/select_only_2015123000.xml +++ b/field/select/tests/fixtures/usertemplate/select_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>SELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>select specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>select specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -41,6 +36,11 @@ 0 1 select_001 + 0 + 0 + 0 + + sea mountain lake @@ -50,27 +50,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -78,6 +73,11 @@ desert 0 2 select_002 + 0 + 0 + 0 + + sea mountain lake @@ -87,27 +87,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -115,6 +110,11 @@ desert 0 3 select_003 + 0 + 0 + 0 + + sea mountain lake @@ -124,27 +124,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -152,6 +147,11 @@ desert 0 4 select_004 + 0 + 0 + 0 + + sea mountain lake @@ -162,27 +162,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -190,6 +185,11 @@ desert 0 5 select_005 + 0 + 0 + 0 + + sea mountain lake @@ -200,27 +200,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -228,6 +223,11 @@ desert 0 6 select_006 + 0 + 0 + 0 + + sea mountain lake @@ -238,27 +238,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -266,6 +261,11 @@ desert 0 7 select_007 + 0 + 0 + 0 + + sea mountain lake @@ -276,27 +276,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -304,6 +299,11 @@ desert 0 8 select_008 + 0 + 0 + 0 + + sea mountain lake @@ -314,27 +314,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -342,6 +337,11 @@ desert 0 9 select_009 + 0 + 0 + 0 + + sea mountain lake @@ -353,27 +353,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -381,6 +376,11 @@ desert 0 10 select_010 + 0 + 0 + 0 + + sea mountain lake @@ -392,27 +392,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -420,6 +415,11 @@ desert 0 11 select_011 + 0 + 0 + 0 + + sea mountain lake @@ -431,27 +431,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -459,6 +454,11 @@ desert 0 12 select_012 + 0 + 0 + 0 + + sea mountain lake @@ -470,27 +470,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -498,6 +493,11 @@ desert 0 13 select_013 + 0 + 0 + 0 + + sea mountain lake diff --git a/field/select/version.php b/field/select/version.php index 454fef755dc..a2d42aeac1c 100644 --- a/field/select/version.php +++ b/field/select/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_select'; // Full name of the plugin (used for diagnostics). diff --git a/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php b/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php index f048d5661a4..881b383561a 100644 --- a/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php +++ b/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'shortdate'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginshortdate = new backup_nested_element('surveyprofield_shortdate', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/shortdate/classes/item.php b/field/shortdate/classes/item.php index bbee1ac61a5..babedfaafd0 100644 --- a/field/shortdate/classes/item.php +++ b/field/shortdate/classes/item.php @@ -39,67 +39,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; + // Itembase properties. /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var string Format of the content once downloaded */ - protected $indent; + protected $downloadformat; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the shortdate in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Lowerbound for the shortdate in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the shortdate in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Month of the defaultvalue for the shortdate @@ -111,11 +78,6 @@ class item extends itembase { */ protected $defaultvalueyear; - /** - * @var int Lowerbound for the shortdate in unixtime - */ - protected $lowerbound; - /** * @var int Month of the lowerbound for the shortdate */ @@ -126,11 +88,6 @@ class item extends itembase { */ protected $lowerboundyear; - /** - * @var int Lowerbound for the shortdate in unixtime - */ - protected $upperbound; - /** * @var int Month of the upperbound for the shortdate */ @@ -141,6 +98,13 @@ class item extends itembase { */ protected $upperboundyear; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -177,7 +141,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_shortdate_to_unix_time(12, $this->surveypro->stopyear); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -209,14 +175,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -229,15 +191,9 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date (short) [mm/yyyy]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'shortdate_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = 'strftime01'; $record->lowerbound = 43200; $record->upperbound = 1606824000; @@ -251,7 +207,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_shortdate_to_unix_time($month, $year) { - return (mktime(12, 0, 0, $month, 1, $year)); + return (gmmktime(12, 0, 0, $month, 1, $year)); } /** @@ -278,7 +234,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -300,15 +256,217 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; } /** @@ -347,14 +505,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'lowerboundyear', 'lowerboundmonth', 'upperboundyear', 'upperboundmonth', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_shortdate'] = []; return $fieldlist; } @@ -371,30 +545,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -428,8 +583,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_shortdate_'.$this->sortindex; - // Begin of: element values. $months = []; $years = []; @@ -455,60 +608,50 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_shortdate_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'indent-'.$this->indent.' shortdate_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); - - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $attributes['class'] = 'shortdate_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'shortdate_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -521,7 +664,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $shortdatearray['year'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -557,12 +700,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_month', $shortdatearray['mon']); - $mform->setDefault($this->itemname.'_year', $shortdatearray['year']); + $mform->setDefault($basename.'_month', $shortdatearray['mon']); + $mform->setDefault($basename.'_year', $shortdatearray['year']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -581,13 +724,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -614,13 +757,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_shortdatenotset', 'surveyprofield_shortdate', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_shortdate_to_unix_time(1, $this->surveypro->startyear)); @@ -641,6 +784,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_shortdate'); } } + + return $errors; } /** diff --git a/field/shortdate/classes/itemsetupform.php b/field/shortdate/classes/itemsetupform.php index fc41dcedec6..602da7881fa 100644 --- a/field/shortdate/classes/itemsetupform.php +++ b/field/shortdate/classes/itemsetupform.php @@ -61,7 +61,7 @@ public function definition() { $fieldname = 'defaultoption'; $months = []; for ($i = 1; $i <= 12; $i++) { - $months[$i] = userdate(mktime(12, 0, 0, $i, 1, 2000), "%B", 0); + $months[$i] = userdate(gmmktime(12, 0, 0, $i, 1, 2000), "%B", 0); } $yearsrange = range($startyear, $stopyear); $years = array_combine($yearsrange, $yearsrange); diff --git a/field/shortdate/db/install.xml b/field/shortdate/db/install.xml index fab3dad8a14..8e088206483 100644 --- a/field/shortdate/db/install.xml +++ b/field/shortdate/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/shortdate/db/upgrade.php b/field/shortdate/db/upgrade.php index e9dd82e7c9d..2be5f2c3ae2 100644 --- a/field/shortdate/db/upgrade.php +++ b/field/shortdate/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_shortdate_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Shortdate savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'shortdate'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_shortdate. + $table = new xmldb_table('surveyprofield_shortdate'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_shortdate} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Shortdate savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'shortdate'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_shortdate'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_shortdate. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_shortdate} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Shortdate savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'shortdate'); + } + return true; } diff --git a/field/shortdate/lang/en/surveyprofield_shortdate.php b/field/shortdate/lang/en/surveyprofield_shortdate.php index b308f625025..75c54889b8b 100644 --- a/field/shortdate/lang/en/surveyprofield_shortdate.php +++ b/field/shortdate/lang/en/surveyprofield_shortdate.php @@ -25,18 +25,19 @@ $string['currentshortdatedefault'] = 'Current short date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the short date the remote user will find answered by default. The default for this type of question is mandatory. If "Current short date" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the short date the remote user will find answered by default. The default for this type of question is mandatory. If "Current short date" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['pluginname'] = 'Short date'; +$string['privacy:metadata'] = 'The "Short date" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -51,7 +52,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_shortdatenotset'] = 'Please choose a short date or select "{$a}" checkbox'; $string['uerr_shortdatenotsetrequired'] = 'Short date is not correctly defined'; -$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date (short) [mm/yyyy]'; -$string['privacy:metadata'] = 'The "Short date" field plugin does not store any personal data.'; diff --git a/field/shortdate/tests/behat/itemform.feature b/field/shortdate/tests/behat/itemform.feature index 2e09e715814..95791b8304d 100644 --- a/field/shortdate/tests/behat/itemform.feature +++ b/field/shortdate/tests/behat/itemform.feature @@ -102,6 +102,6 @@ Feature: Create a shortdate item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When did you buy your current car?" - Then the field "id_surveypro_field_shortdate_2_month" matches value "January" - Then the field "id_surveypro_field_shortdate_2_year" matches value "2014" + Then the field "id_field_shortdate_2_month" matches value "January" + Then the field "id_field_shortdate_2_year" matches value "2014" Then I should see "Additional note" diff --git a/field/shortdate/tests/behat/submit_shortdate.feature b/field/shortdate/tests/behat/submit_shortdate.feature index 55f758150fd..e2685a74433 100644 --- a/field/shortdate/tests/behat/submit_shortdate.feature +++ b/field/shortdate/tests/behat/submit_shortdate.feature @@ -43,8 +43,8 @@ Feature: Submit using a shortdate item # student1 submits And I set the following fields to these values: - | id_surveypro_field_shortdate_1_month | March | - | id_surveypro_field_shortdate_1_year | 2005 | + | id_field_shortdate_1_month | March | + | id_field_shortdate_1_year | 2005 | And I press "Submit" diff --git a/field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml b/field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml similarity index 88% rename from field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml rename to field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml index 9d64f2c3353..55a1e4d9b23 100644 --- a/field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml +++ b/field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>SHORT DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>shortdate specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SHORT DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>shortdate specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 @@ -42,6 +37,11 @@ 1 0 shortdate_001 + 0 + 0 + 0 + + 2 39600 strftime01 @@ -49,35 +49,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 2 - 0 + 1 shortdate_002 + 0 + 0 + 0 + + 1 1254391200 strftime01 @@ -85,35 +84,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 3 - 0 + 1 shortdate_003 + 0 + 0 + 0 + + 4 39600 strftime01 @@ -121,35 +119,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 4 - 0 + 1 shortdate_004 + 0 + 0 + 0 + + 5 39600 strftime01 @@ -157,35 +154,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 5 - 0 + 1 shortdate_005 + 0 + 0 + 0 + + 3 39600 strftime01 @@ -193,35 +189,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 6 - 0 + 1 shortdate_006 + 0 + 0 + 0 + + 2 39600 strftime01 @@ -229,35 +224,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 7 - 0 + 1 shortdate_007 + 0 + 0 + 0 + + 1 1254391200 strftime01 @@ -265,35 +259,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 8 - 0 + 1 shortdate_008 + 0 + 0 + 0 + + 4 39600 strftime01 @@ -301,35 +294,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 9 - 0 + 1 shortdate_009 + 0 + 0 + 0 + + 5 39600 strftime01 diff --git a/field/shortdate/version.php b/field/shortdate/version.php index 955149762a8..6d18f22132b 100644 --- a/field/shortdate/version.php +++ b/field/shortdate/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_shortdate'; // Full name of the plugin (used for diagnostics). diff --git a/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php b/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php index 1a2e20fea00..8d9b7f4da53 100644 --- a/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php +++ b/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'textarea'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugintextarea = new backup_nested_element('surveyprofield_textarea', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'trimonsave', - 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength', ]); + 'trimonsave', 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/textarea/classes/item.php b/field/textarea/classes/item.php index e9c52182c0e..f67d1800c87 100644 --- a/field/textarea/classes/item.php +++ b/field/textarea/classes/item.php @@ -40,58 +40,13 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var boolean True if the user input will be trimmed at save time + * @var bool True if the user input will be trimmed at save time */ protected $trimonsave; - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; - /** * @var bool Does the item use html editor? */ @@ -117,6 +72,13 @@ class item extends itembase { */ protected $maxlength; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -149,7 +111,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -181,14 +145,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -201,18 +161,13 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Text (long)'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'textarea_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + // $record->trimonsave $record->useeditor = 0; $record->arearows = 10; $record->areacols = 60; $record->minlength = 0; + // $record->maxlength } /** @@ -231,7 +186,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. if (!core_text::strlen($record->minlength)) { @@ -262,47 +217,149 @@ public function item_custom_fields_to_db($record) { // 4. Other. } - // MARK get. + // MARK set. /** - * Is this item available as a parent? + * Set trimonsave. * - * @return the content of the static property "canbeparent" + * @param string $trimonsave + * @return void */ - public static function get_canbeparent() { - return self::$canbeparent; + public function set_trimonsave($trimonsave) { + $this->trimonsave = $trimonsave; } /** - * Make the list of the fields using multilang + * Set useeditor. * - * @return array of felds + * @param string $useeditor + * @return void */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function set_useeditor($useeditor) { + $this->useeditor = $useeditor; + } - return $fieldlist; + /** + * Set arearows. + * + * @param string $arearows + * @return void + */ + public function set_arearows($arearows) { + $this->arearows = $arearows; + } + + /** + * Set areacols. + * + * @param string $areacols + * @return void + */ + public function set_areacols($areacols) { + $this->areacols = $areacols; + } + + /** + * Set minlength. + * + * @param string $minlength + * @return void + */ + public function set_minlength($minlength) { + $this->minlength = $minlength; + } + + /** + * Set maxlength. + * + * @param string $maxlength + * @return void + */ + public function set_maxlength($maxlength) { + $this->maxlength = $maxlength; } + // MARK get. + /** - * Does the user input need trim? + * Get trimonsave. * - * @return if this plugin requires a user input trim + * @return $this->trimonsave */ public function get_trimonsave() { return $this->trimonsave; } /** - * Get use editor. + * Get useeditor. * - * @return the content of $useeditor property + * @return $this->useeditor */ - public function get_useseditor() { + public function get_useeditor() { return $this->useeditor; } + /** + * Get arearows. + * + * @return $this->arearows + */ + public function get_arearows() { + return $this->arearows; + } + + /** + * Get areacols. + * + * @return $this->areacols + */ + public function get_areacols() { + return $this->areacols; + } + + /** + * Get minlength. + * + * @return $this->minlength + */ + public function get_minlength() { + return $this->minlength; + } + + /** + * Get maxlength. + * + * @return $this->maxlength + */ + public function get_maxlength() { + return $this->maxlength; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['trimonsave', 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + + /** + * Make the list of the fields using multilang + * + * @param boolean $includemetafields + * @return array of fields + */ + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_textarea'] = []; + + return $fieldlist; + } + /** * Return the xml schema for surveypro_<> table. * @@ -315,29 +372,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -393,41 +431,38 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_textarea_'.$this->sortindex; - $attributes = []; - $attributes['id'] = $idprefix; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_textarea_'.$this->sortindex; + $basename = $this->itemname; + + $attributes['id'] = $baseid; $attributes['rows'] = $this->arearows; $attributes['cols'] = $this->areacols; if (empty($this->useeditor) || ($searchform)) { - $fieldname = $this->itemname; - $attributes['class'] = 'indent-'.$this->indent.' textarea_textarea'; $attributes['wrap'] = 'virtual'; if (!$searchform) { - $mform->addElement('mod_surveypro_textarea_plain', $fieldname, $elementlabel, $attributes); - $mform->setType($fieldname, PARAM_TEXT); + $elementgroup[] = $mform->createElement('textarea', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename, PARAM_TEXT); } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('mod_surveypro_textarea_plain', $fieldname, $elementlabel, $attributes); + $elementgroup[] = $mform->createElement('textarea', $basename, $elementlabel, $attributes); - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'textarea_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - // Note: $attributes['class'] and $attributes['id'] do not work: MDL_28194. - $attributes['class'] = 'indent-'.$this->indent.' textarea_editor'; - $fieldname = $this->itemname.'_editor'; + $fieldname = $basename.'_editor'; $editoroptions = ['trusttext' => true, 'subdirs' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES]; - $mform->addElement('mod_surveypro_textarea_editor', $fieldname, $elementlabel, $attributes, $editoroptions); - $mform->setType($fieldname, PARAM_CLEANHTML); + $elementgroup[] = $mform->createElement('editor', $basename.'_editor', $elementlabel, $attributes, $editoroptions); + $mform->addGroup($elementgroup, $basename.'_editor'.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename.'_editor', PARAM_CLEANHTML); } if (!$searchform) { @@ -436,7 +471,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $fieldname; + if ($this->position == SURVEYPRO_POSITIONTOP) { + $starplace = $basename.'_extrarow_group'; + } else { + $starplace = empty($this->useeditor) ? $basename.'_group' : $basename.'_editor_group'; + } $mform->_required[] = $starplace; } } @@ -452,38 +491,52 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (!empty($this->useeditor)) { - $errorkey = $this->itemname.'_editor'; + $errorkey = $this->itemname.'_editor_group'; $fieldname = $this->itemname.'_editor'; - $itemcontent = $data[$fieldname]['text']; + $userinput = $data[$fieldname]['text']; } else { - $errorkey = $this->itemname; + $errorkey = $this->itemname.'_group'; $fieldname = $this->itemname; - $itemcontent = $data[$fieldname]; + $userinput = $data[$fieldname]; } + // If trimonsave is asked, make the validation on trimmed text. if ($this->trimonsave) { - $itemcontent = trim($itemcontent); + if (trim($userinput) != $userinput) { + $warnings[$errorkey] = get_string('uerr_willbetrimmed', 'mod_surveypro'); + } + + // The variable $userinput is not going to be saved. I can freely modify it. + $userinput = trim($userinput); } - if (empty($itemcontent)) { + // If $userinput is empty the story stops here. It doesn't matter if there were requirements on the answer. + if (empty($userinput)) { if ($this->required) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } // I don't care if this element is required or not. - // If the user provides an answer, it has to be compliant with the field validation rules. - if ( $this->maxlength && (\core_text::strlen($itemcontent) > $this->maxlength) ) { + // If the user provided an answer, it has to be compliant with the field validation rules. + if ( $this->maxlength && (\core_text::strlen($userinput) > $this->maxlength) ) { $errors[$errorkey] = get_string('uerr_texttoolong', 'surveyprofield_textarea'); } - if (\core_text::strlen($itemcontent) < $this->minlength) { + if (\core_text::strlen($userinput) < $this->minlength) { $errors[$errorkey] = get_string('uerr_texttooshort', 'surveyprofield_textarea'); } + + if ( $errors && isset($warnings) ) { + // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. + $errors = array_merge($warnings, $errors); + } + + return $errors; } /** @@ -595,15 +648,6 @@ public function userform_get_root_elements_name() { return $elementnames; } - /** - * Does the user input need trim? - * - * @return if this plugin requires a user input trim - */ - public static function userform_input_needs_trim() { - return true; - } - /** * Starting from the info stored into $answer, this function returns the corresponding content for the export file. * diff --git a/field/textarea/classes/itemsetupform.php b/field/textarea/classes/itemsetupform.php index febd3f624bc..457151b5fe0 100644 --- a/field/textarea/classes/itemsetupform.php +++ b/field/textarea/classes/itemsetupform.php @@ -77,7 +77,7 @@ public function definition() { $mform->setType($fieldname, PARAM_INT); $mform->setDefault($fieldname, SURVEYPROFIELD_TEXTAREA_DEFAULTCOLS); - // Item: trimonsave. + // Itembase: trimonsave. $fieldname = 'trimonsave'; $mform->addElement('checkbox', $fieldname, get_string($fieldname, 'surveyprofield_textarea')); $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_textarea'); diff --git a/field/textarea/db/install.xml b/field/textarea/db/install.xml index 17a8f159aa6..e46b6b6a62f 100644 --- a/field/textarea/db/install.xml +++ b/field/textarea/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/textarea/db/upgrade.php b/field/textarea/db/upgrade.php index 8df9df5789f..89ceab7550d 100644 --- a/field/textarea/db/upgrade.php +++ b/field/textarea/db/upgrade.php @@ -100,9 +100,70 @@ function xmldb_surveyprofield_textarea_upgrade($oldversion) { // Launch rename field nexttrimonsave to trimonsave. $dbman->rename_field($table, $newfield, 'trimonsave'); - // Character savepoint reached. + // Textarea savepoint reached. upgrade_plugin_savepoint(true, 2024020700, 'surveyprofield', 'textarea'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_textarea. + $table = new xmldb_table('surveyprofield_textarea'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_textarea} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Textarea savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'textarea'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_textarea'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_textarea. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_textarea} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Textarea savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'textarea'); + } + return true; } diff --git a/field/textarea/lang/en/surveyprofield_textarea.php b/field/textarea/lang/en/surveyprofield_textarea.php index 0a29a76bd8b..01efe9af029 100644 --- a/field/textarea/lang/en/surveyprofield_textarea.php +++ b/field/textarea/lang/en/surveyprofield_textarea.php @@ -23,27 +23,27 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['areacols_help'] = 'Define a custom width for the text area (This option is not applied in conjunction with "Use html editor")'; $string['areacols'] = 'Area width in columns'; -$string['arearows_help'] = 'Define a custom height for the text area'; +$string['areacols_help'] = 'Define a custom width for the text area (This option is not applied in conjunction with "Use html editor")'; $string['arearows'] = 'Area height in rows'; +$string['arearows_help'] = 'Define a custom height for the text area'; $string['hasmaxlength'] = 'Text is supposed to be shorter or equal than {$a} characters'; $string['hasminlength'] = 'Text is supposed to be longer or equal than {$a} characters'; $string['hasminmaxlength'] = 'Text is supposed to fit between {$a->minlength} and {$a->maxlength} characters'; -$string['ierr_maxlengthlowerthanminlength'] = 'Maximum length can not be lowwer-equal than minimum length'; +$string['ierr_maxlengthlowerthanminlength'] = 'Maximum length can not be lower-equal than minimum length'; $string['ierr_maxlengthnotinteger'] = 'Maximum length must be integer'; $string['ierr_minlengthnotinteger'] = 'Minimum length must be integer'; $string['ierr_requirednozerolength'] = 'Required item can not allow a zero length test'; -$string['maxlength_help'] = 'The maximun number of allowed characters for the answer. Empty for unlimited length.'; $string['maxlength'] = 'Maximum length (in characters)'; -$string['minlength_help'] = 'The minimun number of allowed characters for the answer to this question'; +$string['maxlength_help'] = 'The maximun number of allowed characters for the answer. Empty for unlimited length.'; $string['minlength'] = 'Minimum length (in characters)'; +$string['minlength_help'] = 'The minimun number of allowed characters for the answer to this question'; $string['pluginname'] = 'Text area'; $string['privacy:metadata'] = 'The "Textarea" field plugin does not store any personal data.'; -$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['trimonsave'] = 'Clean answer at save time'; +$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['uerr_texttoolong'] = 'Text is too long'; $string['uerr_texttooshort'] = 'Text is too short'; -$string['useeditor_help'] = 'Is the answer supposed to be in plain text or in html?'; $string['useeditor'] = 'Use html editor'; +$string['useeditor_help'] = 'Is the answer supposed to be in plain text or in html?'; $string['userfriendlypluginname'] = 'Text (long)'; diff --git a/field/textarea/lang/es_mx/surveyprofield_textarea.php b/field/textarea/lang/es_mx/surveyprofield_textarea.php index f2af6c380ea..cd55364bbe8 100644 --- a/field/textarea/lang/es_mx/surveyprofield_textarea.php +++ b/field/textarea/lang/es_mx/surveyprofield_textarea.php @@ -25,24 +25,24 @@ defined('MOODLE_INTERNAL') || die(); -$string['areacols_help'] = 'Definir un ancho personalizado para el área de texto'; $string['areacols'] = 'Ancho del área en columnas'; -$string['arearows_help'] = 'Definir un ancho personalizado para el área de texto'; +$string['areacols_help'] = 'Definir un ancho personalizado para el área de texto'; $string['arearows'] = 'Altura del área en filas'; +$string['arearows_help'] = 'Definir un ancho personalizado para el área de texto'; $string['hasmaxlength'] = 'Se supone que el texto sea menor o igual a {$a} caracteres'; $string['hasminlength'] = 'Se supone que el texto sea mayor o igual a {$a} caracteres'; $string['hasminmaxlength'] = 'Se supone que el texto tenga entre {$a->minlength} y {$a->maxlength} caracteres'; $string['ierr_maxlengthlowerthanminlength'] = 'La longitud máxima no puede ser menor o igual a la longitud mínima'; $string['ierr_maxlengthnotinteger'] = 'La longitud máxima debe ser un número entero'; -$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación. Dejar vacío para longitud ilimitada.'; $string['maxlength'] = 'Longitud máxima (en caracteres)'; -$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; +$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación. Dejar vacío para longitud ilimitada.'; $string['minlength'] = 'Longitud mínima (en caracteres)'; +$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; $string['pluginname'] = 'Área de texto'; -$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['trimonsave'] = 'Contestación limpia al momento de guardar'; +$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['uerr_texttoolong'] = 'El texto es demasiado largo'; $string['uerr_texttooshort'] = 'El texto es demasiado corto'; -$string['useeditor_help'] = '¿Se supone que la contestación sea en texto simple o HTML?'; $string['useeditor'] = 'Usar editor HTML'; +$string['useeditor_help'] = '¿Se supone que la contestación sea en texto simple o HTML?'; $string['userfriendlypluginname'] = 'Texto (largo)'; diff --git a/field/textarea/lang/it/surveyprofield_textarea.php b/field/textarea/lang/it/surveyprofield_textarea.php index e6508ae3a35..ed61278a8c2 100644 --- a/field/textarea/lang/it/surveyprofield_textarea.php +++ b/field/textarea/lang/it/surveyprofield_textarea.php @@ -23,23 +23,23 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['areacols_help'] = 'Larghezza dell\'area di testo (verrà trascurato se si sceglie di usare l\'editor html)'; $string['areacols'] = 'Larghezza dell\'area in colonne'; -$string['arearows_help'] = 'Altezza dell\'area di testo'; +$string['areacols_help'] = 'Larghezza dell\'area di testo (verrà trascurato se si sceglie di usare l\'editor html)'; $string['arearows'] = 'Altezza dell\'area in righe'; +$string['arearows_help'] = 'Altezza dell\'area di testo'; $string['hasmaxlength'] = 'Il testo deve essere al massimo di {$a} caratteri'; $string['hasminlength'] = 'Il testo deve essere almeno di {$a} caratteri'; $string['hasminmaxlength'] = 'Il testo deve avere un numero di caratteri compreso fra {$a->minlength} e {$a->maxlength}'; $string['ierr_maxlengthlowerthanminlength'] = 'La lunghezza massima del testo non può essere inferiore alla lunghezza minima'; $string['ierr_maxlengthnotinteger'] = 'La lunghezza massima deve essere un numero intero'; -$string['maxlength_help'] = 'Il massimo numero di caratteri di una risposta. Lasciare vuoto per consentite una lunghezza illimitata.'; $string['maxlength'] = 'Lunghezza massima (in caratteri)'; -$string['minlength_help'] = 'Il minimo numero di caratteri di una risposta'; +$string['maxlength_help'] = 'Il massimo numero di caratteri di una risposta. Lasciare vuoto per consentite una lunghezza illimitata.'; $string['minlength'] = 'Lunghezza minima (in caratteri)'; +$string['minlength_help'] = 'Il minimo numero di caratteri di una risposta'; $string['pluginname'] = 'Regione di testo'; $string['privacy:metadata'] = 'La plugin "Testo (lungo)" con contiene alcun dato personale.'; $string['uerr_texttoolong'] = 'Il testo è troppo lungo'; $string['uerr_texttooshort'] = 'Il testo è troppo corto'; -$string['useeditor_help'] = 'La risposta deve essere in testo privo di formattazione o arricchita da tag html?'; $string['useeditor'] = 'Usa l\'editor html'; +$string['useeditor_help'] = 'La risposta deve essere in testo privo di formattazione o arricchita da tag html?'; $string['userfriendlypluginname'] = 'Testo (lungo)'; diff --git a/field/textarea/mform/textarea_editor.php b/field/textarea/mform/textarea_editor.php deleted file mode 100644 index dcc5d5e48b1..00000000000 --- a/field/textarea/mform/textarea_editor.php +++ /dev/null @@ -1,119 +0,0 @@ -. - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/editor.php'); - -// @codingStandardsIgnoreFile - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_textarea_editor extends \MoodleQuickForm_editor { - - /** - * Constructor. - * - * @param string $elementName Optional name of the editor - * @param string $elementLabel Optional editor label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filepicker - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * My intervention only replaces
with
AT THE BEGINNING of $output - * I use the output of parent::toHtml() to get advantages of future updates to core mform class - * I search for simple
without attributes so that if moodle HQ will ever fix this issue in the core code, - * my intervention will result in nothing without adding useless or dangerous modifications - * - * @return string - */ - public function toHtml() { - // The core code is ONLY MISSING the class in the first
. - // I add it with a simple replace. - $output = parent::toHtml(); // Core code. - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
~'; - $class = empty($this->_attributes['class']) ? 'indent-0' : $this->_attributes['class']; - $replacement = $tabs.'
'; - $output = preg_replace($pattern, $replacement, $output); - - return $output; - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml(): string { - $complexvalue = $this->getValue(); - $value = core_text::strlen($complexvalue['text']) ? $complexvalue['text'] : ' '; - - $class = array(); - $class['id'] = $this->getAttribute('id'); - $class['name'] = $this->getAttribute('name'); - if (empty($this->_attributes['class'])) { - $class['class'] = 'indent-0 '; - } else { - $class['class'] = $this->_attributes['class']; - } - $class['readonly'] = 'true'; - - $output = $this->_getTabs(); - $output .= \html_writer::start_tag('textarea', $class); - $output .= $value; - $output .= \html_writer::end_tag('textarea'); - $output .= $this->_getPersistantData(); - - return $output; - } -} diff --git a/field/textarea/mform/textarea_plain.php b/field/textarea/mform/textarea_plain.php deleted file mode 100644 index c30904f8311..00000000000 --- a/field/textarea/mform/textarea_plain.php +++ /dev/null @@ -1,120 +0,0 @@ -. - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/textarea.php'); - -// @codingStandardsIgnoreFile - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_textarea_plain extends \MoodleQuickForm_textarea { - - /** - * Constructor. - * - * @param string $elementName Optional name of the editor - * @param string $elementLabel Optional editor label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filepicker - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * My intervention only replaces
with
AT THE BEGINNING of $output - * I use the output of parent::toHtml() to get advantages of future updates to core mform class - * I search for simple
without attributes so that if moodle HQ will ever fix this issue in the core code, - * my intervention will result in nothing without adding useless or dangerous modifications - * - * @return string - */ - public function toHtml() { - // The core code is ONLY MISSING the class in the first
. - // I add it with a simple replace. - $output = parent::toHtml(); // Core code. - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
~'; - $class = empty($this->_attributes['class']) ? 'indent-0' : $this->_attributes['class']; - $replacement = $tabs.'
'; - $output = preg_replace($pattern, $replacement, $output); - return $output; - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $value = htmlspecialchars($this->getValue()); - $value = nl2br($value); - $value = core_text::strlen($value) ? $value : ' '; - - $class = array(); - $class['id'] = $this->getAttribute('id'); - $class['name'] = $this->getAttribute('name'); - if (empty($this->_attributes['class'])) { - $class['class'] = 'indent-0 '; - } else { - $class['class'] = $this->_attributes['class']; - } - $class['readonly'] = 'true'; - - $output = $this->_getTabs(); - // $output .= \html_writer::tag('div', $value, $class); - $output .= \html_writer::start_tag('textarea', $class); - $output .= $value; - $output .= \html_writer::end_tag('textarea'); - $output .= $this->_getPersistantData(); - - return $output; - } -} diff --git a/field/textarea/tests/behat/itemform.feature b/field/textarea/tests/behat/itemform.feature index 90280df01f3..4511c2c7031 100644 --- a/field/textarea/tests/behat/itemform.feature +++ b/field/textarea/tests/behat/itemform.feature @@ -50,7 +50,7 @@ Feature: Create a textarea item | Maximum length (in characters) | 4 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" And I set the field "Maximum length (in characters)" to "40" And I press "Add" @@ -94,4 +94,4 @@ Feature: Create a textarea item And I select "Preview" from the "jump" singleselect Then I should see "II.b Write a short description of yourself" Then I should see "One more additional note" - Then "//textarea[contains(@id, 'id_surveypro_field_textarea_3')]" "xpath_element" should exist + Then "//textarea[contains(@id, 'id_field_textarea_3')]" "xpath_element" should exist diff --git a/field/textarea/tests/behat/settings_configuration.feature b/field/textarea/tests/behat/settings_configuration.feature index f09874a7964..b6c72ff43e3 100644 --- a/field/textarea/tests/behat/settings_configuration.feature +++ b/field/textarea/tests/behat/settings_configuration.feature @@ -42,7 +42,7 @@ Feature: Submit using textarea item and check form validation | Minimum length (in characters) | 20 | | Maximum length (in characters) | 1 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" And I set the field "Maximum length (in characters)" to "" And I press "Add" # End of test number 1 @@ -123,7 +123,7 @@ Feature: Submit using textarea item and check form validation | Minimum length (in characters) | 20 | | Maximum length (in characters) | 1 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" # End of test number 8 # if the corresponding field is submitted when still empty diff --git a/field/textarea/tests/behat/trim.feature b/field/textarea/tests/behat/trim.feature index 908ba2300f8..ddfcff78a86 100644 --- a/field/textarea/tests/behat/trim.feature +++ b/field/textarea/tests/behat/trim.feature @@ -61,6 +61,7 @@ Feature: Trim textarea content And I press "New response" And I set the field "This is a standard text" to " false long text " And I set the field "Text to trim" to " false long text " + And I press "Submit" Then I should see "Text is too short" @@ -75,5 +76,5 @@ Feature: Trim textarea content And I press "Continue to responses list" And I follow "edit_submission_row_1" - Then the field "id_surveypro_field_textarea_1" matches value " false long text " - Then the field "id_surveypro_field_textarea_2" matches value "text correctly trimmed" + Then the field "id_field_textarea_1" matches value " false long text " + Then the field "id_field_textarea_2" matches value "text correctly trimmed" diff --git a/field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml b/field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml similarity index 87% rename from field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml rename to field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml index 77e50f56b8f..55c92e1b9d3 100644 --- a/field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml +++ b/field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml @@ -1,159 +1,155 @@ - + + <h5>TEXTAREA<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Use html editor</li><li>Area heigh in rows</li><li>Area width in columns<br /></li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>TEXTAREA<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Use html editor</li><li>Area heigh in rows</li><li>Area width in columns<br /></li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 1 0 0 - 1 - 0 + 1 textarea_001 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 - + + <ul><li>not mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 0 0 0 - 2 - 0 + 1 textarea_002 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 - + + <ul><li>mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 1 0 0 - 3 - 0 + 1 textarea_003 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 - + + <ul><li>not mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 0 0 0 - 4 - 0 + 1 textarea_004 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 diff --git a/field/textarea/version.php b/field/textarea/version.php index ec4cc0feccd..4643454e457 100644 --- a/field/textarea/version.php +++ b/field/textarea/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024020700; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_textarea'; // Full name of the plugin (used for diagnostics). diff --git a/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php b/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php index 2e5d1447098..879ee4be640 100644 --- a/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php +++ b/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'time'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugintime = new backup_nested_element('surveyprofield_time', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/time/classes/item.php b/field/time/classes/item.php index be43e0bb242..e185ca6198d 100644 --- a/field/time/classes/item.php +++ b/field/time/classes/item.php @@ -39,52 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Step for minutes drop down menu @@ -96,30 +51,37 @@ class item extends itembase { */ protected $defaultoption; + /** + * @var int Defaultvalue for the item answer + */ + protected $defaultvalue; + /** * @var string Format of the content once downloaded */ protected $downloadformat; /** - * @var int Defaultvalue for the time in unixtime + * @var int Lowerbound for the shortdate in unixtime */ - protected $defaultvalue; + protected $lowerbound; /** - * @var int Hour of the defaultvalue for the time + * @var int Upperbound for the shortdate in unixtime */ - protected $defaultvaluehour; + protected $upperbound; /** - * @var int Minute of the defaultvalue for the time + * @var int defaultvaluehour hours of defaultvalue */ - protected $defaultvalueminute; + protected $defaultvaluehour; /** - * @var int Lowerbound for the shortdate in unixtime + * @var int defaultvalueminute minutes of defaultvalue */ - protected $lowerbound; + protected $defaultvalueminute; + + // Service variables. /** * @var int Hour of the lowerbound for the time @@ -131,21 +93,23 @@ class item extends itembase { */ protected $lowerboundminute; - /** - * @var int Upperbound for the shortdate in unixtime - */ - protected $upperbound; - /** * @var int Hour of the upperbound for the time */ protected $upperboundhour; + // Service variables. + /** * @var int Minute of the upperbound for the time */ protected $upperboundminute; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -178,7 +142,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -210,14 +176,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -230,14 +192,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Time'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'time_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->step = 1; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; @@ -254,7 +209,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_time_to_unix_time($hour, $minute) { - $unixtime = mktime( + $unixtime = gmmktime( $hour, $minute, 0, SURVEYPROFIELD_TIME_MONTHOFFSET, SURVEYPROFIELD_TIME_DAYOFFSET, SURVEYPROFIELD_TIME_YEAROFFSET ); @@ -284,7 +239,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -322,15 +277,216 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set step. + * + * @param string $step + * @return void + */ + public function set_step($step) { + $this->step = $step; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set lowerboundhour. + * + * @param string $lowerboundhour + * @return void + */ + public function set_lowerboundhour($lowerboundhour) { + $this->lowerboundhour = $lowerboundhour; + } + + /** + * Set lowerboundminute. + * + * @param string $lowerboundminute + * @return void + */ + public function set_lowerboundminute($lowerboundminute) { + $this->lowerboundminute = $lowerboundminute; + } + + /** + * Set upperboundhour. + * + * @param string $upperboundhour + * @return void + */ + public function set_upperboundhour($upperboundhour) { + $this->upperboundhour = $upperboundhour; + } + + /** + * Set upperboundminute. + * + * @param string $upperboundminute + * @return void + */ + public function set_upperboundminute($upperboundminute) { + $this->upperboundminute = $upperboundminute; + } + // MARK get. /** - * Is this item available as a parent? + * Get step. + * + * @return $this->step + */ + public function get_step() { + return $this->step; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get defaultvaluehour. + * + * @return $this->defaultvaluehour + */ + public function get_defaultvaluehour() { + return $this->defaultvaluehour; + } + + /** + * Get defaultvalueminute. + * + * @return $this->defaultvalueminute + */ + public function get_defaultvalueminute() { + return $this->defaultvalueminute; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get lowerboundhour. + * + * @return $this->lowerboundhour + */ + public function get_lowerboundhour() { + return $this->lowerboundhour; + } + + /** + * Get lowerboundminute. * - * @return the content of the static property "canbeparent" + * @return $this->lowerboundminute */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_lowerboundminute() { + return $this->lowerboundminute; + } + + /** + * Get upperboundhour. + * + * @return $this->upperboundhour + */ + public function get_upperboundhour() { + return $this->upperboundhour; + } + + /** + * Get upperboundminute. + * + * @return $this->upperboundminute + */ + public function get_upperboundminute() { + return $this->upperboundminute; } /** @@ -369,14 +525,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvaluehour', 'defaultvalueminute', 'lowerboundhour', 'lowerboundminute', 'upperboundhour', 'upperboundminute', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_time'] = []; return $fieldlist; } @@ -393,31 +565,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + - - - + + + @@ -446,8 +599,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_time_'.$this->sortindex; - // Begin of: element values. $hours = []; $minutes = []; @@ -484,62 +635,52 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_time_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_hour'; - $attributes['id'] = $idprefix.'_hour'; - $attributes['class'] = 'indent-'.$this->indent.' time_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $hours, $attributes); - - $itemname = $this->itemname.'_minute'; - $attributes['id'] = $idprefix.'_minute'; - $attributes['class'] = 'time_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $minutes, $attributes); + $attributes['id'] = $baseid.'_hour'; + $elementgroup[] = $mform->createElement('select', $basename.'_hour', '', $hours, $attributes); + $attributes['id'] = $baseid.'_minute'; + $elementgroup[] = $mform->createElement('select', $basename.'_minute', '', $minutes, $attributes); $separator = [':']; if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'time_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); $separator[] = ' '; if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -552,7 +693,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $timearray['minutes'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -588,12 +729,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_hour', $timearray['hours']); - $mform->setDefault($this->itemname.'_minute', $timearray['minutes']); + $mform->setDefault($basename.'_hour', $timearray['hours']); + $mform->setDefault($basename.'_minute', $timearray['minutes']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -618,7 +759,7 @@ public function userform_mform_validation($data, &$errors, $searchform) { // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -645,13 +786,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_timenotset', 'surveyprofield_time', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_time_to_unix_time(0, 0)); @@ -685,6 +826,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_time'); } } + + return $errors; } /** @@ -779,9 +922,9 @@ public function userform_get_prefill($fromdb) { return $prefill; } - $datearray = $this->item_split_unix_time($fromdb->content); - $prefill[$this->itemname.'_hour'] = $datearray['hours']; - $prefill[$this->itemname.'_minute'] = $datearray['minutes']; + $timearray = $this->item_split_unix_time($fromdb->content); + $prefill[$this->itemname.'_hour'] = $timearray['hours']; + $prefill[$this->itemname.'_minute'] = $timearray['minutes']; } // If the "No answer" checkbox is part of the element GUI... diff --git a/field/time/db/install.xml b/field/time/db/install.xml index 19e0cdb00f1..9374f7e5412 100644 --- a/field/time/db/install.xml +++ b/field/time/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/time/db/upgrade.php b/field/time/db/upgrade.php index 1059375b9ec..4179aeadb6c 100644 --- a/field/time/db/upgrade.php +++ b/field/time/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_time_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Time savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'time'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_time. + $table = new xmldb_table('surveyprofield_time'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_time} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Time savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'time'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_time'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_time. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_time} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Time savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'time'); + } + return true; } diff --git a/field/time/lang/en/surveyprofield_time.php b/field/time/lang/en/surveyprofield_time.php index 4952ed79b45..2dedd69bcf4 100644 --- a/field/time/lang/en/surveyprofield_time.php +++ b/field/time/lang/en/surveyprofield_time.php @@ -25,10 +25,10 @@ $string['currenttimedefault'] = 'Current time'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the time the remote user will find answered by default. The default for this type of question is mandatory. If "Current time" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the time the remote user will find answered by default. The default for this type of question is mandatory. If "Current time" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['fifteenminutes'] = 'fifteen minutes'; $string['fiveminutes'] = 'five minutes'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; @@ -36,16 +36,17 @@ $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitehour'] = 'Choose an hour'; $string['inviteminute'] = 'Choose a minute'; -$string['lowerbound_help'] = 'The lowest time the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest time the user is allowed to enter'; $string['oneminute'] = 'One minute'; $string['pluginname'] = 'Time'; +$string['privacy:metadata'] = 'The "Time" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; $string['restriction_upperlower'] = 'Answer is supposed to be greater-equal than {$a->lowerbound} or lower-equal than {$a->upperbound}'; -$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['step'] = 'Step'; +$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['strftime01'] = '%H:%M'; $string['strftime02'] = '%I:%M %p'; $string['tenminutes'] = 'ten minutes'; @@ -57,7 +58,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_timenotset'] = 'Please choose a time or select the "{$a}" checkbox'; $string['uerr_timenotsetrequired'] = 'Time is not correctly defined'; -$string['upperbound_help'] = 'The biggest time the user is allowed to enter.

Upper and lower bound define a range.
If "lower bound" is lower than "upper bound" the user is forced to enter a value falling into the range.
If "lower bound" is greater than "upper bound" the user input is forced out from the range. i.e. the user input is supposed to be greater-equal than the lower bound OR lower-equal than the upper bound.

Example: By setting "lower bound" to 22 and "upper bound" to 1, the user input is supposed to fall in the three hours long range between 22 in the night and 1 in the morning.'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest time the user is allowed to enter.

Upper and lower bound define a range.
If "lower bound" is lower than "upper bound" the user is forced to enter a value falling into the range.
If "lower bound" is greater than "upper bound" the user input is forced out from the range. i.e. the user input is supposed to be greater-equal than the lower bound OR lower-equal than the upper bound.

Example: By setting "lower bound" to 22 and "upper bound" to 1, the user input is supposed to fall in the three hours long range between 22 in the night and 1 in the morning.'; $string['userfriendlypluginname'] = 'Time'; -$string['privacy:metadata'] = 'The "Time" field plugin does not store any personal data.'; diff --git a/field/time/tests/behat/itemform.feature b/field/time/tests/behat/itemform.feature index 4f5347da105..f9289a5f619 100644 --- a/field/time/tests/behat/itemform.feature +++ b/field/time/tests/behat/itemform.feature @@ -54,18 +54,18 @@ Feature: Create a time item Then I should see "Lower and upper bounds must be different" And I set the following fields to these values: - | id_lowerboundhour | 10 | - | id_lowerboundminute | 0 | - | id_upperboundhour | 7 | - | id_upperboundminute | 0 | + | id_lowerboundhour | 10 | + | id_lowerboundminute | 0 | + | id_upperboundhour | 7 | + | id_upperboundminute | 0 | And I press "Add" Then I should see "Default does not fall within the specified range (see \"Upper bound\" help)" And I set the following fields to these values: - | id_lowerboundhour | 7 | - | id_lowerboundminute | 0 | - | id_upperboundhour | 10 | - | id_upperboundminute | 0 | + | id_lowerboundhour | 7 | + | id_lowerboundminute | 0 | + | id_upperboundhour | 10 | + | id_upperboundminute | 0 | And I press "Add" And I follow "edit_item_2" @@ -99,6 +99,6 @@ Feature: Create a time item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a At what time do you usually get up in the morning in a working day?" - Then the field "id_surveypro_field_time_2_hour" matches value "7" - Then the field "id_surveypro_field_time_2_minute" matches value "40" + Then the field "id_field_time_2_hour" matches value "7" + Then the field "id_field_time_2_minute" matches value "40" Then I should see "Additional note" diff --git a/field/time/tests/behat/submit_time.feature b/field/time/tests/behat/submit_time.feature index 688bad2ed5d..896e377207f 100644 --- a/field/time/tests/behat/submit_time.feature +++ b/field/time/tests/behat/submit_time.feature @@ -40,8 +40,8 @@ Feature: Submit using a time item # student1 submits And I press "New response" And I set the following fields to these values: - | id_surveypro_field_time_1_hour | 7 | - | id_surveypro_field_time_1_minute | 15 | + | id_field_time_1_hour | 7 | + | id_field_time_1_minute | 15 | And I press "Submit" diff --git a/field/time/tests/fixtures/usertemplate/time_only_2023103100.xml b/field/time/tests/fixtures/usertemplate/time_only_2024032800.xml similarity index 89% rename from field/time/tests/fixtures/usertemplate/time_only_2023103100.xml rename to field/time/tests/fixtures/usertemplate/time_only_2024032800.xml index cf097e9f465..8abe5850af4 100644 --- a/field/time/tests/fixtures/usertemplate/time_only_2023103100.xml +++ b/field/time/tests/fixtures/usertemplate/time_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>TIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only three <b>time specific setting</b>:</p><ol><li>Step</li><li>Default<br></li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>TIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only three <b>time specific setting</b>:</p><ol><li>Step</li><li>Default<br></li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 1 - 0 + 1 time_001 + 0 + 0 + 0 + + 15 2 -3600 @@ -50,35 +49,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid static value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid static value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 2 - 0 + 1 time_002 + 0 + 0 + 0 + + 15 1 26100 @@ -87,35 +85,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 3 - 0 + 1 time_003 + 0 + 0 + 0 + + 15 4 -3600 @@ -124,35 +121,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 4 - 0 + 1 time_004 + 0 + 0 + 0 + + 15 5 -3600 @@ -161,35 +157,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 5 - 0 + 1 time_005 + 0 + 0 + 0 + + 15 3 -3600 @@ -198,35 +193,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 6 - 0 + 1 time_006 + 0 + 0 + 0 + + 15 2 -3600 @@ -235,35 +229,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 7 - 0 + 1 time_007 + 0 + 0 + 0 + + 15 1 26100 @@ -272,35 +265,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 8 - 0 + 1 time_008 + 0 + 0 + 0 + + 15 4 -3600 @@ -309,35 +301,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time<br /></li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time<br /></li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 9 - 0 + 1 time_009 + 0 + 0 + 0 + + 15 5 -3600 diff --git a/field/time/version.php b/field/time/version.php index 945e0d9bc85..cd028656b02 100644 --- a/field/time/version.php +++ b/field/time/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_time'; // Full name of the plugin (used for diagnostics). diff --git a/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php b/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php index f2170a51641..2d5cdc7727c 100644 --- a/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php +++ b/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php @@ -39,7 +39,7 @@ protected function define_item_subplugin_structure() { // XML nodes declaration. $subplugin = $this->get_subplugin_element(null, '../../plugin', 'fieldset'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); - $subpluginfieldset = new backup_nested_element('surveyproformat_fieldset', ['id'], ['content', 'defaultstatus']); + $subpluginfieldset = new backup_nested_element('surveyproformat_fieldset', ['id'], ['defaultstatus']); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/format/fieldset/classes/item.php b/format/fieldset/classes/item.php index f87222999cd..155520e39c0 100644 --- a/format/fieldset/classes/item.php +++ b/format/fieldset/classes/item.php @@ -39,10 +39,19 @@ */ class item extends itembase { + // Itembase properties. + + /** + * @var int defaultstatus + */ + protected $defaultstatus; + + // Service variables. + /** - * @var string Label of the fieldset + * @var bool Does this item use the child table surveypro(field|format)_plugin? */ - protected $content; + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -67,24 +76,27 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'fieldset'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. + $this->insetupform['common_fs'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -113,24 +125,19 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } /** - * Get content. + * Returns if this item has the mandatory attribute. * - * @return the content of $content property + * @return bool */ - public function get_content() { - return s($this->content); + public static function has_mandatoryattribute() { + return false; } /** @@ -140,29 +147,65 @@ public function get_content() { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Fieldset'; + public function item_add_fields_default_to_child_table(&$record) { + // $record->defaultstatus + + return; + } + + // MARK set. + + /** + * Set defaultstatus. + * + * @param string $defaultstatus + * @return void + */ + public function set_defaultstatus($defaultstatus) { + $this->defaultstatus = $defaultstatus; } // MARK get. /** - * Is this item available as a parent? + * Get content. * - * @return the content of the static property "canbeparent" + * @return the content of $content property */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_content() { + return s($this->content); + } + + /** + * Get defaultstatus. + * + * @return $this->defaultstatus + */ + public function get_defaultstatus() { + return $this->defaultstatus; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultstatus']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = ['content', 'extranote']; + $fieldlist['surveyprofield_time'] = []; return $fieldlist; } @@ -188,7 +231,6 @@ public static function get_plugin_schema() { - @@ -228,6 +270,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/fieldset/classes/itemsetupform.php b/format/fieldset/classes/itemsetupform.php index 50964839cb4..ade6ee9be49 100644 --- a/format/fieldset/classes/itemsetupform.php +++ b/format/fieldset/classes/itemsetupform.php @@ -57,7 +57,7 @@ public function definition() { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyproformat_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); // Item: defaultstatus. diff --git a/format/fieldset/db/install.xml b/format/fieldset/db/install.xml index 93376c95260..80c691d4e8a 100644 --- a/format/fieldset/db/install.xml +++ b/format/fieldset/db/install.xml @@ -1,30 +1,14 @@ -
- - - - - - - - - - - - - - - - - - - + + + diff --git a/format/fieldset/db/upgrade.php b/format/fieldset/db/upgrade.php index f0525362def..15c51143ced 100644 --- a/format/fieldset/db/upgrade.php +++ b/format/fieldset/db/upgrade.php @@ -81,5 +81,25 @@ function xmldb_surveyproformat_fieldset_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024011101, 'surveyproformat', 'fieldset'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyproformat_fieldset. + $table = new xmldb_table('surveyproformat_fieldset'); + $field = new xmldb_field('content'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + if ($dbman->field_exists($table, $field)) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_fieldset} f ON f.itemid = i.id + SET i.content = f.content'; + $DB->execute($sql); + + $dbman->drop_field($table, $field); + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyproformat', 'fieldset'); + } + return true; } diff --git a/format/fieldset/lang/en/surveyproformat_fieldset.php b/format/fieldset/lang/en/surveyproformat_fieldset.php index b94fc43fe35..04aaca5233c 100644 --- a/format/fieldset/lang/en/surveyproformat_fieldset.php +++ b/format/fieldset/lang/en/surveyproformat_fieldset.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['defaultstatus_help'] = 'The status of this fieldset at page load time.'; $string['defaultstatus'] = 'Status at page load'; +$string['defaultstatus_help'] = 'The status of this fieldset at page load time.'; $string['forceclosed'] = 'Force closed'; $string['forceopened'] = 'Force opened'; $string['ierr_contenttoolong'] = 'The fieldset label is supposed to be shorter than 128 characters'; diff --git a/format/fieldset/version.php b/format/fieldset/version.php index 18aa98b2687..9895ff2faeb 100644 --- a/format/fieldset/version.php +++ b/format/fieldset/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_fieldset'; // Full name of the plugin (used for diagnostics). diff --git a/format/fieldsetend/classes/item.php b/format/fieldsetend/classes/item.php index 49ede40b38a..edff532257f 100644 --- a/format/fieldsetend/classes/item.php +++ b/format/fieldsetend/classes/item.php @@ -39,6 +39,15 @@ */ class item extends itembase { + // Itembase properties. + + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = false; + /** * @var bool Can this item be parent? */ @@ -62,26 +71,28 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'fieldsetend'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['common_fs'] = false; $this->insetupform['content'] = false; - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -114,6 +125,15 @@ public function get_content() { return $this->content; } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Item save. * @@ -121,12 +141,7 @@ public function get_content() { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -139,37 +154,44 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { + public function item_add_fields_default_to_child_table(&$record) { return; } // MARK get. /** - * Is this item available as a parent? + * get_pdf_template. * - * @return the content of the static property "canbeparent" + * @return the template to use at response report creation */ - public static function get_canbeparent() { - return self::$canbeparent; + public static function get_pdf_template() { + return 0; } /** - * get_pdf_template. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return the template to use at response report creation + * @return array $data */ - public static function get_pdf_template() { - return 0; + public function get_plugin_presets() { + $pluginproperties = []; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** - * Get if the plugin uses a table into the db. + * Make the list of the fields using multilang * - * @return if the plugin uses a personal table in the db. + * @param boolean $includemetafields + * @return array of fields */ - public function uses_db_table() { - return false; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = []; + $fieldlist['surveyprofield_time'] = []; + + return $fieldlist; } /** @@ -177,8 +199,8 @@ public function uses_db_table() { * * @return string $schema */ - public static function item_get_plugin_schema() { - return; + public static function get_plugin_schema() { + return ''; } // MARK userform. @@ -213,6 +235,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php b/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php index 112bf8115ae..1d271151f77 100644 --- a/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php +++ b/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Fieldsetend'; -$string['userfriendlypluginname'] = 'Fieldset closure'; $string['privacy:metadata'] = 'The "Fieldset end" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Fieldset closure'; diff --git a/format/fieldsetend/version.php b/format/fieldsetend/version.php index cb30671f171..ea9e8448e64 100644 --- a/format/fieldsetend/version.php +++ b/format/fieldsetend/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_fieldsetend'; // Full name of the plugin (used for diagnostics). diff --git a/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php b/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php index c47f896ceee..bd8bc466a83 100644 --- a/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php +++ b/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php @@ -39,10 +39,7 @@ protected function define_item_subplugin_structure() { // XML nodes declaration. $subplugin = $this->get_subplugin_element(null, '../../plugin', 'label'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); - $subpluginlabel = new backup_nested_element('surveyproformat_label', ['id'], [ - 'content', 'contentformat', - 'indent', 'customnumber', - 'fullwidth', 'leftlabel', ]); + $subpluginlabel = new backup_nested_element('surveyproformat_label', ['id'], ['fullwidth', 'leftlabel']); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/format/label/classes/item.php b/format/label/classes/item.php index 5f7b1a1169b..19ba690ec3d 100644 --- a/format/label/classes/item.php +++ b/format/label/classes/item.php @@ -39,22 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** * @var int The label has a dedicated row @@ -66,6 +51,13 @@ class item extends itembase { */ protected $leftlabel; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -98,13 +90,18 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. + $this->insetupform['required'] = false; $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; $this->insetupform['required'] = false; + $this->insetupform['position'] = false; $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; $this->insetupform['hideinstructions'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -133,25 +130,31 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Traslate values from the mform of this item to values for corresponding properties. * * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -175,22 +178,51 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Label'; - $record->contentformat = 1; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->fullwidth = 0; + // $record->leftlabel + } + + // MARK set. + + /** + * Set fullwidth. + * + * @param string $fullwidth + * @return void + */ + public function set_fullwidth($fullwidth) { + $this->fullwidth = $fullwidth; + } + + /** + * Set leftlabel. + * + * @param string $leftlabel + * @return void + */ + public function set_leftlabel($leftlabel) { + $this->leftlabel = $leftlabel; } // MARK get. /** - * Is this item available as a parent? + * Get fullwidth. + * + * @return $this->fullwidth + */ + public function get_fullwidth() { + return $this->fullwidth; + } + + /** + * Get leftlabel. * - * @return the content of the static property "canbeparent" + * @return $this->leftlabel */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_leftlabel() { + return $this->leftlabel; } /** @@ -206,14 +238,31 @@ public function get_indent() { } } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['fullwidth', 'leftlabel']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'leftlabel']; + public function get_multilang_fields($includemetafields=true) { + if ($includemetafields) { + $fieldlist['surveypro_item'] = ['content', 'filename', 'filecontent']; + } else { + $fieldlist['surveypro_item'] = ['content']; + } + $fieldlist['surveyproformat_label'] = ['leftlabel']; return $fieldlist; } @@ -239,26 +288,7 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + @@ -294,9 +324,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $elementnumber = $this->customnumber ? $this->customnumber.$labelsep : ''; $elementlabel = $elementnumber.$this->leftlabel; - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' label_static'; - $mform->addElement('mod_surveypro_label', $this->itemname, $elementlabel, $this->get_content(), $attributes); + + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $elementgroup[] = $mform->createElement('static', $this->itemname, $elementlabel, $this->get_content()); + $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false, $class); } } @@ -310,6 +342,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** @@ -341,11 +374,7 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - if (empty($this->fullwidth)) { - $elementnames = [$this->itemname]; - } else { - $elementnames = []; - } + $elementnames = []; return $elementnames; } diff --git a/format/label/classes/itemsetupform.php b/format/label/classes/itemsetupform.php index a0364d6a0e8..8d9cfa4161b 100644 --- a/format/label/classes/itemsetupform.php +++ b/format/label/classes/itemsetupform.php @@ -56,7 +56,7 @@ public function definition() { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyproformat_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); // Item: fullwidth. diff --git a/format/label/db/install.xml b/format/label/db/install.xml index 856a975bd93..caf6dffa3fc 100644 --- a/format/label/db/install.xml +++ b/format/label/db/install.xml @@ -1,31 +1,15 @@ -
- - - - - - - - - - - - - - - - - - - - + + + + diff --git a/format/label/db/upgrade.php b/format/label/db/upgrade.php index a540bb92415..4a725a33ba3 100644 --- a/format/label/db/upgrade.php +++ b/format/label/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyproformat_label_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Label savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyproformat', 'label'); } @@ -63,9 +63,70 @@ function xmldb_surveyproformat_label_upgrade($oldversion) { $whereparams = ['parentid' => null, 'parentvalue' => null, 'plugin' => 'label']; $DB->execute($sql, $whereparams); - // Surveypro savepoint reached. + // Label savepoint reached. upgrade_plugin_savepoint(true, 2024011101, 'surveyproformat', 'label'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyproformat_label. + $table = new xmldb_table('surveyproformat_label'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_label} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Label savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyproformat', 'label'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyproformat_label'); + + $fieldnames = ['indent', 'customnumber']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyproformat_label. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_label} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Label savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyproformat', 'label'); + } + return true; } diff --git a/format/label/lang/en/surveyproformat_label.php b/format/label/lang/en/surveyproformat_label.php index 57fcac60a5a..34a543ae1cc 100644 --- a/format/label/lang/en/surveyproformat_label.php +++ b/format/label/lang/en/surveyproformat_label.php @@ -22,10 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['fullwidth_help'] = 'Use full screen width to display the label using as much space as possible starting from the left of the screen. When this option is used the element label and the element number will not be displayed.
As opposite alternative, the element will be drawn on the right side of the row leaving to its label the room on the left.'; $string['fullwidth'] = 'Full width'; -$string['leftlabel_help'] = 'The text that will be shown on the left of the label in the form'; +$string['fullwidth_help'] = 'Use full screen width to display the label using as much space as possible starting from the left of the screen. When this option is used the element label and the element number will not be displayed.
As opposite alternative, the element will be drawn on the right side of the row leaving to its label the room on the left.'; $string['leftlabel'] = 'Label'; +$string['leftlabel_help'] = 'The text that will be shown on the left of the label in the form'; $string['pluginname'] = 'Label'; -$string['userfriendlypluginname'] = 'Label'; $string['privacy:metadata'] = 'The "Label" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Label'; diff --git a/format/label/mform/label.php b/format/label/mform/label.php deleted file mode 100644 index c4b6c43fe10..00000000000 --- a/format/label/mform/label.php +++ /dev/null @@ -1,86 +0,0 @@ -. - -/** - * static form element - * - * HTML class for a static type element - * - * @package surveyproformat_label - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/static.php'); - -// @codingStandardsIgnoreFile - -/** - * static form element - * - * HTML class for a static type element - * - * @package surveyproformat_label - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_label extends \MoodleQuickForm_static { - - /** - * Class constructor. - * - * @param string $elementName Select name attribute - * @param mixed $elementLabel Label(s) for the select - * @param mixed $options Data to be used to populate options - * @param mixed $attributes Either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $options); - $this->_options['class'] = !isset($attributes['class']) ? 'indent-0' : $attributes['class']; - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * @return string - */ - public function toHtml() { - $output = parent::toHtml(); // Core code. - - // Even if the simpler way to pass the class is: - // $output = \html_writer::tag('div', $output, $this->_options); - // I create the array from scratch in order to - // drop any other potentially dangerous element of the original $this->_options array. - $class = ['class' => $this->_options['class']]; - $output = \html_writer::tag('div', $output, $class); - - return $output; - } -} diff --git a/format/label/version.php b/format/label/version.php index c7abe1c8304..7b73f748351 100644 --- a/format/label/version.php +++ b/format/label/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_label'; // Full name of the plugin (used for diagnostics). diff --git a/format/pagebreak/classes/item.php b/format/pagebreak/classes/item.php index 532c79df8f2..cd6947103f8 100644 --- a/format/pagebreak/classes/item.php +++ b/format/pagebreak/classes/item.php @@ -39,6 +39,15 @@ */ class item extends itembase { + // Itembase properties. + + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = false; + /** * @var bool Can this item be parent? */ @@ -62,28 +71,28 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'pagebreak'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['common_fs'] = false; $this->insetupform['content'] = false; - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; - $this->insetupform['insearchform'] = false; - $this->insetupform['reserved'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -114,17 +123,21 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Item add mandatory plugin fields * Copy mandatory fields to $record @@ -132,7 +145,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { + public function item_add_fields_default_to_child_table(&$record) { return; } @@ -146,45 +159,52 @@ public function item_uses_form_page() { } /** - * Return the xml schema for surveypro_<> table. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return string $schema + * @return array $data */ - public static function item_get_plugin_schema() { - return; - } + public function get_plugin_presets() { + $pluginproperties = []; + $data = $this->get_base_presets($pluginproperties); - // MARK get. + return $data; + } /** - * Get content. + * Make the list of the fields using multilang * - * @return the content of $content property + * @param boolean $includemetafields + * @return array of fields */ - public function get_content() { - return $this->content; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = []; + $fieldlist['surveyprofield_time'] = []; + + return $fieldlist; } /** - * Is this item available as a parent? + * Return the xml schema for surveypro_<> table. * - * @return the content of the static property "canbeparent" + * @return string $schema */ - public static function get_canbeparent() { - return self::$canbeparent; + public static function get_plugin_schema() { + return ''; } - // MARK userform. + // MARK get. /** - * Get if the plugin uses a table into the db. + * Get content. * - * @return if the plugin uses a personal table in the db. + * @return the content of $content property */ - public function uses_db_table() { - return false; + public function get_content() { + return $this->content; } + // MARK userform. + /** * Define the mform element for the userform and the searchform. * @@ -210,6 +230,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/pagebreak/lang/en/surveyproformat_pagebreak.php b/format/pagebreak/lang/en/surveyproformat_pagebreak.php index f60c43ef716..bc0bd3ce6b3 100644 --- a/format/pagebreak/lang/en/surveyproformat_pagebreak.php +++ b/format/pagebreak/lang/en/surveyproformat_pagebreak.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Page break'; -$string['userfriendlypluginname'] = 'Page break'; $string['privacy:metadata'] = 'The "Page break" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Page break'; diff --git a/format/pagebreak/version.php b/format/pagebreak/version.php index 8368f4f4c24..931577d957b 100644 --- a/format/pagebreak/version.php +++ b/format/pagebreak/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019031901; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_pagebreak'; // Full name of the plugin (used for diagnostics). diff --git a/index.php b/index.php index c14202f5774..dbde3626a73 100644 --- a/index.php +++ b/index.php @@ -31,6 +31,13 @@ require_course_login($course, true); +$context = context_course::instance($course->id); + +$params = ['context' => context_course::instance($course->id)]; +$event = \mod_surveypro\event\course_module_instance_list_viewed::create($params); +$event->add_record_snapshot('course', $course); +$event->trigger(); + // Get all required strings. $strname = get_string('name'); $strsurveypro = get_string('modulename', 'mod_surveypro'); @@ -41,8 +48,9 @@ $PAGE->set_pagelayout('incourse'); $PAGE->set_url('/mod/surveypro/index.php', ['id' => $id]); -$PAGE->navbar->add($strsurveypro, new \moodle_url('/mod/data/index.php', ['id' => $id])); -$PAGE->set_title($strsurveypro); +$PAGE->navbar->add($strsurveypro, new \moodle_url('/mod/surveypro/index.php', ['id' => $course->id])); +$titleparts = [$strdataplural, format_string($course->fullname)]; +$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); $PAGE->set_heading($course->fullname); // Is it useful? $PAGE->add_body_class('mediumwidth');. @@ -50,8 +58,6 @@ echo $OUTPUT->header(); echo $OUTPUT->heading($strdataplural, 2); -\mod_surveypro\event\course_module_instance_list_viewed::create_from_course($course)->trigger(); - // Get all the appropriate data. if (!$surveypros = get_all_instances_in_course('surveypro', $course)) { $url = new \moodle_url('/course/view.php', ['id' => $course->id]); @@ -74,7 +80,6 @@ } $table->colclasses = ['col1', 'col2', 'col3', 'col4', 'col5']; -$currentsection = -1; $sectionvisible = $DB->get_records_menu('course_sections', ['course' => $course->id], '', 'section, visible'); $sql = 'SELECT surveyproid, COUNT(id) as responses @@ -87,19 +92,24 @@ $whereparams = ['status' => SURVEYPRO_STATUSCLOSED]; $closedsubmissions = $DB->get_records_sql_menu($sql, $whereparams); +$currentsection = -1; foreach ($surveypros as $surveypro) { if ($surveypro->section != $currentsection) { if ($surveypro->section) { $printsection = get_section_name($course, $surveypro->section); - $sectionclass = $sectionvisible[$surveypro->section] ? null : ['class' => 'dimmed']; + $sectionclass = $sectionvisible[$surveypro->section] ? [] : ['class' => 'dimmed']; + } else { + $printsection = $surveypro->section; + $sectionclass = []; } $currentsection = $surveypro->section; } else { $printsection = ''; + $sectionclass = []; } if (empty($sectionclass)) { // The section is visible. - $cellclass = $surveypro->visible ? null : ['class' => 'dimmed']; + $cellclass = $surveypro->visible ? [] : ['class' => 'dimmed']; } else { $cellclass = ['class' => 'dimmed']; } @@ -108,7 +118,8 @@ $inprogressresp = isset($inprogresssubmissions[$surveypro->id]) ? $inprogresssubmissions[$surveypro->id] : 0; $closedresp = isset($closedsubmissions[$surveypro->id]) ? $closedsubmissions[$surveypro->id] : 0; - $content = [html_writer::tag('span', $printsection, $sectionclass), + $content = [ + \html_writer::tag('span', $printsection, $sectionclass), \html_writer::link($url, format_string($surveypro->name), $cellclass), \html_writer::tag('span', format_module_intro('surveypro', $surveypro, $surveypro->coursemodule), $cellclass), \html_writer::tag('span', $inprogressresp, $cellclass), diff --git a/lang/en/surveypro.php b/lang/en/surveypro.php index b7c51b99160..b3efd61d069 100644 --- a/lang/en/surveypro.php +++ b/lang/en/surveypro.php @@ -25,11 +25,11 @@ defined('MOODLE_INTERNAL') || die(); $string['abandoned_submission_deleted'] = 'Deleted abandoned response'; -$string['action_help'] = 'Operate on elements already present in the survey with the following action.'; $string['action'] = 'Preexisting elements'; +$string['action_help'] = 'Operate on elements already present in the survey with the following action.'; $string['addnewsubmission'] = 'New response'; -$string['anonymous_help'] = 'The responses management table will not show the owner of the responses and reports and export will be anonymous.'; $string['anonymous'] = 'Anonymous responses'; +$string['anonymous_help'] = 'The responses management table will not show the owner of the responses and reports and export will be anonymous.'; $string['answerisnoanswer'] = 'Answer refused'; $string['answernotsubmitted'] = 'Answer not submitted'; $string['apply'] = 'Apply'; @@ -39,16 +39,16 @@ $string['applyusertemplates'] = 'Apply user templates'; $string['arrayexpected'] = 'Array is expected in {$a}'; $string['attemptinfo'] = 'Survey and responses information'; -$string['availability_fs'] = 'Availability'; $string['availability'] = 'Availability'; +$string['availability_fs'] = 'Availability'; $string['available_title'] = 'Available element. Click to make it reserved.'; $string['badchildparentvalue'] = 'Malformed condition: "{$a}".
It might never be verified.'; $string['badtablenamefound'] = 'Parse error reading xml. "{$a}" has been found as table name and, most probably, is invalid.'; $string['basic_editthanks'] = 'Thank you. Your response has been successfully modified!'; $string['basic_submitthanks'] = 'Thank you. Your response has been successfully submitted!'; $string['branching'] = 'Branching'; -$string['bulkaction_help'] = 'Use this menu to perform actions against elements as described by labels.'; $string['bulkaction'] = 'Bulk actions'; +$string['bulkaction_help'] = 'Use this menu to perform actions against elements as described by labels.'; $string['calendar_close_description'] = 'Surveypro "{$a}" closed.'; $string['calendar_close_time'] = 'Surveypro "{$a}" is no longer available.'; $string['calendar_open_description'] = 'Fill surveypro "{$a}", please.'; @@ -56,8 +56,8 @@ $string['canneversubmit'] = 'You are not allowed to submit a response'; $string['cannotsubmittooearly'] = 'The survey is still not open. You have to wait until {$a}'; $string['cannotsubmittoolate'] = 'This survey has been closed on {$a}'; -$string['captcha_help'] = 'Add to this collectoin the captcha to increase the security.'; $string['captcha'] = 'Add captcha'; +$string['captcha_help'] = 'Add to this collectoin the captcha to increase the security.'; $string['category'] = 'Course category'; $string['changeorder_title'] = 'Reorder'; $string['closed'] = 'This survey closed at'; @@ -66,11 +66,12 @@ $string['collespreferred'] = 'COLLES (Preferred)'; $string['common_fs'] = 'General settings'; $string['completiondetail:entries'] = 'Make entries: {$a}'; +$string['completionsubmit'] = 'this is the title of the \'help\'. Where does it appear?'; $string['completionsubmit_check'] = 'Student must submit the survey at least '; -$string['completionsubmit_group_help'] = 'This survey is considered completed when the student submit it at least as much as times how it is written here.'; $string['completionsubmit_group'] = 'Require submission'; -$string['completionsubmit'] = 'this is the title of the \'help\'. Where does it appear?'; +$string['completionsubmit_group_help'] = 'This survey is considered completed when the student submit it at least as much as times how it is written here.'; $string['completionsubmitdesc'] = 'Minimum number of submissions required: {$a}'; +$string['confirm_applyutemplate'] = 'Are you sure you want to apply the usertemplate adding all its item to the current surveypro?'; $string['confirm_delete1item'] = 'Are you sure you want to delete the \'{$a->pluginname}\' element: {$a->content}'; $string['confirm_delete1utemplate'] = 'Are you sure you want to delete the user template "{$a}"'; $string['confirm_deleteallitems'] = 'Do you confirm you want to delete EACH element?'; @@ -88,23 +89,23 @@ $string['confirm_duplicateotherresponse_modified'] = 'Are you sure you want to duplicate the response owned by {$a->fullname}, created on {$a->timecreated} and modified on {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = 'Are you sure you want to duplicate the response owned by {$a->fullname}, created on {$a->timecreated} and never modified?'; $string['confirm_free1item'] = 'Making available the element "{$a->itemcontent}" you are going to make available its ancestor.
Ancestor is the element in position: {$a->ancestors}.
Do you confirm this action?'; -$string['confirm_freechainitems_newparent'] = 'Making available the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be made available too.
So, in addition to the chosen element, you are going to make available the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_freechainitems'] = 'Making available the element "{$a->itemcontent}" you are going to make available all its dependencies.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; +$string['confirm_freechainitems_newparent'] = 'Making available the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be made available too.
So, in addition to the chosen element, you are going to make available the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_hide1item'] = 'Hiding the element "{$a->itemcontent}" its dependency will be hidden too.
Dependency is the element in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_hideallitems'] = 'Do you confirm you want to hide EACH element?'; $string['confirm_hidechainitems'] = 'Hiding the element "{$a->itemcontent}" all its dependencies will be hidden too.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_reserve1item'] = 'Reserving the element "{$a->itemcontent}" you are going to reserve its dependency too.
Dependency is the element in position: {$a->dependencies}.
Do you confirm this action?'; -$string['confirm_reservechainitems_newparent'] = 'Reserving the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be reserved too.
So, in addition to the chosen element, you are going to reserve the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_reservechainitems'] = 'Reserving the element "{$a->itemcontent}" you are going to reserve all its dependencies too.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; +$string['confirm_reservechainitems_newparent'] = 'Reserving the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be reserved too.
So, in addition to the chosen element, you are going to reserve the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_show1item'] = 'Showing the element {$a->lastitem} you are going to show its ancestor(s).
Ancestor(s) is(are) the element(s) in position: {$a->ancestors}.
Do you confirm this action?'; $string['confirm_showallitems'] = 'Do you confirm you want to show EACH element?'; $string['confirm_showchainitems'] = 'Showing the element {$a->lastitem} you are going to show all its ancestors.
Ancestors are the elements in position: {$a->ancestors}.
Do you confirm this action?'; +$string['content'] = 'Content'; +$string['content_editor'] = 'Content'; $string['content_editor_err'] = 'The content is mandatory'; $string['content_editor_help'] = 'The content of the element as it will be shown to remote user.'; -$string['content_editor'] = 'Content'; $string['content_err'] = 'The content is mandatory'; $string['content_help'] = 'The content of the element as it will be shown to remote user.'; -$string['content'] = 'Content'; $string['count_allitems'] = 'Survey built on {$a} elements.'; $string['count_hiddenitems'] = '({$a} hidden)'; $string['count_pages'] = 'Divided into {$a} pages.'; @@ -113,9 +114,9 @@ $string['currentcategory'] = 'This course category'; $string['currentcourse'] = 'This course'; $string['currenttotemplate'] = 'Save current survey as master template in zip format.
To install a master template, unzip it to mod/surveypro/template/ and visit the notification page.'; +$string['customnumber'] = 'Element number'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use this field to give a custom number to the element. It may be a natural number like 1 or whatever you may need: 1a, A, 1.1.a, #1, A, A.1... Take in mind that you are responsible for the coherence of that numbers. Because of this take care if you plan to change the order of the elements.'; -$string['customnumber'] = 'Element number'; $string['dataimport'] = 'Import data'; $string['deleteabandoned_task'] = 'Deleting uncompleted submissions'; $string['deleteallitems'] = 'Delete all elements'; @@ -164,10 +165,11 @@ $string['event_usertemplate_imported'] = 'A user template has been imported'; $string['event_usertemplate_saved'] = 'A user template has been saved'; $string['exporttemplate'] = 'export template'; -$string['extranote_help'] = 'Write here a description/note about extra informations the user is supposed to know about this element.'; $string['extranote'] = 'Additional note'; -$string['extranoteinsearch_descr'] = 'Are user notes needed in the search form?'; +$string['extranote_help'] = 'Write here a description/note about extra informations the user is supposed to know about this element.'; $string['extranoteinsearch'] = 'Extra note in search form'; +$string['extranoteinsearch_descr'] = 'Are user notes needed in the search form?'; +$string['feedback_applyutemplate'] = 'The usertemplate has been applied successfully'; $string['feedback_delete1item'] = 'The \'{$a->pluginname}\' element: {$a->content} has been successfully deleted'; $string['feedback_delete1response'] = 'User response has been successfully deleted'; $string['feedback_delete1utemplate'] = 'Usertemplate "{$a}" was successfully deleted'; @@ -190,27 +192,27 @@ $string['feedback_showallitems'] = 'All the elements were successfully shown'; $string['field'] = 'field element'; $string['fieldplugin'] = 'Element plugin'; -$string['fillinginstructioninsearch_descr'] = 'Are filling instructions needed in the search form?'; $string['fillinginstructioninsearch'] = 'Filling instruction in search form'; +$string['fillinginstructioninsearch_descr'] = 'Are filling instructions needed in the search form?'; $string['forcedoptionalitem_title'] = 'Forced optional element because of default value.'; $string['format'] = 'format element'; $string['formatplugin'] = 'Format plugin'; $string['free'] = 'free'; $string['fullwidth'] = 'top left (full width)'; $string['gotolist'] = 'Continue to responses list'; -$string['hassubmissions_alert_activitycompletion'] = '
With items modification the activity completion status will change too.
You have been warned.'; $string['hassubmissions_alert'] = 'This survey has already been answered at least once.
Please proceed with extreme caution and make only neutral changes to not compromise the validity of the whole survey.

BE WARNED: Adding a new item the status of each already submitted response will be forced to "in progress".'; +$string['hassubmissions_alert_activitycompletion'] = '
With items modification the activity completion status will change too.
You have been warned.'; $string['hassubmissions_danger'] = '
"In progress" responses...
  • are subject to deletion in 4 hours if pause/resume is not allowed;
  • are subject to deletion in the number of hours set into surveypro settings page if pause/resume is allowed.
'; -$string['hidden_help'] = 'Use this option to hide the element. Hided elements will not be available to anyone. You can consider these elements as not part of the survey.'; $string['hidden'] = 'Hidden'; +$string['hidden_help'] = 'Use this option to hide the element. Hided elements will not be available to anyone. You can consider these elements as not part of the survey.'; $string['hideallitems'] = 'Hide all elements'; $string['hidefield_title'] = 'Visible element. Click to hide.'; -$string['hideinstructions_help'] = 'Use this checkbox to show/hide filling instruction for this element.'; $string['hideinstructions'] = 'Hide filling instruction'; +$string['hideinstructions_help'] = 'Use this checkbox to show/hide filling instruction for this element.'; $string['hideitems'] = 'Hide'; $string['hideshow'] = 'Hide/Show'; -$string['history_help'] = 'Preserving history, users will no longer be able to directly modify a closed response. Modification to closed responses will be saved as a new copy, leaving the original one untouched and the history preserved.'; $string['history'] = 'Preserve history'; +$string['history_help'] = 'Preserving history, users will no longer be able to directly modify a closed response. Modification to closed responses will be saved as a new copy, leaving the original one untouched and the history preserved.'; $string['ierr_invalidinput'] = 'Incorrect value entered'; $string['ierr_missingparentcontent'] = 'You need to specify a parent content otherwise clear the "{$a}" field'; $string['ierr_missingparentid'] = 'You need to select a element to branch the survey. Otherwise clear the "{$a}" field'; @@ -243,50 +245,50 @@ $string['includenames'] = 'Include owner name'; $string['includereserved'] = 'Include reserved elements'; $string['incorrectaccessdetected'] = 'Incorrect access detected'; -$string['indent_help'] = 'The indent of the element alias the left margin the element will respect once drawn.'; $string['indent'] = 'Indent'; +$string['indent_help'] = 'The indent of the element alias the left margin the element will respect once drawn.'; $string['inprogresssubmissions'] = 'In progress responses'; $string['inputclean'] = 'Input will be cleaned up from trailing spaces at save time'; +$string['insearchform'] = 'Search form'; $string['insearchform_help'] = 'Is this element going to be used in the search form?'; $string['insearchform_title'] = 'Searchable item. Click to make it not searchable.'; -$string['insearchform'] = 'Search form'; $string['invalidtypeorplugin'] = 'Invalid type or plugin were provided as item properties in the template'; $string['invitedefault'] = 'Invite'; $string['item'] = 'Element'; $string['itemcontentfilearea'] = 'Item content'; $string['itemlist'] = 'Elements list'; -$string['keepinprogress_help'] = 'Do not delete "in progress" responses in spite of module policy. "In progress" responses are supposed to be dropped to always guarantee a good reliability to the final database. If, for any reason, you need to collect also the "in progress" responses, check this box.'; $string['keepinprogress'] = 'Keep "in progress" responses'; +$string['keepinprogress_help'] = 'Do not delete "in progress" responses in spite of module policy. "In progress" responses are supposed to be dropped to always guarantee a good reliability to the final database. If, for any reason, you need to collect also the "in progress" responses, check this box.'; +$string['layout'] = 'Layout'; $string['layout_branchingvalidation'] = 'Branching validation'; $string['layout_edititem'] = 'Edit element'; $string['layout_items'] = 'Elements'; $string['layout_itemsetup'] = 'Element setup'; $string['layout_preview'] = 'Preview'; -$string['layout'] = 'Layout'; $string['left'] = 'left'; $string['likelast'] = 'Like last response'; $string['mailcontentdefault'] = 'User {FULLNAME} added a response to "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'The content of the custom message that will be sent at user response submission time. If a notification mail is requested at response submission time and this message is not provided, the default email content is used.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
to get
  • the user first name
  • the user last name
  • the user full name
  • the name of the course
  • the name of this surveypro
  • the url of this surveypro
Take care: default message is multilanguage, your custom message is going to be used as you write it and never translated.'; $string['mailcontenteditor'] = 'Notification message'; -$string['mailextraaddresses_help'] = 'Some additional email addresses to notify about new responses. Addresses are supposed to be one per row.'; +$string['mailcontenteditor_help'] = 'The content of the custom message that will be sent at user response submission time. If a notification mail is requested at response submission time and this message is not provided, the default email content is used.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
to get
  • the user first name
  • the user last name
  • the user full name
  • the name of the course
  • the name of this surveypro
  • the url of this surveypro
Take care: default message is multilanguage, your custom message is going to be used as you write it and never translated.'; $string['mailextraaddresses'] = 'More addresses'; -$string['mailroles_help'] = 'Send an email to each component of the selected roles at each response. Roles are intended at course level therefore any division into groups is neglected. The email will only advise about response from the user, not about its content and without sender details.'; +$string['mailextraaddresses_help'] = 'Some additional email addresses to notify about new responses. Addresses are supposed to be one per row.'; $string['mailroles'] = 'Roles to notify'; +$string['mailroles_help'] = 'Send an email to each component of the selected roles at each response. Roles are intended at course level therefore any division into groups is neglected. The email will only advise about response from the user, not about its content and without sender details.'; $string['managesurveyprofieldplugins'] = 'Manage field plugins'; $string['managesurveyproformatplugins'] = 'Manage format plugins'; $string['managesurveyproreportplugins'] = 'Manage report plugins'; $string['managesurveyprotemplateplugins'] = 'Manage template plugins'; $string['manageusertemplates'] = 'Manage user templates'; -$string['mastertemplate_help'] = 'Choose a master template like one of the classical ones provided by default or a custom one added to this instance of surveypro. The classical survey types are:
  • ATTLS: Attitudes To Thinking and Learning Survey.
    For more details, see the documentation on ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey.
    For more details, see the documentation on COLLES.
  • CRITICAL INCIDENTS.
    For more details, see the documentation on Critical incidents
'; $string['mastertemplate'] = 'Master templates'; +$string['mastertemplate_help'] = 'Choose a master template like one of the classical ones provided by default or a custom one added to this instance of surveypro. The classical survey types are:
  • ATTLS: Attitudes To Thinking and Learning Survey.
    For more details, see the documentation on ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey.
    For more details, see the documentation on COLLES.
  • CRITICAL INCIDENTS.
    For more details, see the documentation on Critical incidents
'; $string['mastertemplateaddendum'] = '
You can not apply this mastertemplate until you uninstall it, fix all the issues and reinstall it.'; -$string['mastertemplatename_help'] = 'Choose the name of the master template name that is going to be downloaded in zip format.'; $string['mastertemplatename'] = 'Master template name'; +$string['mastertemplatename_help'] = 'Choose the name of the master template name that is going to be downloaded in zip format.'; $string['mastertemplateplugin'] = 'Master template plugin'; -$string['maxentries_help'] = 'The maximum number of responses a student is allowed to submit for this activity.'; $string['maxentries'] = 'Maximum allowed attempts'; -$string['maxinputdelay_descr'] = 'The maximum allowed delay in hours for users to submit a survey. Even if the user is allowed to pause the data entry and restart it later, after the time defined here partial responses will be deleted. Default of 168 hours is equivalent to a week. Set this to 0 (zero) if you really want to allow partial responses (not recommended).'; +$string['maxentries_help'] = 'The maximum number of responses a student is allowed to submit for this activity.'; $string['maxinputdelay'] = 'Max input delay'; +$string['maxinputdelay_descr'] = 'The maximum allowed delay in hours for users to submit a survey. Even if the user is allowed to pause the data entry and restart it later, after the time defined here partial responses will be deleted. Default of 168 hours is equivalent to a week. Set this to 0 (zero) if you really want to allow partial responses (not recommended).'; $string['missingfile'] = 'It seems no file was selected'; $string['missingitemplugin'] = 'One or more items of the template are missing the plugin'; $string['missingitemtype'] = 'One or more items of the template are missing the type'; @@ -294,19 +296,19 @@ $string['missingmandatory'] = 'Some mandatory answer of this response has not been found. Because of this, the overall response has been marked as "{$a}".
To fix this issue, please edit the response and review item contents page per page.'; $string['missingvalidation'] = 'Some answers of this response have been found as unverified. Because of this, the overall response has been marked as "{$a}".
Your data is not necessarily incorrect but needs validation before definitive storage.
To fix this issue, please edit the response and review item contents page per page.'; $string['module'] = 'This instance of survey'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro allows the creation of custom surveys as far as built in surveys like ATTLS, COLLES and CRITICAL INCIDENTS. You can also save and reuse parts or whole of your own custom survey.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Surveypro settings'; +$string['mtemplate'] = 'Master templates'; $string['mtemplate_apply'] = 'Apply'; $string['mtemplate_save'] = 'Save'; -$string['mtemplate'] = 'Master templates'; $string['mtemplatessection'] = 'Master templates section'; -$string['neverstartedemail_help'] = 'Send a reminder email to users not starting their first submission'; $string['neverstartedemail'] = 'Email for not started survey'; -$string['newpageforchild_help'] = 'Use this option to force a new page after each branching element.'; +$string['neverstartedemail_help'] = 'Send a reminder email to users not starting their first submission'; $string['newpageforchild'] = 'Branches increase pages'; +$string['newpageforchild_help'] = 'Use this option to force a new page after each branching element.'; $string['newsubmissionbody'] = '{$a->username} submitted a new response in "{$a->surveyproname}". You can review it here'; $string['newsubmissionsubject'] = 'New response'; $string['nextformpage'] = 'Next page >>'; @@ -316,9 +318,9 @@ $string['noitemsfoundadmin'] = 'This survey has no elements. Please add them from "{$a}".'; $string['nomoreitems'] = 'On the basis of the answers provided, no more elements remain to display.
Your survey is over. You only need to submit{$a}.'; $string['nomoresubmissionsallowed'] = 'The maximun number of {$a} responses has already been reached.
No new responses are allowed'; +$string['nomtemplates'] = 'Missing master templates'; $string['nomtemplates_help'] = 'Course creator probably denied the instantiation of each master tempalte. Contact your course creator for further details.'; $string['nomtemplates_message'] = 'Sorry. Not any master template seems available in this moodle site instance.'; -$string['nomtemplates'] = 'Missing master templates'; $string['noreportsfound'] = 'There are no reports in this surveypro instillation.'; $string['nosubmissionsforenrolled'] = 'No responses were found in this survey for enrolled students.'; $string['note'] = 'Note:'; @@ -333,41 +335,41 @@ $string['opened'] = 'Opening time'; $string['optionalitem_title'] = 'Optional element. Click to make the element mandatory.'; $string['outputstyle'] = 'Output style'; -$string['overwrite_help'] = 'Selecting this checkbox you will overwrite an older template with the same name. If you leave this checkbox unselected, in case of conflicts, you will be asked for a new unique name.'; $string['overwrite'] = 'Replace older template'; +$string['overwrite_help'] = 'Selecting this checkbox you will overwrite an older template with the same name. If you leave this checkbox unselected, in case of conflicts, you will be asked for a new unique name.'; $string['pagexofy'] = 'Page {$a->formpage} of {$a->userformpagecount}'; $string['parentconstraints'] = 'Parent constraints'; -$string['parentcontent_help'] = 'This is what the user is supposed to answer to the parent element in order to enable/display this element.'; $string['parentcontent'] = 'Parent content'; +$string['parentcontent_help'] = 'This is what the user is supposed to answer to the parent element in order to enable/display this element.'; $string['parentelement_help'] = 'The element whose answer, during the compilation of the questionnaire, determines the access to the current element.'; $string['parentelement_title'] = 'Parent element'; $string['parentformat'] = 'Define the "{$a->fieldname}" format as shown here: {$a->examples}'; +$string['parentid'] = 'Parent element'; $string['parentid_header'] = 'Relation'; $string['parentid_help'] = 'Parent elements allows you to create conditional branching. Dimmed elements in the list identify hidden parent elments. Show them to have them available in this list.
Elements marked with an asterisk are reserved.'; -$string['parentid'] = 'Parent element'; $string['pause'] = 'Pause'; -$string['pauseresume_help'] = 'Allow to pause a survey in order to resume and submit it later on. You can also email users to remind their uncompleted job.'; $string['pauseresume'] = 'Allow Pause/Resume'; +$string['pauseresume_help'] = 'Allow to pause a survey in order to resume and submit it later on. You can also email users to remind their uncompleted job.'; $string['pauseresumeemail'] = 'Allow pause/resume with reminder email'; $string['pauseresumenoemail'] = 'Allow pause/resume without reminder email'; $string['pdfsubject'] = 'Single response in PDF'; $string['plugin'] = 'Element'; $string['pluginadministration'] = 'Surveypro administration'; -$string['pluginname_help'] = 'Write here the name of the survey plugin you are going to save.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Write here the name of the survey plugin you are going to save.'; $string['plugintype'] = 'Plugin type'; -$string['position_help'] = 'Use this option to choose the position of the content of the element. It can be to the left of the user interface, in a dedicated row just upper the interface to enter the answer or in a dedicated row just upper the interface spanning all the row.
Note: The left position forces the element contents to plain text without images.
The two \'top\' positions are usually needed for contents longer than few words and are required for questions containing images!'; $string['position'] = 'Question position'; -$string['previewmode'] = 'You are in \'{$a}\': buttons to save data are not supposed to display'; +$string['position_help'] = 'Use this option to choose the position of the content of the element. It can be to the left of the user interface, in a dedicated row just upper the interface to enter the answer or in a dedicated row just upper the interface spanning all the row.
Note: The left position forces the element contents to plain text without images.
The two \'top\' positions are usually needed for contents longer than few words and are required for questions containing images!'; +$string['previewmode'] = 'You are in \'{$a}\': buttons to save data are not expected'; $string['previousformpage'] = '<< Previous page'; +$string['privacy:metadata:answer'] = 'Answers to items of surveypros.'; $string['privacy:metadata:answer:content'] = 'Field where the answers to items are stored.'; $string['privacy:metadata:answer:contentformat'] = 'Field storing the format of the answers to items.'; -$string['privacy:metadata:answer'] = 'Answers to items of surveypros.'; +$string['privacy:metadata:submission'] = 'Responses to surveypros.'; $string['privacy:metadata:submission:status'] = 'The overall status of the response provided by the user.'; $string['privacy:metadata:submission:timecreated'] = 'The time when the response was posted.'; $string['privacy:metadata:submission:timemodified'] = 'The time when the response was modified.'; $string['privacy:metadata:submission:userid'] = 'The ID of the user who submitted his/her answer.'; -$string['privacy:metadata:submission'] = 'Responses to surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Field data for the surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Format data for the surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Report data for the surveypro.'; @@ -394,12 +396,12 @@ $string['reportplugin'] = 'Report plugin'; $string['reports'] = 'Reports'; $string['reportsection'] = 'Reports section'; -$string['required_help'] = 'Will the user be forced to answer this element?'; $string['required'] = 'Required'; +$string['required_help'] = 'Will the user be forced to answer this element?'; $string['requireditem_title'] = 'Mandatory element. Click to make it optional.'; +$string['reserved'] = 'Reserved'; $string['reserved_help'] = 'Is this element going to be available only to users equipped with a special permission or generally available to each user?'; $string['reserved_title'] = 'Reserved element. Click make it available.'; -$string['reserved'] = 'Reserved'; $string['response'] = 'response'; $string['responseauthor'] = 'Author: '; $string['responses'] = 'responses'; @@ -407,8 +409,8 @@ $string['responsetimemodified'] = ', Last modified on: '; $string['revieworpause'] = ', review or pause'; $string['reviewsubmissions'] = 'review surveypro submissions'; -$string['riskyeditdeadline_help'] = 'Allow users permitted to manage survey elements to force modifications of this survey even once already answered.'; $string['riskyeditdeadline'] = 'Deadline of risky modification session'; +$string['riskyeditdeadline_help'] = 'Allow users permitted to manage survey elements to force modifications of this survey even once already answered.'; $string['runreport'] = 'Run {$a->reportname} report'; $string['save'] = 'Save'; $string['saveasnew'] = 'Save as new'; @@ -416,23 +418,24 @@ $string['saveusertemplates'] = 'Save user templates'; $string['schemavalidationfailed'] = 'The template uses an invalid xml file. Please verify it'; $string['settings'] = 'Surveypro'; -$string['sharinglevel_help'] = 'Choose at which level your template will be shared with other courses. If you choose "course" this template will be available in this course ONLY, if you choose course category this template will be available ONLY to courses sharing the same course "category" with this course, if you choose "site" this template will be available to each other courses in this platform.'; $string['sharinglevel'] = 'Sharing level'; +$string['sharinglevel_help'] = 'Choose at which level your template will be shared with other courses. If you choose "course" this template will be available in this course ONLY, if you choose course category this template will be available ONLY to courses sharing the same course "category" with this course, if you choose "site" this template will be available to each other courses in this platform.'; $string['showallitems'] = 'Show all elements'; $string['showallsubmissions'] = 'Show all responses'; $string['showfield_title'] = 'Hidden element. Click to show.'; $string['sortindex'] = 'Order'; $string['specializations'] = '{$a} specific settings'; $string['star'] = '*'; -$string['startyear_help'] = 'Define the lower year that each question will require.'; $string['startyear'] = 'Minimum allowed year'; +$string['startyear_help'] = 'Define the lower year that each question will require.'; $string['status'] = 'Responses status'; $string['statusboth'] = 'closed and in progress both'; $string['statusclosed'] = 'closed'; $string['statusinprogress'] = 'in progress'; -$string['stopyear_help'] = 'Define the upper year that each question will require.'; $string['stopyear'] = 'Maximum allowed year'; +$string['stopyear_help'] = 'Define the upper year that each question will require.'; $string['submission'] = 'Attempt'; +$string['submissions'] = 'Responses'; $string['submissions_all_1_1'] = '1 response submitted by 1 user'; $string['submissions_all_1_many'] = '1 response submitted by {$a->usercount} users'; $string['submissions_all_many_1'] = '{$a->submissions} responses submitted by 1 user'; @@ -442,11 +445,14 @@ $string['submissions_detail_many_1'] = '{$a->submissions} \'{$a->status}\' responses submitted by 1 user'; $string['submissions_detail_many_many'] = '{$a->submissions} \'{$a->status}\' responses submitted by {$a->usercount} users'; $string['submissions_welcome'] = 'Responses overview'; -$string['submissions'] = 'Responses'; $string['submissionslist'] = 'Responses list'; +$string['subplugintype_surveyprofield'] = 'Surveypro field plugin'; $string['subplugintype_surveyprofield_plural'] = 'Surveypro fields plugins'; +$string['subplugintype_surveyproformat'] = 'Surveypro format plugin'; $string['subplugintype_surveyproformat_plural'] = 'Surveypro formats plugins'; +$string['subplugintype_surveyproreport'] = 'Surveypro report plugin'; $string['subplugintype_surveyproreport_plural'] = 'Surveypro reports plugins'; +$string['subplugintype_surveyprotemplate'] = 'Surveypro template plugin'; $string['subplugintype_surveyprotemplate_plural'] = 'Surveypro templates plugins'; $string['surveypro_dashboard'] = 'Dashboard'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Edit response'; @@ -536,6 +542,7 @@ $string['utemplate_apply'] = 'Apply'; $string['utemplate_import'] = 'Import'; $string['utemplate_manage'] = 'Manage'; +$string['utemplate_nolongervalid'] = '
It may be you are trying to apply a no longer valid usertemplate.'; $string['utemplate_save'] = 'Save'; $string['utemplate'] = 'User templates'; $string['utemplatessection'] = 'User templates section'; @@ -562,6 +569,7 @@ $string['wrongrelation'] = '"{$a}" will never match'; $string['xmltemplate_help'] = 'Choose the template you want to download as zip file to share it with other moodle users.'; $string['xsdnotfound'] = 'xsd validation schema for your xml template was not found.
Your code must be fixed by a developer.'; +$string['yes_applyutemplate'] = 'Yes, apply the usertemplate ignoring preexisting items'; $string['yes_deleteallitems'] = 'Delete each element'; $string['yes_deletehiddenitems'] = 'Delete each hidden element'; $string['yes_deletevisibleitems'] = 'Delete each visible element'; diff --git a/lang/es/surveypro.php b/lang/es/surveypro.php index 36d584488f2..fe7496799d9 100644 --- a/lang/es/surveypro.php +++ b/lang/es/surveypro.php @@ -24,11 +24,11 @@ defined('MOODLE_INTERNAL') || die(); -$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['action'] = 'Elementos pre-existentes'; +$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['addnewsubmission'] = 'Nueva respuesta'; -$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['anonymous'] = 'Respuestas anónimas'; +$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['answerisnoanswer'] = 'Contestación rehusada'; $string['answernotsubmitted'] = 'Contestación no enviada'; $string['apply'] = 'Aplicar'; @@ -38,21 +38,21 @@ $string['applyusertemplates'] = 'Aplicar plantillas de usuario'; $string['arrayexpected'] = 'Se espera un arreglo (una matriz) en {$a}'; $string['attemptinfo'] = 'Información de encuesta y respuestas'; -$string['availability_fs'] = 'Disponibilidad'; $string['availability'] = 'Disponibilidad'; +$string['availability_fs'] = 'Disponibilidad'; $string['available_title'] = 'Elemento de acceso libre. Haga clic para reservar.'; $string['badchildparentvalue'] = 'Condición malformada: "{$a}".
Podría ser que nunca sea verificada.'; $string['badtablenamefound'] = 'Error de procesamiento al leer XML. "{$a}" se ha encontrado como nombre de tabla y, lo más probable, es inválido.'; $string['basic_editthanks'] = 'Gracias. ¡Su respuesta ha sido modificada exitosamente!'; $string['basic_submitthanks'] = 'Gracias. ¡Su respuesta ha sido enviada exitosamente!'; $string['branching'] = 'Ramificación'; -$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['bulkaction'] = 'Acciones masivas'; +$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['canneversubmit'] = 'Usted no tiene permitido el enviar una respuesta'; $string['cannotsubmittooearly'] = 'La encuesta aun no está abierta. Usted tiene que esperar hasta {$a}'; $string['cannotsubmittoolate'] = 'La encuesta se ha cerrado en {$a}'; -$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['captcha'] = 'Añadir CAPTCHA'; +$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['category'] = 'Categoría de curso'; $string['changeorder_title'] = 'Reordenar'; $string['closed'] = 'Esta encuesta cerró en'; @@ -60,10 +60,10 @@ $string['collesactual'] = 'COLLES (Actual/Real)'; $string['collespreferred'] = 'COLLES (Favorita)'; $string['common_fs'] = 'Configuraciones generales'; +$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; $string['completionsubmit_check'] = 'Los estudiantes deben de enviar la encuesta al menos'; -$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['completionsubmit_group'] = 'Requerir envío'; -$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; +$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['confirm_delete1item'] = 'Está seguro de querer eliminar el \'{$a->pluginname}\' elemento: {$a->content}'; $string['confirm_delete1utemplate'] = '¿Está seguro de querer eliminar la plantilla del usuario "{$a}"'; $string['confirm_deleteallitems'] = '¿Confirma la eliminación de TODOS los elementos?'; @@ -81,31 +81,31 @@ $string['confirm_duplicateotherresponse_modified'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y modificada en {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y nunca modificada?'; $string['confirm_free1item'] = 'Liberando al elemento "{$a->itemcontent}" Usted va a liberar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; -$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_freechainitems'] = 'Haciendo disponible el elemento "{$a->itemcontent}" Usted va a hacer disponible todas sus dependencias.
Las dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_hide1item'] = 'Ocultando al elementot "{$a->itemcontent}" su dependencia se ocultará también.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_hideallitems'] = '¿Confirma el ocultamiento de TODOS los elementos?'; $string['confirm_hidechainitems'] = 'Al ocultar el elementot "{$a->itemcontent}" todas sus dependencias se ocultarán también.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reserve1item'] = 'Al reservar el elemento {$a->parentcontent}, Usted también va a reservar sus dependencias.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; -$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reservechainitems'] = 'Al reservar el elemento "{$a->itemcontent}" Usted también va a reservar todas sus dependencias.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_show1item'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; $string['confirm_showallitems'] = '¿Confirma el mostrar TODOS los elementos ?'; $string['confirm_showchainitems'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar todos sus ancestros.
Ancestros son los elementos en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; +$string['content'] = 'Contenido'; +$string['content_editor'] = 'Contenido'; $string['content_editor_err'] = 'El contenido es obligatorio'; $string['content_editor_help'] = 'El contenido del elemento tal como será mostrado al usuario remoto.'; -$string['content_editor'] = 'Contenido'; $string['content_err'] = 'El contenido es obligatorio'; -$string['content'] = 'Contenido'; $string['count_allitems'] = 'Encuesta construida en {$a} elementos.'; $string['count_hiddenitems'] = '({$a} ocultos)'; $string['count_pages'] = 'Dividida en {$a} páginas.'; $string['course'] = 'Curso'; $string['crontask'] = 'Trabajos de mantenimiento de Surveypro'; $string['currenttotemplate'] = 'Guardar encuesta actual como plantilla maestra en formato ZIP.
Para instalar una plantilla maestra, descomprímala a mod/surveypro/template/ y visite la página de notificaciones.'; +$string['customnumber'] = 'Elemento número'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use este campo para darle un número personalizado al elemento. Puede ser un número natural como 1 o cualquier otro que Usted necesite: 1a, A, 1.1.a, #1, A, A.1... Tome en cuenta que Usted es responsable por la coherencia de esos números. Debido a esto, tenga cuidado si Usted planea cambiar el orden de los elementos.'; -$string['customnumber'] = 'Elemento número'; $string['dataimport'] = 'Importar datos'; $string['deleteallitems'] = 'Eliminar todos los elementos'; $string['deleteallsubmissions'] = 'Eliminar todas las respuestas'; @@ -149,10 +149,10 @@ $string['event_usertemplate_imported'] = 'Se ha importado una plantilla de usuario'; $string['event_usertemplate_saved'] = 'Se ha guardado una plantilla de usuario'; $string['exporttemplate'] = 'exportar plantilla'; -$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranote'] = 'Nota adicional'; -$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; +$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranoteinsearch'] = 'Nota extra en formato de búsqueda'; +$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; $string['feedback_delete1item'] = 'El \'{$a->pluginname}\' elemento : {$a->content} ha sido eliminado exitosamente'; $string['feedback_delete1response'] = 'La respuesta del usuario ha sido eliminada exitosamente'; $string['feedback_delete1utemplate'] = 'La plantilla_de_usuario "{$a}" fue eliminada exitosamente'; @@ -175,27 +175,27 @@ $string['feedback_showallitems'] = 'Todos los elementos fueron mostrados exitosamente'; $string['field'] = 'elemento de campo'; $string['fieldplugin'] = 'Plugin de Elemento'; -$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['fillinginstructioninsearch'] = 'Instrucción de llenado en formato de búsqueda'; +$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['forcedoptionalitem_title'] = 'Elemento opcional forzado debido al valor por defecto.'; $string['format'] = 'elemento de formato'; $string['formatplugin'] = 'Plugin de formato'; $string['free'] = 'libre'; $string['fullwidth'] = 'superior izquierdo (ancho completo)'; $string['gotolist'] = 'Continuar hacia lista de respuestas'; -$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_alert'] = 'Esta encuesta ya ha sido contestada al menos una vez.
Por favor proceda con extrema cautela y sólamente haga cambios neutros que no comprometan la validez de toda la encuesta.'; +$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_danger'] = '
Las respuestas "En progreso"...
  • están sujetas a eliminación en 4 horas si no estuvierapermitido guardar/continuar;
  • están sujetas a eliminación en el número de horas configurado en la página de configuraciones de surveypro settings page si gguardar/continuar está permitido.
'; -$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hidden'] = 'Oculto'; +$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hideallitems'] = 'Ocultar todos los elementos'; $string['hidefield_title'] = 'Elemento visible. Hacer clic para ocultar.'; -$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideinstructions'] = 'Ocultar instrucciones de llenado'; +$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideitems'] = 'Ocultar'; $string['hideshow'] = 'Ocultar/Mostrar'; -$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['history'] = 'Preservar historia'; +$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['ierr_invalidinput'] = 'Valor incorrecto ingresado'; $string['ierr_missingparentcontent'] = 'Usted necesita especificar un contenido paterno o de lo contrario vaciar el campo "{$a}"'; $string['ierr_missingparentid'] = 'Usted necesita seleccionar un elemento para ramificar la encuesta. De lo contario, vaciar el campo "{$a}"'; @@ -228,48 +228,48 @@ $string['includenames'] = 'Incluir nombre del propietario'; $string['includereserved'] = 'Incluir elementos reservados'; $string['incorrectaccessdetected'] = 'Acceso incorrecto detectado'; -$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['indent'] = 'Indentar'; +$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['inprogresssubmissions'] = 'Respuestas en progreso'; $string['inputclean'] = 'La entrada será limpiada de espacios finales al momento de guardar'; +$string['insearchform'] = 'Formato de búsqueda'; $string['insearchform_help'] = '¿Será usado este elemento en el formato de búsqueda?'; $string['insearchform_title'] = 'Ítem buscable. Haga clic para hacerlo no buscable.'; -$string['insearchform'] = 'Formato de búsqueda'; $string['invalidtypeorplugin'] = 'Tipo inválido o plugin fueron proporcionados como propiedades de ítem en la plantilla'; $string['invitedefault'] = 'Invitar'; $string['item'] = 'Elemento'; $string['itemlist'] = 'Lista de elementos'; -$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; $string['keepinprogress'] = 'Conservar respuestas "en progreso" '; +$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; +$string['layout'] = 'Diseño'; $string['layout_branchingvalidation'] = 'Validación ramificada'; $string['layout_items'] = 'Elementos'; $string['layout_itemsetup'] = 'Configuración de elemento'; $string['layout_preview'] = 'Previsualización'; -$string['layout'] = 'Diseño'; $string['left'] = 'izquierda'; $string['likelast'] = 'Como la última respuesta'; $string['mailcontentdefault'] = 'Usuario {FULLNAME} añadió una respuesta a "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailcontenteditor'] = 'Mensaje de notificación'; -$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; +$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailextraaddresses'] = 'Más direcciones'; -$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; +$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; $string['mailroles'] = 'Roles a notificarle'; +$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; $string['managesurveyprofieldplugins'] = 'Gestionar plugins de campo'; $string['managesurveyproformatplugins'] = 'Gestionar plugins de formato'; $string['managesurveyproreportplugins'] = 'Gestionar plugins de reporte'; $string['managesurveyprotemplateplugins'] = 'Gestionar plugins de plantilla'; $string['manageusertemplates'] = 'Gestionar plantillas de usuario'; -$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplate'] = 'Plantillas maestras'; +$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplateaddendum'] = '
Usted no puede aplicar esta plantilla_maestra hasta que la des-instale, le arregle todos los problemas y la re-instale.'; -$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplatename'] = 'Nombre de plantilla maestra'; +$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplateplugin'] = 'Plugin de plantilla maestra'; -$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxentries'] = 'Máximos intentos permitidos'; -$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; +$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxinputdelay'] = 'Retraso máximo para contestar'; +$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; $string['missingfile'] = 'Al parecer no se seleccionó ningun archivo'; $string['missingitemplugin'] = 'A uno o más ítems de la plantilla les falta el plugin'; $string['missingitemtype'] = 'A uno o más ítems de la plantilla les falta el tipo'; @@ -277,17 +277,17 @@ $string['missingmandatory'] = 'No se ha encontrado alguna contestación obligatoria de esta respuesta. Por esto, las respuestas generales se han marcado como "{$a}".
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['missingvalidation'] = 'Algunas contestaciones de esta respuesta han sido encontradas como no-verificadas. Por esto, la respuesta general la sido marcada como "{$a}".
Sus datos no son necesariamente incorrectos, pero necesitan validación antes del almacenamiento definitivo.
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['module'] = 'Esta instancia de encuesta'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro le permite crear encuestas personalizadas, tanto como encuestas tipo ATTLS, COLLES y de INCIDENTES CRÍTICOS. Usted también puede gurdar y re-utilizar partes de, o toda su encuenta personalizada.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Configuraciones de Encuestapro (Surveypro)'; +$string['mtemplate'] = 'Master plantillas'; $string['mtemplate_apply'] = 'Aplicar'; $string['mtemplate_save'] = 'Guardar'; -$string['mtemplate'] = 'Master plantillas'; $string['mtemplatessection'] = 'Sección de plantillas maestras'; -$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newpageforchild'] = 'Las ramas aumentan las páginas'; +$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newsubmissionbody'] = '{$a->username} envió un nuevo registro en "{$a->surveyproname}" Usted puede revisarlo aquí'; $string['newsubmissionsubject'] = 'Nueva respuesta'; $string['nextformpage'] = 'Página siguiente >>'; @@ -297,9 +297,9 @@ $string['noitemsfoundadmin'] = 'Esta plantilla no tiene elementos. Por favor añádalos desde "{$a}".'; $string['nomoreitems'] = 'Con base en las contestaciones proporcionadas, ya no quedan más elementos para mostrar.
Su encuesta está terminada. Usted solamente necesita enviar {$a}.'; $string['nomoresubmissionsallowed'] = 'El número máximo de {$a} respuestas ya fue alcanzado.
No se permiten más intentos'; +$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nomtemplates_help'] = 'El creador del curso probablemente negó la instalación de cada plantilla maestra. Contacte a su creador del curso para más detalles.'; $string['nomtemplates_message'] = 'Lo sentimos. No aparece ninguna plantilla maestra disponible en esta instancia de sitio Moodle.'; -$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nosubmissionfound'] = 'No se encontraron repuestas en esta encuesta.'; $string['note'] = 'Nota:'; $string['nothingtodownload'] = 'Nada para descargar'; @@ -310,38 +310,38 @@ $string['opened'] = 'Hora de apertura'; $string['optionalitem_title'] = 'Elemento opcional. Haga click para volver obligatorio al elemento.'; $string['outputstyle'] = 'Estilo de salida'; -$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['overwrite'] = 'Remplazar plantilla más antigua'; +$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['pagexofy'] = 'Página {$a->formpage} de {$a->userformpagecount}'; $string['parentconstraints'] = 'Limitantes paternas'; -$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentcontent'] = 'Contenido paterno'; +$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentelement_help'] = 'El elemento cuya respuesta, durante la compilación del questionnaire, determina el acceso al elemento actual.'; $string['parentelement_title'] = 'Elemento paterno'; $string['parentformat'] = 'Defina el formato "{$a->fieldname}" tal y como se muestra aquí: {$a->examples}'; +$string['parentid'] = 'Elemento paterno'; $string['parentid_header'] = 'Relación'; $string['parentid_help'] = 'Los elementos paternos le permiten a Usted crear ramificación condicional. Los elementos atenuados en la lista identifican elementos paternos ocultos. Muéstrelos para tenerlos disponibles en la lista.
Elementos precedidos por un asterisco se supone que pertenecen SOLAMENTE a formato reservado.'; -$string['parentid'] = 'Elemento paterno'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['pauseresume'] = 'Permitir Guardar/Continuar'; +$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['plugin'] = 'Elemento'; $string['pluginadministration'] = 'Administración de Surveypro'; -$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['plugintype'] = 'Tipo de plugin'; -$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['position'] = 'Posición de la pregunta'; +$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['previewmode'] = 'Usted está en \'{$a}\': se supone que no deben de mostrarse los botones para guardar datos'; $string['previousformpage'] = '<< Página anterior'; +$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; $string['privacy:metadata:answer:content'] = 'Campo donde son almacenados las respuestas a ítems.'; $string['privacy:metadata:answer:contentformat'] = 'Campo que almacena el formato de las respuestas a los ítems.'; -$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; +$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:submission:status'] = 'El estdo global de la respuesta proporcionada por el usuario.'; $string['privacy:metadata:submission:timecreated'] = 'La hora de cuando se publicó la respuesta.'; $string['privacy:metadata:submission:timemodified'] = 'La hora de cuando se modificó la respuesta.'; $string['privacy:metadata:submission:userid'] = 'La ID del usuario que mandó su respuesta.'; -$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Datos de campo para el surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Datos de formato para el surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Datos de reporte para el surveypro.'; @@ -357,12 +357,12 @@ $string['reportplugin'] = 'Plugin de reporte'; $string['reports'] = 'Reportes'; $string['reportsection'] = 'Sección de reportes'; -$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['required'] = 'Requerido'; +$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['requireditem_title'] = 'Elemento obligatorio. Haga clic para hacer opcional al elemento.'; +$string['reserved'] = 'Reservado'; $string['reserved_help'] = '¿Este elemento solamente estará disponible para usuarios equipados con un permiso especial, o generalmente estará disponible para cada usuario?'; $string['reserved_title'] = 'Elemento reservado. Haga click para liberarlo.'; -$string['reserved'] = 'Reservado'; $string['response'] = 'respuesta'; $string['responseauthor'] = 'Autor:'; $string['responses'] = 'respuestas'; @@ -370,8 +370,8 @@ $string['responsetimemodified'] = ', Última midificación en:'; $string['revieworpause'] = ', revisar o pausar'; $string['reviewsubmissions'] = 'Revisar envíos de Encuestapro'; -$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['riskyeditdeadline'] = 'Fecha límite de sesión de modificación riesgosa'; +$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['runreport'] = 'Correr reporte de {$a->reportname}'; $string['save'] = 'Guardar'; $string['saveasnew'] = 'Guardar como nuevo'; @@ -379,23 +379,24 @@ $string['saveusertemplates'] = 'Guardar plantillas de usuario'; $string['schemavalidationfailed'] = 'La plantilla usa un archivo XML inválido. Por favor verifíquelo'; $string['settings'] = 'Encuestapro (Surveypro)'; -$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['sharinglevel'] = 'Nivel de compartir'; +$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['showallitems'] = 'Mostrar todos los elementos'; $string['showallsubmissions'] = 'Mostrar todas las respuestas'; $string['showfield_title'] = 'Elemento oculto. Haga click para mostrar.'; $string['sortindex'] = 'Orden'; $string['specializations'] = 'Configuraciones específicas de {$a}'; $string['star'] = '*'; -$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['startyear'] = 'Año mínimo permitido'; +$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['status'] = 'Estatus de encuesta'; $string['statusboth'] = 'ambas cerrada y en progreso'; $string['statusclosed'] = 'cerrada'; $string['statusinprogress'] = 'en progreso'; -$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['stopyear'] = 'Año máximo permitido'; +$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['submission'] = 'Intento'; +$string['submissions'] = 'Respuestas'; $string['submissions_all_1_1'] = '1 respuesta enviada por 1 usuario'; $string['submissions_all_1_many'] = '1 respuesta enviada por {$a->usercount} usuarios'; $string['submissions_all_many_1'] = '{$a->submissions} respuestas enviadas por 1 usuario'; @@ -405,7 +406,6 @@ $string['submissions_detail_many_1'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por 1 usuario'; $string['submissions_detail_many_many'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por {$a->usercount} usuarios'; $string['submissions_welcome'] = 'Vista general de respuestas'; -$string['submissions'] = 'Respuestas'; $string['submissionslist'] = 'Lista de respuestas'; $string['surveypro_dashboard'] = 'Tablero'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Editar'; diff --git a/lang/es_mx/surveypro.php b/lang/es_mx/surveypro.php index 26952e0e474..055189d7073 100644 --- a/lang/es_mx/surveypro.php +++ b/lang/es_mx/surveypro.php @@ -24,11 +24,11 @@ defined('MOODLE_INTERNAL') || die(); -$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['action'] = 'Elementos pre-existentes'; +$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['addnewsubmission'] = 'Nueva respuesta'; -$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['anonymous'] = 'Respuestas anónimas'; +$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['answerisnoanswer'] = 'Contestación rehusada'; $string['answernotsubmitted'] = 'Contestación no enviada'; $string['apply'] = 'Aplicar'; @@ -38,21 +38,21 @@ $string['applyusertemplates'] = 'Aplicar plantillas de usuario'; $string['arrayexpected'] = 'Se espera un arreglo (una matriz) en {$a}'; $string['attemptinfo'] = 'Información de encuesta y respuestas'; -$string['availability_fs'] = 'Disponibilidad'; $string['availability'] = 'Disponibilidad'; +$string['availability_fs'] = 'Disponibilidad'; $string['available_title'] = 'Elemento de acceso libre. Haga clic para reservar.'; $string['badchildparentvalue'] = 'Condición malformada: "{$a}".
Podría ser que nunca sea verificada.'; $string['badtablenamefound'] = 'Error de procesamiento al leer XML. "{$a}" se ha encontrado como nombre de tabla y, lo más probable, es inválido.'; $string['basic_editthanks'] = 'Gracias. ¡Su respuesta ha sido modificada exitosamente!'; $string['basic_submitthanks'] = 'Gracias. ¡Su respuesta ha sido enviada exitosamente!'; $string['branching'] = 'Ramificación'; -$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['bulkaction'] = 'Acciones masivas'; +$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['canneversubmit'] = 'Usted no tiene permitido el enviar una respuesta'; $string['cannotsubmittooearly'] = 'La encuesta aun no está abierta. Usted tiene que esperar hasta {$a}'; $string['cannotsubmittoolate'] = 'La encuesta se ha cerrado en {$a}'; -$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['captcha'] = 'Añadir CAPTCHA'; +$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['category'] = 'Categoría de curso'; $string['changeorder_title'] = 'Reordenar'; $string['closed'] = 'Esta encuesta cerró en'; @@ -60,10 +60,10 @@ $string['collesactual'] = 'COLLES (Actual/Real)'; $string['collespreferred'] = 'COLLES (Favorita)'; $string['common_fs'] = 'Configuraciones generales'; +$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; $string['completionsubmit_check'] = 'Los estudiantes deben de enviar la encuesta al menos'; -$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['completionsubmit_group'] = 'Requerir envío'; -$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; +$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['confirm_delete1item'] = 'Está seguro de querer eliminar el \'{$a->pluginname}\' elemento: {$a->content}'; $string['confirm_delete1utemplate'] = '¿Está seguro de querer eliminar la plantilla del usuario "{$a}"'; $string['confirm_deleteallitems'] = '¿Confirma la eliminación de TODOS los elementos?'; @@ -81,32 +81,30 @@ $string['confirm_duplicateotherresponse_modified'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y modificada en {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y nunca modificada?'; $string['confirm_free1item'] = 'Liberando al elemento "{$a->itemcontent}" Usted va a liberar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; -$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_freechainitems'] = 'Haciendo disponible el elemento "{$a->itemcontent}" Usted va a hacer disponible todas sus dependencias.
Las dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_hide1item'] = 'Ocultando al elementot "{$a->itemcontent}" su dependencia se ocultará también.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_hideallitems'] = '¿Confirma el ocultamiento de TODOS los elementos?'; $string['confirm_hidechainitems'] = 'Al ocultar el elementot "{$a->itemcontent}" todas sus dependencias se ocultarán también.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reserve1item'] = 'Al reservar el elemento {$a->parentcontent}, Usted también va a reservar sus dependencias.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; -$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reservechainitems'] = 'Al reservar el elemento "{$a->itemcontent}" Usted también va a reservar todas sus dependencias.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_show1item'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; $string['confirm_showallitems'] = '¿Confirma el mostrar TODOS los elementos ?'; $string['confirm_showchainitems'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar todos sus ancestros.
Ancestros son los elementos en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; +$string['content'] = 'Contenido'; +$string['content_editor'] = 'Contenido'; $string['content_editor_err'] = 'El contenido es obligatorio'; -$string['content_editor_err'] = 'El contenido es obligatorio'; -$string['content_editor_help'] = 'El contenido del elemento tal como será mostrado al usuario remoto.'; $string['content_editor_help'] = 'El contenido del elemento tal y como se le mostrará al usuario remoto.'; -$string['content_editor'] = 'Contenido'; -$string['content'] = 'Contenido'; $string['count_allitems'] = 'Encuesta construida en {$a} elementos.'; $string['count_hiddenitems'] = '({$a} ocultos)'; $string['count_pages'] = 'Dividida en {$a} páginas.'; $string['course'] = 'Curso'; $string['crontask'] = 'Trabajos de mantenimiento de Surveypro'; $string['currenttotemplate'] = 'Guardar encuesta actual como plantilla maestra en formato ZIP.
Para instalar una plantilla maestra, descomprímala a mod/surveypro/template/ y visite la página de notificaciones.'; +$string['customnumber'] = 'Elemento número'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use este campo para darle un número personalizado al elemento. Puede ser un número natural como 1 o cualquier otro que Usted necesite: 1a, A, 1.1.a, #1, A, A.1... Tome en cuenta que Usted es responsable por la coherencia de esos números. Debido a esto, tenga cuidado si Usted planea cambiar el orden de los elementos.'; -$string['customnumber'] = 'Elemento número'; $string['dataimport'] = 'Importar datos'; $string['deleteallitems'] = 'Eliminar todos los elementos'; $string['deleteallsubmissions'] = 'Eliminar todas las respuestas'; @@ -150,10 +148,10 @@ $string['event_usertemplate_imported'] = 'Se ha importado una plantilla de usuario'; $string['event_usertemplate_saved'] = 'Se ha guardado una plantilla de usuario'; $string['exporttemplate'] = 'exportar plantilla'; -$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranote'] = 'Nota adicional'; -$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; +$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranoteinsearch'] = 'Nota extra en formato de búsqueda'; +$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; $string['feedback_delete1item'] = 'El \'{$a->pluginname}\' elemento : {$a->content} ha sido eliminado exitosamente'; $string['feedback_delete1response'] = 'La respuesta del usuario ha sido eliminada exitosamente'; $string['feedback_delete1utemplate'] = 'La plantilla_de_usuario "{$a}" fue eliminada exitosamente'; @@ -176,27 +174,27 @@ $string['feedback_showallitems'] = 'Todos los elementos fueron mostrados exitosamente'; $string['field'] = 'elemento de campo'; $string['fieldplugin'] = 'Plugin de Elemento'; -$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['fillinginstructioninsearch'] = 'Instrucción de llenado en formato de búsqueda'; +$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['forcedoptionalitem_title'] = 'Elemento opcional forzado debido al valor por defecto.'; $string['format'] = 'elemento de formato'; $string['formatplugin'] = 'Plugin de formato'; $string['free'] = 'libre'; $string['fullwidth'] = 'superior izquierdo (ancho completo)'; $string['gotolist'] = 'Continuar hacia lista de respuestas'; -$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_alert'] = 'Esta encuesta ya ha sido contestada al menos una vez.
Por favor proceda con extrema cautela y sólamente haga cambios neutros que no comprometan la validez de toda la encuesta.'; +$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_danger'] = '
Las respuestas "En progreso"...
  • están sujetas a eliminación en 4 horas si no estuvierapermitido guardar/continuar;
  • están sujetas a eliminación en el número de horas configurado en la página de configuraciones de surveypro settings page si gguardar/continuar está permitido.
'; -$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hidden'] = 'Oculto'; +$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hideallitems'] = 'Ocultar todos los elementos'; $string['hidefield_title'] = 'Elemento visible. Hacer clic para ocultar.'; -$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideinstructions'] = 'Ocultar instrucciones de llenado'; +$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideitems'] = 'Ocultar'; $string['hideshow'] = 'Ocultar/Mostrar'; -$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['history'] = 'Preservar historia'; +$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['ierr_invalidinput'] = 'Valor incorrecto ingresado'; $string['ierr_missingparentcontent'] = 'Usted necesita especificar un contenido paterno o de lo contrario vaciar el campo "{$a}"'; $string['ierr_missingparentid'] = 'Usted necesita seleccionar un elemento para ramificar la encuesta. De lo contario, vaciar el campo "{$a}"'; @@ -229,48 +227,48 @@ $string['includenames'] = 'Incluir nombre del propietario'; $string['includereserved'] = 'Incluir elementos reservados'; $string['incorrectaccessdetected'] = 'Acceso incorrecto detectado'; -$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['indent'] = 'Indentar'; +$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['inprogresssubmissions'] = 'Respuestas en progreso'; $string['inputclean'] = 'La entrada será limpiada de espacios finales al momento de guardar'; +$string['insearchform'] = 'Formato de búsqueda'; $string['insearchform_help'] = '¿Será usado este elemento en el formato de búsqueda?'; $string['insearchform_title'] = 'Ítem buscable. Haga clic para hacerlo no buscable.'; -$string['insearchform'] = 'Formato de búsqueda'; $string['invalidtypeorplugin'] = 'Tipo inválido o plugin fueron proporcionados como propiedades de ítem en la plantilla'; $string['invitedefault'] = 'Invitar'; $string['item'] = 'Elemento'; $string['itemlist'] = 'Lista de elementos'; -$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; $string['keepinprogress'] = 'Conservar respuestas "en progreso" '; +$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; +$string['layout'] = 'Diseño'; $string['layout_branchingvalidation'] = 'Validación ramificada'; $string['layout_items'] = 'Elementos'; $string['layout_itemsetup'] = 'Configuración de elemento'; $string['layout_preview'] = 'Previsualización'; -$string['layout'] = 'Diseño'; $string['left'] = 'izquierda'; $string['likelast'] = 'Como la última respuesta'; $string['mailcontentdefault'] = 'Usuario {FULLNAME} añadió una respuesta a "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailcontenteditor'] = 'Mensaje de notificación'; -$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; +$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailextraaddresses'] = 'Más direcciones'; -$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; +$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; $string['mailroles'] = 'Roles a notificarle'; +$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; $string['managesurveyprofieldplugins'] = 'Gestionar plugins de campo'; $string['managesurveyproformatplugins'] = 'Gestionar plugins de formato'; $string['managesurveyproreportplugins'] = 'Gestionar plugins de reporte'; $string['managesurveyprotemplateplugins'] = 'Gestionar plugins de plantilla'; $string['manageusertemplates'] = 'Gestionar plantillas de usuario'; -$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplate'] = 'Plantillas maestras'; +$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplateaddendum'] = '
Usted no puede aplicar esta plantilla_maestra hasta que la des-instale, le arregle todos los problemas y la re-instale.'; -$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplatename'] = 'Nombre de plantilla maestra'; +$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplateplugin'] = 'Plugin de plantilla maestra'; -$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxentries'] = 'Máximos intentos permitidos'; -$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; +$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxinputdelay'] = 'Retraso máximo para contestar'; +$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; $string['missingfile'] = 'Al parecer no se seleccionó ningun archivo'; $string['missingitemplugin'] = 'A uno o más ítems de la plantilla les falta el plugin'; $string['missingitemtype'] = 'A uno o más ítems de la plantilla les falta el tipo'; @@ -278,17 +276,17 @@ $string['missingmandatory'] = 'No se ha encontrado alguna contestación obligatoria de esta respuesta. Por esto, las respuestas generales se han marcado como "{$a}".
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['missingvalidation'] = 'Algunas contestaciones de esta respuesta han sido encontradas como no-verificadas. Por esto, la respuesta general la sido marcada como "{$a}".
Sus datos no son necesariamente incorrectos, pero necesitan validación antes del almacenamiento definitivo.
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['module'] = 'Esta instancia de encuesta'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro le permite crear encuestas personalizadas, tanto como encuestas tipo ATTLS, COLLES y de INCIDENTES CRÍTICOS. Usted también puede gurdar y re-utilizar partes de, o toda su encuenta personalizada.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Configuraciones de Encuestapro (Surveypro)'; +$string['mtemplate'] = 'Master plantillas'; $string['mtemplate_apply'] = 'Aplicar'; $string['mtemplate_save'] = 'Guardar'; -$string['mtemplate'] = 'Master plantillas'; $string['mtemplatessection'] = 'Sección de plantillas maestras'; -$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newpageforchild'] = 'Las ramas aumentan las páginas'; +$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newsubmissionbody'] = '{$a->username} envió un nuevo registro en "{$a->surveyproname}" Usted puede revisarlo aquí'; $string['newsubmissionsubject'] = 'Nueva respuesta'; $string['nextformpage'] = 'Página siguiente >>'; @@ -298,9 +296,9 @@ $string['noitemsfoundadmin'] = 'Esta plantilla no tiene elementos. Por favor añádalos desde "{$a}".'; $string['nomoreitems'] = 'Con base en las contestaciones proporcionadas, ya no quedan más elementos para mostrar.
Su encuesta está terminada. Usted solamente necesita enviar {$a}.'; $string['nomoresubmissionsallowed'] = 'El número máximo de {$a} respuestas ya fue alcanzado.
No se permiten más intentos'; +$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nomtemplates_help'] = 'El creador del curso probablemente negó la instalación de cada plantilla maestra. Contacte a su creador del curso para más detalles.'; $string['nomtemplates_message'] = 'Lo sentimos. No aparece ninguna plantilla maestra disponible en esta instancia de sitio Moodle.'; -$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nosubmissionfound'] = 'No se encontraron repuestas en esta encuesta.'; $string['note'] = 'Nota:'; $string['nothingtodownload'] = 'Nada para descargar'; @@ -311,38 +309,38 @@ $string['opened'] = 'Hora de apertura'; $string['optionalitem_title'] = 'Elemento opcional. Haga click para volver obligatorio al elemento.'; $string['outputstyle'] = 'Estilo de salida'; -$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['overwrite'] = 'Remplazar plantilla más antigua'; +$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['pagexofy'] = 'Página {$a->formpage} de {$a->userformpagecount}'; $string['parentconstraints'] = 'Limitantes paternas'; -$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentcontent'] = 'Contenido paterno'; +$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentelement_help'] = 'El elemento cuya respuesta, durante la compilación del questionnaire, determina el acceso al elemento actual.'; $string['parentelement_title'] = 'Elemento paterno'; $string['parentformat'] = 'Defina el formato "{$a->fieldname}" tal y como se muestra aquí: {$a->examples}'; +$string['parentid'] = 'Elemento paterno'; $string['parentid_header'] = 'Relación'; $string['parentid_help'] = 'Los elementos paternos le permiten a Usted crear ramificación condicional. Los elementos atenuados en la lista identifican elementos paternos ocultos. Muéstrelos para tenerlos disponibles en la lista.
Elementos precedidos por un asterisco se supone que pertenecen SOLAMENTE a formato reservado.'; -$string['parentid'] = 'Elemento paterno'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['pauseresume'] = 'Permitir Guardar/Continuar'; +$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['plugin'] = 'Elemento'; $string['pluginadministration'] = 'Administración de Surveypro'; -$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['plugintype'] = 'Tipo de plugin'; -$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['position'] = 'Posición de la pregunta'; +$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['previewmode'] = 'Usted está en \'{$a}\': se supone que no deben de mostrarse los botones para guardar datos'; $string['previousformpage'] = '<< Página anterior'; +$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; $string['privacy:metadata:answer:content'] = 'Campo donde son almacenados las respuestas a ítems.'; $string['privacy:metadata:answer:contentformat'] = 'Campo que almacena el formato de las respuestas a los ítems.'; -$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; +$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:submission:status'] = 'El estdo global de la respuesta proporcionada por el usuario.'; $string['privacy:metadata:submission:timecreated'] = 'La hora de cuando se publicó la respuesta.'; $string['privacy:metadata:submission:timemodified'] = 'La hora de cuando se modificó la respuesta.'; $string['privacy:metadata:submission:userid'] = 'La ID del usuario que mandó su respuesta.'; -$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Datos de campo para el surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Datos de formato para el surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Datos de reporte para el surveypro.'; @@ -358,12 +356,12 @@ $string['reportplugin'] = 'Plugin de reporte'; $string['reports'] = 'Reportes'; $string['reportsection'] = 'Sección de reportes'; -$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['required'] = 'Requerido'; +$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['requireditem_title'] = 'Elemento obligatorio. Haga clic para hacer opcional al elemento.'; +$string['reserved'] = 'Reservado'; $string['reserved_help'] = '¿Este elemento solamente estará disponible para usuarios equipados con un permiso especial, o generalmente estará disponible para cada usuario?'; $string['reserved_title'] = 'Elemento reservado. Haga click para liberarlo.'; -$string['reserved'] = 'Reservado'; $string['response'] = 'respuesta'; $string['responseauthor'] = 'Autor:'; $string['responses'] = 'respuestas'; @@ -371,8 +369,8 @@ $string['responsetimemodified'] = ', Última midificación en:'; $string['revieworpause'] = ', revisar o pausar'; $string['reviewsubmissions'] = 'Revisar envíos de Encuestapro'; -$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['riskyeditdeadline'] = 'Fecha límite de sesión de modificación riesgosa'; +$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['runreport'] = 'Correr reporte de {$a->reportname}'; $string['save'] = 'Guardar'; $string['saveasnew'] = 'Guardar como nuevo'; @@ -380,23 +378,24 @@ $string['saveusertemplates'] = 'Guardar plantillas de usuario'; $string['schemavalidationfailed'] = 'La plantilla usa un archivo XML inválido. Por favor verifíquelo'; $string['settings'] = 'Encuestapro (Surveypro)'; -$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['sharinglevel'] = 'Nivel de compartir'; +$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['showallitems'] = 'Mostrar todos los elementos'; $string['showallsubmissions'] = 'Mostrar todas las respuestas'; $string['showfield_title'] = 'Elemento oculto. Haga click para mostrar.'; $string['sortindex'] = 'Orden'; $string['specializations'] = 'Configuraciones específicas de {$a}'; $string['star'] = '*'; -$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['startyear'] = 'Año mínimo permitido'; +$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['status'] = 'Estatus de encuesta'; $string['statusboth'] = 'ambas cerrada y en progreso'; $string['statusclosed'] = 'cerrada'; $string['statusinprogress'] = 'en progreso'; -$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['stopyear'] = 'Año máximo permitido'; +$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['submission'] = 'Intento'; +$string['submissions'] = 'Respuestas'; $string['submissions_all_1_1'] = '1 respuesta enviada por 1 usuario'; $string['submissions_all_1_many'] = '1 respuesta enviada por {$a->usercount} usuarios'; $string['submissions_all_many_1'] = '{$a->submissions} respuestas enviadas por 1 usuario'; @@ -406,7 +405,6 @@ $string['submissions_detail_many_1'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por 1 usuario'; $string['submissions_detail_many_many'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por {$a->usercount} usuarios'; $string['submissions_welcome'] = 'Vista general de respuestas'; -$string['submissions'] = 'Respuestas'; $string['submissionslist'] = 'Lista de respuestas'; $string['surveypro_dashboard'] = 'Tablero'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Editar'; diff --git a/lang/it/surveypro.php b/lang/it/surveypro.php index 9928c8c5c4f..430f8d444a7 100644 --- a/lang/it/surveypro.php +++ b/lang/it/surveypro.php @@ -51,8 +51,8 @@ $string['cssstylefilearea'] = 'Fogli di stile'; $string['currentcategory'] = 'Questa categoria di corso'; $string['currentcourse'] = 'Questo corso'; -$string['customnumber_help'] = 'Definisce un numero personalizzato per l\'elemento. Può essere un numero intero come "1" o una qualunque altra scelta come, per esempio: 1a, A, 1.1.a, #1, A, A.1... Si consideri la coerenza della numerazione è lasciata alla tua responsabilità. Per questo, si faccia sempre una doppia verifica qualora si scegliesse di modificare l\'ordine delle domande.'; $string['customnumber'] = 'Numero dell\'elemento'; +$string['customnumber_help'] = 'Definisce un numero personalizzato per l\'elemento. Può essere un numero intero come "1" o una qualunque altra scelta come, per esempio: 1a, A, 1.1.a, #1, A, A.1... Si consideri la coerenza della numerazione è lasciata alla tua responsabilità. Per questo, si faccia sempre una doppia verifica qualora si scegliesse di modificare l\'ordine delle domande.'; $string['deleteallitems'] = 'Elimina tutti gli elementi'; $string['deleteallsubmissions'] = 'Cancella tutte le risposte'; $string['deletehiddenitems'] = 'Elimina gli elementi nascosti'; @@ -88,43 +88,43 @@ $string['event_usertemplate_exported'] = 'Esportato "template utente"'; $string['event_usertemplate_imported'] = 'Importato "template utente"'; $string['event_usertemplate_saved'] = 'Salvato "template utente"'; -$string['extranote_help'] = 'Breve nota aggiuntiva relativa a dettagli necessari per rispondere a questa domanda.'; $string['extranote'] = 'Nota personalizzata'; +$string['extranote_help'] = 'Breve nota aggiuntiva relativa a dettagli necessari per rispondere a questa domanda.'; $string['feedback_deleteallresponses'] = 'Tutte le risposte sono state cancellate con successo'; $string['gotolist'] = 'Mostra la lista'; -$string['hassubmissions_alert_activitycompletion'] = '
La modifica degli elementi del sondaggio cambierà anche lo stato di completamento dell\'attività.
Sei stato avvisato.'; $string['hassubmissions_alert'] = 'Questo sondaggio è stato già compilato almeno una volta.
Si procedera con estrema cautela e si apportino solo modifiche neutre per non compromettere la validità dell\'intero sondaggio.

ATTENZIONE: Aggiungendo un nuovo elemento lo stato di ogni risposta già inviata verrà forzato a "in corso".'; +$string['hassubmissions_alert_activitycompletion'] = '
La modifica degli elementi del sondaggio cambierà anche lo stato di completamento dell\'attività.
Sei stato avvisato.'; $string['hassubmissions_danger'] = '
Le risposte "in corso"...
  • sono soggette a cancellazione in 4 ore se la pausa/ripresa non è consentita;
  • sono soggette a cancellazione nel numero di ore impostato nelle impostazioni di surveypro se la pausa/ripresa è consentita.
'; -$string['hidden_help'] = 'Nascondi questa domanda qualora sia ancora in fase di definizione o, comunque, non ancora pronta per comparire regolarmente nel questionario.'; $string['hidden'] = 'Nascosta'; +$string['hidden_help'] = 'Nascondi questa domanda qualora sia ancora in fase di definizione o, comunque, non ancora pronta per comparire regolarmente nel questionario.'; $string['hideallitems'] = 'Nascondi tutti gli elementi'; -$string['hideinstructions_help'] = 'Nasconde o mostra le istruzioni di compilazione. Queste indirizzano l\'utente a fornire la risposta attesa riducendo il tempo necesario alla compilazione del questionario.'; $string['hideinstructions'] = 'Nascondi le istruzioni di compilazione'; +$string['hideinstructions_help'] = 'Nasconde o mostra le istruzioni di compilazione. Queste indirizzano l\'utente a fornire la risposta attesa riducendo il tempo necesario alla compilazione del questionario.'; $string['importusertemplates'] = 'Importa un template utente'; $string['includedates'] = 'Includi le date di creazione e modifica'; $string['includehidden'] = 'Includi gli elementi nascosti'; $string['includereserved'] = 'Includi gli elementi riservati'; -$string['indent_help'] = 'Il rientro dell\'elemento ovvero il margine sinistro che avrà rispetto alla pagina del questionario.'; $string['indent'] = 'Rientro'; -$string['insearchform_help'] = 'Includi questo elemento fra i campi di ricerca?'; +$string['indent_help'] = 'Il rientro dell\'elemento ovvero il margine sinistro che avrà rispetto alla pagina del questionario.'; $string['insearchform'] = 'Includi nella ricerca'; +$string['insearchform_help'] = 'Includi questo elemento fra i campi di ricerca?'; $string['item'] = 'Elemento'; $string['itemcontentfilearea'] = 'Contentenuto degli elementi'; +$string['layout'] = 'Scheda'; $string['layout_branchingvalidation'] = 'Relazioni'; $string['layout_edititem'] = 'Modifica elemento'; $string['layout_items'] = 'Elementi'; $string['layout_itemsetup'] = 'Nuovo elemento'; $string['layout_preview'] = 'Anteprima'; -$string['layout'] = 'Scheda'; $string['manageusertemplates'] = 'Gestisci i template utente'; $string['maxentries'] = 'Numero massimo di risposte consentite'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro consente la realizzazione di indagini personalizzate così come di indagini classiche quali ATTLS, COLLES and CRITICAL INCIDENTS. E\' possibile anche riutilizzare parti di indagini già costruite per integrarle in altre.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveypro'; +$string['mtemplate'] = 'Template di sistema'; $string['mtemplate_apply'] = 'Applica'; $string['mtemplate_save'] = 'Salva'; -$string['mtemplate'] = 'Template di sistema'; $string['nextformpage'] = 'Pagina successiva >>'; $string['noanswer'] = 'Nessuna risposta'; $string['noitemsfound'] = 'This survey is still a work in progress.
Please try again later.'; @@ -138,18 +138,18 @@ $string['opened'] = 'Data di apertura'; $string['outputstyle'] = 'Stile del file'; $string['parentconstraints'] = 'Opzioni di relazione'; -$string['parentcontent_help'] = 'Risposta che l\'utente deve fornire all\'elemento padre affinché questo elemento divenga acessibile.'; $string['parentcontent'] = 'Risposta abilitante'; -$string['parentelement_help'] = 'Elemento la cui risposta, in fase di compilazione del questionario, determina l\'accesso a all\'elemento corrente'; +$string['parentcontent_help'] = 'Risposta che l\'utente deve fornire all\'elemento padre affinché questo elemento divenga acessibile.'; $string['parentelement'] = 'Elemento padre'; +$string['parentelement_help'] = 'Elemento la cui risposta, in fase di compilazione del questionario, determina l\'accesso a all\'elemento corrente'; $string['parentformat'] = 'Definisci il formato del "{$a->fieldname}" come dai seguenti esempi: {$a->examples}'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Consente di interrompere una compilazione per riprenderla ed inviarla in un secondo momento'; $string['pauseresume'] = 'Consenti Pausa/Ripresa'; +$string['pauseresume_help'] = 'Consente di interrompere una compilazione per riprenderla ed inviarla in un secondo momento'; $string['pluginadministration'] = 'Amministrazione surveypro'; $string['pluginname'] = 'Surveypro'; -$string['position_help'] = 'Colloca il testo della domanda intorno all\'elemento di acquisizione del dato. La collocazione può essere a sinistra dell\'elemento di input, in una riga dedicata immediatamente sopra all\'elemento di input oppure, sempre sopra all\'elemento di input, ma ricoprendo l\'intera larghezza della pagina.'; $string['position'] = 'Collocazione della domanda'; +$string['position_help'] = 'Colloca il testo della domanda intorno all\'elemento di acquisizione del dato. La collocazione può essere a sinistra dell\'elemento di input, in una riga dedicata immediatamente sopra all\'elemento di input oppure, sempre sopra all\'elemento di input, ma ricoprendo l\'intera larghezza della pagina.'; $string['previewmode'] = 'Sei in \'{$a}\'. I bottoni per il salvataggio dei dati non saranno visualizzati'; $string['previousformpage'] = '<< Pagina precedente'; $string['raw'] = 'Grezzo (per ulteriori importazioni in surveypro; il "{$a}" scelto potrebbe non essere rispettato;)'; @@ -167,10 +167,10 @@ $string['reminderpaused_content3'] = '
Per favore, cerca di collegarti al più presto a {$a} per inviare definitivamente le informazioni richieste.

Il personale di progetto'; $string['remindneverstarted_content'] = 'Gentile {$a->fullname}
sembra che il tuo contributo all\'indagine "{$a->surveyproname}" non sia mai stato avviato.
Per favore, collegati al più presto a {$a->surveyprourl} per avviare la tua collaborazione con l\'indagine che ti vede coinvolto.

Il personale di progetto'; $string['reports'] = 'Rapporti'; -$string['required_help'] = 'Rende questa domanda obbligatoria o opzionale per l\'utente?'; $string['required'] = 'Obbligatorio'; -$string['reserved_help'] = 'Rendi questo elemento disponibile solo agli utenti con specifico permesso di compilazione o, in alternativa, rendi questo elemento accessibile a chiunque.'; +$string['required_help'] = 'Rende questa domanda obbligatoria o opzionale per l\'utente?'; $string['reserved'] = 'Riservato'; +$string['reserved_help'] = 'Rendi questo elemento disponibile solo agli utenti con specifico permesso di compilazione o, in alternativa, rendi questo elemento accessibile a chiunque.'; $string['revieworpause'] = ', rivederlo o metterlo in pausa'; $string['runreport'] = 'Esegui il report {$a->reportname}'; $string['savemastertemplates'] = 'Salva un master template'; diff --git a/layout.php b/layout.php index 3d373c7066f..f9834c21320 100644 --- a/layout.php +++ b/layout.php @@ -25,11 +25,11 @@ use mod_surveypro\utility_page; use mod_surveypro\utility_layout; use mod_surveypro\utility_submission; -use mod_surveypro\utility_mform; use mod_surveypro\layout_itemsetup; use mod_surveypro\layout_itemlist; use mod_surveypro\layout_preview; +use mod_surveypro\layout_branchingvalidation; use mod_surveypro\utemplate_apply; use mod_surveypro\mtemplate_apply; @@ -40,7 +40,7 @@ use mod_surveypro\local\form\utemplate_applyform; use mod_surveypro\local\form\mtemplate_applyform; use mod_surveypro\local\form\item_bulkactionform; -use mod_surveypro\local\form\userform; +use mod_surveypro\local\form\response_submitform; require_once(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/lib.php'); @@ -83,8 +83,6 @@ $overflowpage = optional_param('overflowpage', 0, PARAM_INT); // Went the user to a overflow page? // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - $previewman = new layout_preview($cm, $context, $surveypro); $previewman->setup($submissionid, $formpage); @@ -110,7 +108,7 @@ $formparams->overflowpage = $overflowpage; // Went the user to a overflow page? // End of: prepare params for the form. - $userform = new userform($formurl, $formparams, 'post', '', ['id' => 'userentry']); + $userform = new response_submitform($formurl, $formparams, 'post', '', ['id' => 'userentry', 'class' => 'narrowlines']); // Begin of: manage form submission. if ($data = $userform->get_data()) { @@ -365,7 +363,7 @@ $plugin = optional_param('plugin', null, PARAM_TEXT); $itemid = optional_param('itemid', 0, PARAM_INT); $action = optional_param('act', SURVEYPRO_NOACTION, PARAM_INT); - $mode = optional_param('mode', SURVEYPRO_NOMODE, PARAM_INT); // Ho sostituito SURVEYPRO_NEWRESPONSEMODE con SURVEYPRO_NOMODE? + $mode = optional_param('mode', SURVEYPRO_NOMODE, PARAM_INT); // I replaced SURVEYPRO_NEWRESPONSEMODE con SURVEYPRO_NOMODE? // Required capability. require_capability('mod/surveypro:additems', $context); @@ -398,8 +396,7 @@ // Begin of: get item. $itemtype = $itemsetupman->get_type(); $itemplugin = $itemsetupman->get_plugin(); - $item = surveypro_get_item($cm, $surveypro, $itemid, $itemtype, $itemplugin, true); - $item->set_editor(); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $itemtype, $itemplugin, true); // End of: get item. // Set $PAGE params. @@ -428,7 +425,7 @@ // End of: define $itemform return url. // Begin of: prepare params for the form. - $classname = 'surveyprofield_'.$itemplugin.'\itemsetupform'; + $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemplugin.'\itemsetupform'; $itemform = new $classname($formurl, ['item' => $item], null, null, ['id' => 'itemsetup']); // End of: prepare params for the form. @@ -448,7 +445,7 @@ $feedback = $item->get_itemeditingfeedback(); // Copy the returned feedback. // Overwrite item to get new settings in the object. - $item = surveypro_get_item($cm, $surveypro, $itemid, $item->get_type(), $item->get_plugin()); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $item->get_type(), $item->get_plugin()); $item->item_update_childrenparentvalue(); $paramurl = ['s' => $cm->instance, 'section' => 'itemslist', 'iefeedback' => $feedback]; @@ -468,9 +465,9 @@ $message = $utilitysubmissionman->get_submissions_warning(); echo $OUTPUT->notification($message, 'notifyproblem'); } - $itemsetupman->item_identitycard(); + $itemsetupman->display_iteminfo(); - $data = $item->get_itemform_preset(); + $data = $item->get_plugin_presets(); $itemform->set_data($data); $itemform->display(); diff --git a/lib.php b/lib.php index d3dac42c2c3..4adc06344cb 100644 --- a/lib.php +++ b/lib.php @@ -89,6 +89,7 @@ // ACTIONS in UTEMPLATE section. define('SURVEYPRO_DELETEUTEMPLATE' , '21'); define('SURVEYPRO_EXPORTUTEMPLATE' , '22'); +define('SURVEYPRO_APPLYUTEMPLATE' , '23'); /** * VIEW @@ -126,11 +127,6 @@ /** * INVITE, NO-ANSWER AND IGNOREME VALUE */ -// Since the very first beginning of the development. -// define('SURVEYPRO_INVITATIONVALUE', '__invItat10n__'); // User should never guess it. -// define('SURVEYPRO_NOANSWERVALUE', '__n0__Answer__'); // User should never guess it. -// define('SURVEYPRO_IGNOREMEVALUE', '__1gn0rE__me__'); // User should never guess it. - // Starting from version 2015090901. define('SURVEYPRO_INVITEVALUE' , '@@_INVITE_@@'); // User should never guess it. define('SURVEYPRO_NOANSWERVALUE' , '@@_NOANSW_@@'); // User should never guess it. @@ -266,6 +262,15 @@ require_once($CFG->dirroot.'/mod/surveypro/deprecatedlib.php'); /* Do not include any libraries here! */ +/** + * Get icon mapping for font-awesome. + * + * @return array + */ +function mod_surveypro_get_fontawesome_icon_map() { + return ['mod_surveypro:stamp' => 'fa-solid fa-stamp']; +} + /** * Saves a new instance of the surveypro into the database * @@ -1156,7 +1161,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $fieldplugins = core_component::get_plugin_list('surveypro'.SURVEYPRO_TYPEFIELD); if (!empty($includetype)) { foreach ($fieldplugins as $k => $v) { - if (!get_config('surveyprofield_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFIELD.'_'.$k, 'disabled')) { $fieldplugins[$k] = SURVEYPRO_TYPEFIELD.'_'.$k; } else { unset($fieldplugins[$k]); @@ -1165,7 +1170,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $fieldplugins = array_flip($fieldplugins); } else { foreach ($fieldplugins as $k => $v) { - if (!get_config('surveyprofield_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFIELD.'_'.$k, 'disabled')) { $fieldplugins[$k] = $k; } else { unset($fieldplugins[$k]); @@ -1181,7 +1186,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $formatplugins = core_component::get_plugin_list('surveypro'.SURVEYPRO_TYPEFORMAT); if (!empty($includetype)) { foreach ($formatplugins as $k => $v) { - if (!get_config('surveyproformat_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$k, 'disabled')) { $formatplugins[$k] = SURVEYPRO_TYPEFORMAT.'_'.$k; } else { unset($formatplugins[$k]); @@ -1190,7 +1195,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $formatplugins = array_flip($formatplugins); } else { foreach ($formatplugins as $k => $v) { - if (!get_config('surveyproformat_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$k, 'disabled')) { $formatplugins[$k] = $k; } else { unset($formatplugins[$k]); @@ -1350,7 +1355,7 @@ function surveypro_inplace_editable($itemtype, $id, $newvalue) { * @param bool $getparentcontent * @return $item object */ -function surveypro_get_item($cm, $surveypro, $itemid=0, $type='', $plugin='', $getparentcontent=false) { +function surveypro_get_itemclass($cm, $surveypro, $itemid=0, $type='', $plugin='', $getparentcontent=false) { global $CFG, $DB; if (!empty($itemid)) { diff --git a/mod_form.php b/mod_form.php index a732d62a1f3..29604c9e804 100644 --- a/mod_form.php +++ b/mod_form.php @@ -253,8 +253,9 @@ public function data_preprocessing(&$defaults) { $draftitemid = file_get_submitted_draft_itemid($filename.'_filemanager'); if ($this->current->instance) { - file_prepare_draft_area($draftitemid, $this->context->id, 'mod_surveypro', - SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions); + file_prepare_draft_area( + $draftitemid, $this->context->id, 'mod_surveypro', SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions + ); $defaults[$filename.'_filemanager'] = $draftitemid; // Manage thankspage editor. @@ -262,8 +263,10 @@ public function data_preprocessing(&$defaults) { $editoroptions = surveypro_get_editor_options(); // Editing an existing surveypro - let us prepare the added editor elements (intro done automatically). $draftitemid = file_get_submitted_draft_itemid('thankspage'); - $defaults[$filename]['text'] = file_prepare_draft_area($draftitemid, $this->context->id, - 'mod_surveypro', SURVEYPRO_THANKSPAGEFILEAREA, 0, $editoroptions, $defaults['thankspage']); + $defaults[$filename]['text'] = file_prepare_draft_area( + $draftitemid, $this->context->id, + 'mod_surveypro', SURVEYPRO_THANKSPAGEFILEAREA, 0, $editoroptions, $defaults['thankspage'] + ); $defaults[$filename]['format'] = $defaults['thankspageformat']; $defaults[$filename]['itemid'] = $draftitemid; @@ -282,8 +285,9 @@ public function data_preprocessing(&$defaults) { $defaults[$filename]['format'] = $defaults['mailcontentformat']; } } else { - file_prepare_draft_area($draftitemid, $this->context->id, 'mod_surveypro', - SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions); + file_prepare_draft_area( + $draftitemid, $this->context->id, 'mod_surveypro', SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions + ); $defaults[$filename.'_filemanager'] = $draftitemid; // Manage thankspage editor. diff --git a/mtemplates.php b/mtemplates.php index a2b5f68a4d5..1c28b067f72 100644 --- a/mtemplates.php +++ b/mtemplates.php @@ -37,8 +37,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('mtemplates'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); @@ -77,7 +77,12 @@ // Start of: define $createmtemplate return url. $formurl = new \moodle_url('/mod/surveypro/mtemplates.php', ['s' => $cm->instance, 'section' => 'save']); - $createmtemplate = new mtemplate_createform($formurl); + // End of: define $createutemplate return url. + + // Begin of: prepare params for the form. + $formparams = new \stdClass(); + $formparams->defaultname = $surveypro->name; + $createmtemplate = new mtemplate_createform($formurl, $formparams); // End of: define $createmtemplate return url. // Start of: manage form submission. @@ -140,8 +145,12 @@ // Begin of: manage form submission. if ($applyman->formdata = $applymtemplate->get_data()) { - $applyman->apply_template(); - $applyman->trigger_event('mastertemplate_applied'); + $applyman->set_mastertemplate($applyman->formdata->mastertemplate); + $applyman->lastminute_template_check(); + if (!isset($applyman->xmlvalidationoutcome->key)) { + $applyman->apply_template(); + $applyman->trigger_event('mastertemplate_applied'); + } } // End of: manage form submission. @@ -163,6 +172,8 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_mtemplates_action_bar(); + $applyman->lastminute_stop(); + $applyman->friendly_stop(); $riskyediting = ($surveypro->riskyeditdeadline > time()); diff --git a/pix/stamp.png b/pix/stamp.png new file mode 100644 index 0000000000000000000000000000000000000000..88eb31238b69a7db5cb0c5200fe4ea5e4bf31c30 GIT binary patch literal 379 zcmV->0fhdEP)K~zebQL3i#3MvYv2T)Mycmb6}FCR`y!CB0_g#90z#Ky^rxqZXbbDw6Ts&JmCaspaA9&SSn$Q z8Jq9s*Ywt8o);yondd||xk}&?U#OR`g?zzv54%qWXE-kHduR?5;u_vClJ|RTRdGiv zEOcy)VJfBcfoYsq5&H?W^PJ6jz)ht002ovPDHLkV1mA)naltH literal 0 HcmV?d00001 diff --git a/pix/stamp.svg b/pix/stamp.svg new file mode 100644 index 00000000000..29a212a0389 --- /dev/null +++ b/pix/stamp.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/report/attachments/classes/filterform.php b/report/attachments/classes/filterform.php index 5ba7a987cd7..395000638be 100644 --- a/report/attachments/classes/filterform.php +++ b/report/attachments/classes/filterform.php @@ -73,7 +73,7 @@ public function definition() { if ($itemseed->plugin != 'fileupload') { continue; } - $content = $DB->get_field('surveyprofield_fileupload', 'content', ['itemid' => $itemseed->id]); + $content = $DB->get_field('surveypro_item', 'content', ['id' => $itemseed->id]); $options[$itemseed->id] = strip_tags($content); } $itemseeds->close(); diff --git a/report/attachments/classes/form.php b/report/attachments/classes/form.php index 002d3933273..51685c2f7bc 100644 --- a/report/attachments/classes/form.php +++ b/report/attachments/classes/form.php @@ -54,6 +54,16 @@ class form { */ protected $surveypro; + /** + * @var int $userid + */ + protected $userid; + + /** + * @var int $itemid + */ + protected $itemid; + /** * @var int ID of the saved suryey_submission */ @@ -171,10 +181,9 @@ public function display_attachment($submissionid, $itemid) { echo $renderer->render_report_paragraph($viewreportparagraph); $whereparams = ['submissionid' => $submissionid, 'plugin' => 'fileupload']; - $sql = 'SELECT i.id, a.id as answerid, fu.content + $sql = 'SELECT i.id, i.content, a.id as answerid FROM {surveypro_item} i JOIN {surveypro_answer} a ON a.itemid = i.id - JOIN {surveyprofield_fileupload} fu ON fu.itemid = a.itemid WHERE i.plugin = :plugin AND a.submissionid = :submissionid'; if ($itemid) { diff --git a/report/attachments/classes/report.php b/report/attachments/classes/report.php index a5af3a9a445..eabb4847663 100644 --- a/report/attachments/classes/report.php +++ b/report/attachments/classes/report.php @@ -93,7 +93,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'attachments'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/attachments/lang/en/surveyproreport_attachments.php b/report/attachments/lang/en/surveyproreport_attachments.php index 73cf1e4667f..1725f0967f1 100644 --- a/report/attachments/lang/en/surveyproreport_attachments.php +++ b/report/attachments/lang/en/surveyproreport_attachments.php @@ -28,11 +28,11 @@ $string['missing_uploads'] = 'No attachments found'; $string['noattachmentitemsfound'] = 'No attachment items were found in this survey.'; $string['nofilesfound'] = 'no attachment uploaded'; +$string['notinanygroup'] = 'Not in any group'; $string['pluginname'] = 'Attachments overview'; +$string['privacy:metadata'] = 'The "Attachments" report plugin does not store any personal data.'; $string['submission'] = 'Response'; $string['submissionid'] = 'Response id'; $string['submissioninfo'] = 'Response info'; $string['submissions'] = 'Responses'; $string['uploads'] = 'Uploads'; -$string['notinanygroup'] = 'Not in any group'; -$string['privacy:metadata'] = 'The "Attachments" report plugin does not store any personal data.'; diff --git a/report/attachments/tests/behat/attachment_functionality.feature b/report/attachments/tests/behat/attachment_functionality.feature index fe692283859..87b72fcc494 100644 --- a/report/attachments/tests/behat/attachment_functionality.feature +++ b/report/attachments/tests/behat/attachment_functionality.feature @@ -26,9 +26,6 @@ Feature: Test attachment report And the following "permission overrides" exist: | capability | permission | role | contextlevel | reference | | mod/surveypro:editownsubmissions | Allow | student | Course | Test attachment report | - And the following "user preferences" exist: - | user | preference | value | - | teacher1 | htmleditor | textarea | And the following "activities" exist: | activity | name | intro | course | | surveypro | Attachment report test | To test functionality of attachment report | Test attachment report | diff --git a/report/attachments/version.php b/report/attachments/version.php index 914a9144153..7beaddd4c97 100644 --- a/report/attachments/version.php +++ b/report/attachments/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023120101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_attachments'; // Full name of the plugin (used for diagnostics). diff --git a/report/attachments/view.php b/report/attachments/view.php index ac63569891a..6233fac7558 100644 --- a/report/attachments/view.php +++ b/report/attachments/view.php @@ -194,7 +194,7 @@ $formparams->canviewhiddenactivities = $canviewhiddenactivities; // End of: prepare params for the form. - $filterform = new filterform($formurl, $formparams, 'post', '', ['id' => 'userentry']); + $filterform = new filterform($formurl, $formparams, 'post', '', ['id' => 'userentry', 'class' => 'narrowlines']); // Output starts here. echo $OUTPUT->header(); diff --git a/report/colles/classes/report.php b/report/colles/classes/report.php index 95977a9c17b..0a24d40f3dd 100644 --- a/report/colles/classes/report.php +++ b/report/colles/classes/report.php @@ -330,8 +330,8 @@ public function fetch_summarydata() { // Begin of: options (label of answers). $itemid = $qid1area[0][0]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->ylabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->ylabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: calculate the mean and the standard deviation of answers. @@ -486,8 +486,8 @@ public function fetch_scalesdata($areaidx=0) { // Begin of: options (label of answers). $itemid = $qid1area[0][0]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->ylabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->ylabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: calculate the mean and the standard deviation of answers. @@ -607,8 +607,8 @@ public function fetch_questionsdata($areaidx, $qid) { // Begin of: options (label of answers). $itemid = $qid1area[$areaidx][$qid]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->xlabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->xlabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: graph title. diff --git a/report/colles/graph.php b/report/colles/graph.php index e4f5aba3a3c..ea8495cb9bd 100644 --- a/report/colles/graph.php +++ b/report/colles/graph.php @@ -28,8 +28,8 @@ require_once($CFG->libdir.'/graphlib.php'); require_once($CFG->dirroot.'/mod/surveypro/report/colles/lib.php'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $type = required_param('type', PARAM_ALPHA); // Report type. if (!empty($id)) { diff --git a/report/colles/lang/en/surveyproreport_colles.php b/report/colles/lang/en/surveyproreport_colles.php index e356743692b..79351720241 100644 --- a/report/colles/lang/en/surveyproreport_colles.php +++ b/report/colles/lang/en/surveyproreport_colles.php @@ -22,46 +22,46 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Colles report'; -$string['seemoredetail'] = 'Click here to see more detail'; - -$string['summary'] = 'Summary report'; - -$string['collespreferred'] = 'preferred'; $string['collesactual'] = 'actual'; - -$string['summaryreport'] = 'Summary report'; -$string['scalesreport'] = 'Scales report'; -$string['questionsreport'] = 'Questions report'; - +$string['collespreferred'] = 'preferred'; +$string['pluginname'] = 'Colles report'; +$string['privacy:metadata'] = 'The "Colles" report plugin does not store any personal data.'; $string['question01short'] = 'focus on interesting issues'; $string['question02short'] = 'important to my practice'; $string['question03short'] = 'improve my practice'; $string['question04short'] = 'connects with my practice'; - $string['question05short'] = 'I\'m critical of my learning'; $string['question06short'] = 'I\'m critical of my own ideas'; $string['question07short'] = 'I\'m critical of other students'; $string['question08short'] = 'I\'m critical of readings'; - $string['question09short'] = 'I explain my ideas'; $string['question10short'] = 'I ask for explanations'; $string['question11short'] = 'I\'m asked to explain'; $string['question12short'] = 'students respond to me'; - $string['question13short'] = 'tutor stimulates thinking'; $string['question14short'] = 'tutor encourages me'; $string['question15short'] = 'tutor models discourse'; $string['question16short'] = 'tutor models self-reflection'; - $string['question17short'] = 'students encourage me'; $string['question18short'] = 'students praise me'; $string['question19short'] = 'students value me'; $string['question20short'] = 'students empathise'; - $string['question21short'] = 'I understand other students'; $string['question22short'] = 'students understand me'; $string['question23short'] = 'I understand the tutor'; $string['question24short'] = 'tutor understands me'; +$string['questionsreport'] = 'Questions report'; +$string['scalesreport'] = 'Scales report'; +$string['seemoredetail'] = 'Click here to see more detail'; + +$string['summary'] = 'Summary report'; + + +$string['summaryreport'] = 'Summary report'; + + + + + + -$string['privacy:metadata'] = 'The "Colles" report plugin does not store any personal data.'; diff --git a/report/colles/version.php b/report/colles/version.php index c147f9516ee..4cd4b115c9c 100644 --- a/report/colles/version.php +++ b/report/colles/version.php @@ -24,9 +24,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->dependencies = [ 'surveyprotemplate_collesactual' => 2013103101, 'surveyprotemplate_collesactualpreferred' => 2013103101, diff --git a/report/frequency/classes/filterform.php b/report/frequency/classes/filterform.php index 4562eb94ed3..0e859b635bb 100644 --- a/report/frequency/classes/filterform.php +++ b/report/frequency/classes/filterform.php @@ -71,13 +71,14 @@ public function definition() { if (($itemseed->plugin == 'textarea') || ($itemseed->plugin == 'fileupload')) { continue; } - $where = ['itemid' => $itemseed->id]; - $thiscontent = $DB->get_field('surveypro'.$itemseed->type.'_'.$itemseed->plugin, 'content', $where); + $where = ['id' => $itemseed->id]; + $thiscontent = $DB->get_field('surveypro_item', 'content', $where); if (!empty($surveypro->template)) { $thiscontent = get_string($thiscontent, 'surveyprotemplate_'.$surveypro->template); } - $content = get_string('pluginname', 'surveyprofield_'.$itemseed->plugin).$labelsep.strip_tags($thiscontent); + $content = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemseed->plugin); + $content .= $labelsep.strip_tags($thiscontent); $content = surveypro_cutdownstring($content); $options[$itemseed->id] = $content; } diff --git a/report/frequency/classes/report.php b/report/frequency/classes/report.php index 98561e31bf5..0e9596d6820 100644 --- a/report/frequency/classes/report.php +++ b/report/frequency/classes/report.php @@ -103,7 +103,6 @@ public function setup_outputtable($itemid) { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'frequencies'); $this->outputtable->set_attribute('class', 'generaltable'); @@ -166,7 +165,7 @@ public function fetch_data($itemid) { // TAKE CARE: this is the answer count, not the submissions count! They may be different. [$sql, $whereparams] = $this->get_answercount_sql($itemid); $answercount = $DB->count_records_sql($sql, $whereparams); - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid); $decimalseparator = get_string('decsep', 'langconfig'); foreach ($answers as $answer) { diff --git a/report/frequency/graph.php b/report/frequency/graph.php index d017eaef689..5a9524c7ed7 100644 --- a/report/frequency/graph.php +++ b/report/frequency/graph.php @@ -47,7 +47,7 @@ list($sql, $whereparams) = $reportman->get_submissions_sql($itemid); $answers = $DB->get_recordset_sql($sql, $whereparams); -$item = surveypro_get_item($cm, $surveypro, $itemid); +$item = surveypro_get_itemclass($cm, $surveypro, $itemid); $content = []; $absolute = []; diff --git a/report/frequency/lang/en/surveyproreport_frequency.php b/report/frequency/lang/en/surveyproreport_frequency.php index 6a83cc34523..01978b8df58 100644 --- a/report/frequency/lang/en/surveyproreport_frequency.php +++ b/report/frequency/lang/en/surveyproreport_frequency.php @@ -24,11 +24,11 @@ $string['absolute'] = 'absolute'; $string['content'] = 'answer'; -$string['itemid_help'] = 'The variable to calculate its distribution'; $string['itemid'] = 'Survey question'; +$string['itemid_help'] = 'The variable to calculate its distribution'; $string['nosubmissionsfound'] = 'No submissions found'; $string['percentage'] = 'percentage'; $string['pleasechooseavalue'] = 'Please choose a variable to make its distribution'; $string['pluginname'] = 'Frequency distribution'; -$string['textareasarenotallowed'] = 'This survey has no fields or uses only fields, among visible and not reserved, that are not suitable for this report.'; $string['privacy:metadata'] = 'The "Frequency" report plugin does not store any personal data.'; +$string['textareasarenotallowed'] = 'This survey has no fields or uses only fields, among visible and not reserved, that are not suitable for this report.'; diff --git a/report/frequency/lang/it/surveyproreport_frequency.php b/report/frequency/lang/it/surveyproreport_frequency.php index 20c4409f121..fc6399e643f 100644 --- a/report/frequency/lang/it/surveyproreport_frequency.php +++ b/report/frequency/lang/it/surveyproreport_frequency.php @@ -22,5 +22,5 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Distribuzione di frequenza'; $string['nosubmissionsfound'] = 'Nessuna risposta trovata.'; +$string['pluginname'] = 'Distribuzione di frequenza'; diff --git a/report/frequency/version.php b/report/frequency/version.php index 9f8eace287a..1fe4c88a0a7 100644 --- a/report/frequency/version.php +++ b/report/frequency/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_frequency'; // Full name of the plugin (used for diagnostics). diff --git a/report/lateusers/classes/report.php b/report/lateusers/classes/report.php index 67667e90991..c5dcadd03aa 100644 --- a/report/lateusers/classes/report.php +++ b/report/lateusers/classes/report.php @@ -98,7 +98,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'lateusers'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/lateusers/version.php b/report/lateusers/version.php index 4b0252261d8..d65e456c7f8 100644 --- a/report/lateusers/version.php +++ b/report/lateusers/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_lateusers'; // Full name of the plugin (used for diagnostics). diff --git a/report/responsesperuser/classes/report.php b/report/responsesperuser/classes/report.php index c12a4493946..c518f8ce1ca 100644 --- a/report/responsesperuser/classes/report.php +++ b/report/responsesperuser/classes/report.php @@ -101,7 +101,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); // $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'responsesperuser'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/responsesperuser/version.php b/report/responsesperuser/version.php index 448effd9ba0..43b6c852197 100644 --- a/report/responsesperuser/version.php +++ b/report/responsesperuser/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_responsesperuser'; // Full name of the plugin (used for diagnostics). diff --git a/report/userspercount/classes/report.php b/report/userspercount/classes/report.php index 3533d470aac..727202c7000 100644 --- a/report/userspercount/classes/report.php +++ b/report/userspercount/classes/report.php @@ -95,7 +95,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); // $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'userattempts'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/userspercount/lang/en/surveyproreport_userspercount.php b/report/userspercount/lang/en/surveyproreport_userspercount.php index 027854afd28..1aaa486236e 100644 --- a/report/userspercount/lang/en/surveyproreport_userspercount.php +++ b/report/userspercount/lang/en/surveyproreport_userspercount.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Users per count of responses'; -$string['userresponses'] = 'Count of submitted responses'; $string['privacy:metadata'] = 'The "Users per count" report plugin does not store any personal data.'; +$string['userresponses'] = 'Count of submitted responses'; diff --git a/report/userspercount/version.php b/report/userspercount/version.php index 84eef6c1840..8bc8284e9d4 100644 --- a/report/userspercount/version.php +++ b/report/userspercount/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_userspercount'; // Full name of the plugin (used for diagnostics). diff --git a/reports.php b/reports.php index 9b9f9343296..7537aa2a59f 100644 --- a/reports.php +++ b/reports.php @@ -24,8 +24,8 @@ require_once(dirname(__FILE__).'/../../config.php'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $report = optional_param('report', null, PARAM_TEXT); // Requested report. Section is the report name. if (!empty($id)) { diff --git a/styles.css b/styles.css index 1f7453c10c3..32be52102e3 100644 --- a/styles.css +++ b/styles.css @@ -23,12 +23,12 @@ /* End of: hacky coluorunifier html element */ /* Begin of: connect note to question */ -.path-mod-surveypro #userentry > div.fitem, -.path-mod-surveypro #usersearch > div.fitem, -.path-mod-surveypro #userentry > fieldset > div > div.fitem, -.path-mod-surveypro #usersearch > fieldset > div > div.fitem { - margin: 0; +/* stylelint-disable declaration-no-important */ +.path-mod-surveypro .narrowlines > div.fitem, +.path-mod-surveypro .narrowlines > fieldset > div > div.fitem { + margin-bottom: 0 !important; } +/* stylelint-enable declaration-no-important */ /* End of: connect note to question */ /* Begin of: no margin bottom to p inside question in SURVEYPRO_POSITIONTOP and SURVEYPRO_POSITIONFULLWIDTH */ @@ -222,7 +222,8 @@ text-align: center; } -.path-mod-surveypro table .dimmed { +.path-mod-surveypro table .dimmed, +.path-mod-surveypro table .dimmed:hover { color: #cdcdcd; } @@ -319,12 +320,13 @@ vertical-align: middle; } +#page-mod-surveypro-utemplates table#managetemplates td.actions img.icon, #page-mod-surveypro-utemplates table#managetemplates td.actions i.icon { width: 16px; height: 16px; - padding: 0; + margin: 0 0 0 0.45em; + padding-right: 0; vertical-align: middle; - margin-right: 0; } #page-mod-surveypro-utemplates table#managetemplates td.actions a.icon { @@ -336,175 +338,33 @@ } /* End of: #managetemplates table */ -/* classes = indent-n */ -.path-mod-surveypro .fitem .felement .indent-1 { - margin-left: 1.5em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-1 > div > select, -.path-mod-surveypro div.indent-1 > div > textarea, -.path-mod-surveypro div.indent-1 > div > input[type='text'], -.path-mod-surveypro div.indent-1 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-1 { - margin-left: 1.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-1.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-1.fileupload_filemanager ~ p { - margin-left: 1.5em; -} - -/* class = indent-2 */ -.path-mod-surveypro .fitem .felement .indent-2 { - margin-left: 3em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-2 > div > select, -.path-mod-surveypro div.indent-2 > div > textarea, -.path-mod-surveypro div.indent-2 > div > input[type='text'], -.path-mod-surveypro div.indent-2 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-2 { - margin-left: 3em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-2.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-2.fileupload_filemanager ~ p { - margin-left: 3em; -} - -/* class = indent-3 */ -.path-mod-surveypro .fitem .felement .indent-3 { - margin-left: 4.5em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-3 > div > select, -.path-mod-surveypro div.indent-3 > div > textarea, -.path-mod-surveypro div.indent-3 > div > input[type='text'], -.path-mod-surveypro div.indent-3 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-3 { - margin-left: 4.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-3.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-3.fileupload_filemanager ~ p { - margin-left: 4.5em; -} - -/* class = indent-4 */ -.path-mod-surveypro .fitem .felement .indent-4 { - margin-left: 6em; -} -.path-mod-surveypro div.indent-4 > div > select, -.path-mod-surveypro div.indent-4 > div > textarea, -.path-mod-surveypro div.indent-4 > div > input[type='text'], -.path-mod-surveypro div.indent-4 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-4 { - margin-left: 6em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-4.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-4.fileupload_filemanager ~ p { - margin-left: 6em; -} - -/* class = indent-5 */ -.path-mod-surveypro .fitem .felement .indent-5 { - margin-left: 7.5em; -} -.path-mod-surveypro div.indent-5 > div > select, -.path-mod-surveypro div.indent-5 > div > textarea, -.path-mod-surveypro div.indent-5 > div > input[type='text'], -.path-mod-surveypro div.indent-5 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-5 { - margin-left: 7.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-5.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-5.fileupload_filemanager ~ p { - margin-left: 7.5em; -} - -/* class = indent-6 */ -.path-mod-surveypro .fitem .felement .indent-6 { - margin-left: 9em; -} -.path-mod-surveypro div.indent-6 > div > select, -.path-mod-surveypro div.indent-6 > div > textarea, -.path-mod-surveypro div.indent-6 > div > input[type='text'], -.path-mod-surveypro div.indent-6 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-6 { - margin-left: 9em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-6.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-6.fileupload_filemanager ~ p { - margin-left: 9em; -} - -/* class = indent-7 */ -.path-mod-surveypro .fitem .felement .indent-7 { - margin-left: 10.5em; -} -.path-mod-surveypro div.indent-7 > div > select, -.path-mod-surveypro div.indent-7 > div > textarea, -.path-mod-surveypro div.indent-7 > div > input[type='text'], -.path-mod-surveypro div.indent-7 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-7 { - margin-left: 10.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-7.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-7.fileupload_filemanager ~ p { - margin-left: 10.5em; -} - -/* class = indent-8 */ -.path-mod-surveypro .fitem .felement .indent-8 { - margin-left: 12em; -} -.path-mod-surveypro div.indent-8 > div > select, -.path-mod-surveypro div.indent-8 > div > textarea, -.path-mod-surveypro div.indent-8 > div > input[type='text'], -.path-mod-surveypro div.indent-8 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-8 { - margin-left: 12em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-8.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-8.fileupload_filemanager ~ p { - margin-left: 12em; -} - -/* class = indent-9 */ -.path-mod-surveypro .fitem .felement .indent-9 { - margin-left: 13.5em; -} -.path-mod-surveypro div.indent-9 > div > select, -.path-mod-surveypro div.indent-9 > div > textarea, -.path-mod-surveypro div.indent-9 > div > input[type='text'], -.path-mod-surveypro div.indent-9 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-9 { - margin-left: 13.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-9.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-9.fileupload_filemanager ~ p { - margin-left: 13.5em; -} - -/* This is for checkboxes affected by MDL-62634 */ -.path-mod-surveypro label.indent-1 > input[type='checkbox'].indent-1, -.path-mod-surveypro label.indent-2 > input[type='checkbox'].indent-2, -.path-mod-surveypro label.indent-3 > input[type='checkbox'].indent-3, -.path-mod-surveypro label.indent-4 > input[type='checkbox'].indent-4, -.path-mod-surveypro label.indent-5 > input[type='checkbox'].indent-5, -.path-mod-surveypro label.indent-6 > input[type='checkbox'].indent-6, -.path-mod-surveypro label.indent-7 > input[type='checkbox'].indent-7, -.path-mod-surveypro label.indent-8 > input[type='checkbox'].indent-8, -.path-mod-surveypro label.indent-9 > input[type='checkbox'].indent-9 { - margin-left: 0; -} -/* End of: classes = indent-n */ +.path-mod-surveypro div.indent-1 > div.felement { + padding-left: 1.5em; +} +.path-mod-surveypro div.indent-2 > div.felement { + padding-left: 3em; +} +.path-mod-surveypro div.indent-3 > div.felement { + padding-left: 4.5em; +} +.path-mod-surveypro div.indent-4 > div.felement { + padding-left: 6em; +} +.path-mod-surveypro div.indent-5 > div.felement { + padding-left: 7.5em; +} +.path-mod-surveypro div.indent-6 > div.felement { + padding-left: 9em; +} +.path-mod-surveypro div.indent-7 > div.felement { + padding-left: 10.5em; +} +.path-mod-surveypro div.indent-8 > div.felement { + padding-left: 12em; +} +.path-mod-surveypro div.indent-9 > div.felement { + padding-left: 13.5em; +} /* Begin of: fix to owful alignment of fielset legends in surveypro -> cover */ .path-mod-surveypro_cover .coverinfolegend { diff --git a/template/attls/lang/en/surveyprotemplate_attls.php b/template/attls/lang/en/surveyprotemplate_attls.php index 032f47b5ddd..cc8abe09472 100644 --- a/template/attls/lang/en/surveyprotemplate_attls.php +++ b/template/attls/lang/en/surveyprotemplate_attls.php @@ -22,16 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'ATTLS (20 item version)'; -$string['privacy:metadata'] = 'The "ATTLS (20 item version)" template plugin does not store any personal data.'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Attitudes Towards Thinking and Learning'; +$string['item_parentvalue_01'] = ''; $string['label_content_01'] = '

The purpose of this questionnaire is to help us understand how well the online delivery of this unit enabled you to learn. Each couple of the 24 statements below asks you to compare your preferred (ideal) and actual experience in this unit. @@ -41,8 +33,11 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Attitudes Towards Thinking and Learning'; +$string['label_leftlabel_01'] = ''; +$string['pluginname'] = 'ATTLS (20 item version)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "ATTLS (20 item version)" template plugin does not store any personal data.'; $string['radiobutton_content_02'] = '

In evaluating what someone says, I focus on the quality of their argument, not on the person who\'s presenting it.

'; $string['radiobutton_content_03'] = '

I like playing devil\'s advocate - arguing the opposite of what someone is saying.

'; @@ -64,11 +59,16 @@ $string['radiobutton_content_19'] = '

I can obtain insight into opinions that differ from mine through empathy.

'; $string['radiobutton_content_20'] = '

When I encounter people whose opinions seem alien to me, I make a deliberate effort to \'extend\' myself into that person, to try to see how they could have those opinions.

'; $string['radiobutton_content_21'] = '

I spend time figuring out what\'s \'wrong\' with things. For example, I\'ll look for something in a literary interpretation that isn\'t argued well enough.

'; +$string['radiobutton_defaultvalue_01'] = ''; +$string['radiobutton_labelother_01'] = ''; +$string['radiobutton_options_01'] = "1::Strongly disagree\n2::Somewhat disagree\n3::Neither agree nor disagree\n4::Somewhat agree\n5::Strongly agree"; +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + -$string['item_parentvalue_01'] = ''; -$string['radiobutton_options_01'] = "1::Strongly disagree\n2::Somewhat disagree\n3::Neither agree nor disagree\n4::Somewhat agree\n5::Strongly agree"; -$string['radiobutton_labelother_01'] = ''; -$string['radiobutton_defaultvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/attls/lang/it/surveyprotemplate_attls.php b/template/attls/lang/it/surveyprotemplate_attls.php index 2537ab883f2..8162abd287e 100644 --- a/template/attls/lang/it/surveyprotemplate_attls.php +++ b/template/attls/lang/it/surveyprotemplate_attls.php @@ -22,15 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'ATTLS (versione con 20 elementi)'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Atteggiamenti nei Confronti del Pensare e dell\'Imparare'; +$string['item_parentvalue_01'] = ''; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a comprendere come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande ti chiede di confrontare l\'esperienza ideale e quella reale in questa unità. @@ -40,9 +33,11 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità online in futuro. Grazie.

'; +$string['label_leftlabel_01'] = ''; +$string['pluginname'] = 'ATTLS (versione con 20 elementi)'; -$string['fieldset_content_01'] = 'Atteggiamenti nei Confronti del Pensare e dell\'Imparare'; - +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_02'] = '

Valutando ciò che le persone dicono, pongo attenzione alla qualità dei suoi argomenti, non alla persona che li presenta.

'; $string['radiobutton_content_03'] = '

Mi piace fare l\'avvocato del diavolo, affermando il contrario di quello che qualcuno sta dicendo.

'; $string['radiobutton_content_04'] = '

Mi piace capire \'da dove vengono\' le altre persone, quali esperienze le hanno portate ad essere quello che sono.

'; @@ -63,11 +58,16 @@ $string['radiobutton_content_19'] = '

Posso arrivare alla comprensione di opinioni diverse dalle mie grazie all\'empatia (immedesimarsi nell\'altra persona).

'; $string['radiobutton_content_20'] = '

Quando incontro persone che sembrano avere opinioni diverse dalle mie, faccio uno sforzo per \'immedesimarmi\' in loro, per cercare di capire come hanno maturato quelle opinioni.

'; $string['radiobutton_content_21'] = '

Passo il tempo a cercare cosa c\'è di sbagliato nelle cose. Per esempio, cercherò qualcosa, in un\'interpretazione letteraria, che non è sufficientemente chiaro.

'; +$string['radiobutton_defaultvalue_01'] = ''; +$string['radiobutton_labelother_01'] = ''; +$string['radiobutton_options_01'] = "1::Fortemente in disaccordo\n2::Un po\' in disaccordo\n3::Né d\'accordo né in disaccordo\n4::Abbastanza d\'accordo\n5::Completamente d\'accordo"; +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + -$string['item_parentvalue_01'] = ''; -$string['radiobutton_options_01'] = "1::Fortemente in disaccordo\n2::Un po\' in disaccordo\n3::Né d\'accordo né in disaccordo\n4::Abbastanza d\'accordo\n5::Completamente d\'accordo"; -$string['radiobutton_labelother_01'] = ''; -$string['radiobutton_defaultvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/attls/template.xml b/template/attls/template.xml index 4884fe35d0c..84250a0b48f 100644 --- a/template/attls/template.xml +++ b/template/attls/template.xml @@ -1,43 +1,43 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 0 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + - 0 - 1 - 0 - - radiobutton_content_02 1 1 0 0 attls_radiobutton_01 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -46,19 +46,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 attls_radiobutton_02 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -67,19 +67,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 attls_radiobutton_03 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -88,19 +88,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 attls_radiobutton_04 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -109,19 +109,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 attls_radiobutton_05 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -130,19 +130,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 attls_radiobutton_06 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -151,19 +151,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 attls_radiobutton_07 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -172,19 +172,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 attls_radiobutton_08 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -193,19 +193,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 attls_radiobutton_09 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -214,19 +214,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 attls_radiobutton_10 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -235,19 +235,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 attls_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -256,19 +256,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 attls_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -277,19 +277,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 attls_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -298,19 +298,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 attls_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -319,19 +319,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 attls_radiobutton_15 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -340,19 +340,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 attls_radiobutton_16 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -361,19 +361,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 attls_radiobutton_17 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -382,19 +382,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 attls_radiobutton_18 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -403,19 +403,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 attls_radiobutton_19 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -424,19 +424,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 attls_radiobutton_20 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -445,4 +445,4 @@ 1 - \ No newline at end of file + diff --git a/template/attls/version.php b/template/attls/version.php index ead574345d2..69de17896ec 100644 --- a/template/attls/version.php +++ b/template/attls/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_attls'; // Full name of the plugin (used for diagnostics). diff --git a/template/collesactual/lang/en/surveyprotemplate_collesactual.php b/template/collesactual/lang/en/surveyprotemplate_collesactual.php index e208d689df8..2acc733667a 100644 --- a/template/collesactual/lang/en/surveyprotemplate_collesactual.php +++ b/template/collesactual/lang/en/surveyprotemplate_collesactual.php @@ -22,20 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Actual)'; -$string['privacy:metadata'] = 'The "COLLES (Actual)" template plugin does not store any personal data.'; - -$string['summary'] = 'Summary'; -$string['scales'] = 'Scales'; $string['areaidxs'] = 'Questions'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Relevance'; +$string['fieldset_content_02'] = 'Reflective thinking'; $string['label_content_01'] = '

The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. Each one of the 24 statements below asks about your experience in this unit. @@ -45,17 +34,28 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Relevance'; - $string['label_content_02'] = '

In this online unit...

'; +$string['pluginname'] = 'COLLES (Actual)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "COLLES (Actual)" template plugin does not store any personal data.'; $string['radiobutton_content_03'] = '

my learning focuses on issues that interest me.

'; $string['radiobutton_content_04'] = '

what I learn is important for my professional practice.

'; $string['radiobutton_content_05'] = '

I learn how to improve my professional practice.

'; $string['radiobutton_content_06'] = '

what I learn connects well with my professional practice.

'; +$string['scales'] = 'Scales'; +$string['summary'] = 'Summary'; + +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + + -$string['fieldset_content_02'] = 'Reflective thinking'; // $string['label_content_02'] = '

In this online unit...

'; diff --git a/template/collesactual/lang/it/surveyprotemplate_collesactual.php b/template/collesactual/lang/it/surveyprotemplate_collesactual.php index e2b15115e59..6bb3db49086 100644 --- a/template/collesactual/lang/it/surveyprotemplate_collesactual.php +++ b/template/collesactual/lang/it/surveyprotemplate_collesactual.php @@ -22,18 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Actual)'; -$string['summary'] = 'Riepilogo'; -$string['scales'] = 'Valutazioni'; $string['areaidxs'] = 'Aree'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Pertinenza'; +$string['fieldset_content_02'] = 'Senso critico'; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande riguarda la tua esperienza in questa unità. @@ -43,17 +34,26 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità. Grazie.

'; - -$string['fieldset_content_01'] = 'Pertinenza'; - $string['label_content_02'] = '

In questa unità online...

'; - +$string['pluginname'] = 'COLLES (Actual)'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_03'] = '

il mio apprendimento si concentra sulle cose che mi interessano.

'; $string['radiobutton_content_04'] = '

quello che imparo è importante per la mia pratica professionale.

'; $string['radiobutton_content_05'] = '

imparo come migliorare la mia pratica professionale.

'; $string['radiobutton_content_06'] = '

quello che imparo si collega bene con la mia pratica professionale.

'; +$string['scales'] = 'Valutazioni'; +$string['summary'] = 'Riepilogo'; + +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + + -$string['fieldset_content_02'] = 'Senso critico'; // $string['label_content_02'] = '

In questa unità online...

'; diff --git a/template/collesactual/template.xml b/template/collesactual/template.xml index 63eb32326ca..f9ccd1515d9 100644 --- a/template/collesactual/template.xml +++ b/template/collesactual/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 ca_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 ca_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 ca_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 ca_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,44 +123,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 ca_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -169,19 +169,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 ca_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -190,19 +190,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 ca_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -211,19 +211,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 ca_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -232,44 +232,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 ca_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -278,19 +278,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 ca_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -299,19 +299,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 ca_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -320,19 +320,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 ca_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -341,44 +341,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 ca_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -387,19 +387,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 ca_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -408,19 +408,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 ca_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -429,19 +429,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 ca_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -450,44 +450,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 ca_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -496,19 +496,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 ca_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -517,19 +517,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 ca_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -538,19 +538,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 ca_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -559,44 +559,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 ca_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -605,19 +605,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 ca_radiobutton_62 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -626,19 +626,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 ca_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -647,19 +647,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 ca_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -668,19 +668,19 @@ 1 - + - 0 - 1 - 0 - - select_content_27 1 1 0 0 ca_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -688,13 +688,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_28 1 0 @@ -702,12 +697,17 @@ 0 0 ca_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collesactual/tests/behat/graphs.feature b/template/collesactual/tests/behat/graphs.feature index f873aedcaf9..dd07078d399 100644 --- a/template/collesactual/tests/behat/graphs.feature +++ b/template/collesactual/tests/behat/graphs.feature @@ -41,32 +41,32 @@ Feature: Apply a COLLES (actual) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_3 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_0 | 1 | - | id_surveypro_field_radiobutton_19_1 | 1 | - | id_surveypro_field_radiobutton_22_2 | 1 | - | id_surveypro_field_radiobutton_23_3 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_0 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_4 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_3 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_0 | 1 | + | id_field_radiobutton_19_1 | 1 | + | id_field_radiobutton_22_2 | 1 | + | id_field_radiobutton_23_3 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_0 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_4 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collesactual/tests/behat/reportswithanswers.feature b/template/collesactual/tests/behat/reportswithanswers.feature index 971bd2f8b0c..73e675901cb 100644 --- a/template/collesactual/tests/behat/reportswithanswers.feature +++ b/template/collesactual/tests/behat/reportswithanswers.feature @@ -56,32 +56,32 @@ Feature: Test colles report for courses divided into groups having answers # student11 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_1 | 1 | - | id_surveypro_field_radiobutton_5_0 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_0 | 1 | - | id_surveypro_field_radiobutton_13_1 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_4 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_4 | 1 | - | id_surveypro_field_radiobutton_28_3 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_1 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_2 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_1 | 1 | + | id_field_radiobutton_5_0 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_0 | 1 | + | id_field_radiobutton_13_1 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_4 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_4 | 1 | + | id_field_radiobutton_28_3 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_1 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_2 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out @@ -93,32 +93,32 @@ Feature: Test colles report for courses divided into groups having answers # student12 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_2 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_3 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_3 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_0 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_1 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_4 | 1 | - | id_surveypro_field_radiobutton_30_2 | 1 | - | id_surveypro_field_radiobutton_31_1 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_3 | 1 | - | id_surveypro_field_radiobutton_37_2 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_2 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_3 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_3 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_0 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_1 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_4 | 1 | + | id_field_radiobutton_30_2 | 1 | + | id_field_radiobutton_31_1 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_3 | 1 | + | id_field_radiobutton_37_2 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out @@ -130,32 +130,32 @@ Feature: Test colles report for courses divided into groups having answers # student21 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_4 | 1 | - | id_surveypro_field_radiobutton_5_2 | 1 | - | id_surveypro_field_radiobutton_6_1 | 1 | - | id_surveypro_field_radiobutton_7_0 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_4 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_0 | 1 | - | id_surveypro_field_radiobutton_16_2 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_1 | 1 | - | id_surveypro_field_radiobutton_19_4 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_0 | 1 | - | id_surveypro_field_radiobutton_24_3 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_28_4 | 1 | - | id_surveypro_field_radiobutton_29_1 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_4 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_4 | 1 | + | id_field_radiobutton_5_2 | 1 | + | id_field_radiobutton_6_1 | 1 | + | id_field_radiobutton_7_0 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_4 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_0 | 1 | + | id_field_radiobutton_16_2 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_1 | 1 | + | id_field_radiobutton_19_4 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_0 | 1 | + | id_field_radiobutton_24_3 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_28_4 | 1 | + | id_field_radiobutton_29_1 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_4 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out diff --git a/template/collesactual/tests/behat/reportswithoutanswers.feature b/template/collesactual/tests/behat/reportswithoutanswers.feature index 9dcaa44c18d..403b901ae61 100644 --- a/template/collesactual/tests/behat/reportswithoutanswers.feature +++ b/template/collesactual/tests/behat/reportswithoutanswers.feature @@ -37,6 +37,7 @@ Feature: Test colles report for courses divided into groups not having answers | surveypro | Verify reports | Verify reports | Course grouped | When I am on the "Verify reports" "Activity editing" page logged in as teacher1 + And I expand all fieldsets And I set the following fields to these values: | Group mode | Visible groups | And I press "Save and display" @@ -53,32 +54,32 @@ Feature: Test colles report for courses divided into groups not having answers # student11 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_1 | 1 | - | id_surveypro_field_radiobutton_5_0 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_0 | 1 | - | id_surveypro_field_radiobutton_13_1 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_4 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_4 | 1 | - | id_surveypro_field_radiobutton_28_3 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_1 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_2 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_1 | 1 | + | id_field_radiobutton_5_0 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_0 | 1 | + | id_field_radiobutton_13_1 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_4 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_4 | 1 | + | id_field_radiobutton_28_3 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_1 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_2 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out diff --git a/template/collesactual/version.php b/template/collesactual/version.php index 5eb5c47c6ba..5474b76bd11 100644 --- a/template/collesactual/version.php +++ b/template/collesactual/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collesactual'; // Full name of the plugin (used for diagnostics). diff --git a/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php b/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php index c947e90619c..6f4f71c1ad0 100644 --- a/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php +++ b/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php @@ -22,19 +22,19 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['areaidxs'] = 'Questions'; $string['pluginname'] = 'COLLES (Preferred and Actual)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; $string['privacy:metadata'] = 'The "COLLES (Preferred and Actual)" template plugin does not store any personal data.'; -$string['summary'] = 'Summary'; $string['scales'] = 'Scales'; -$string['areaidxs'] = 'Questions'; +$string['summary'] = 'Summary'; +$string['useradio'] = 'Radio buttons'; $string['useritem'] = 'Style of the choice elements'; $string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; $string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; // Label. $string['label_content_01'] = '

The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. diff --git a/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php b/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php index aaf5fb21d5b..83e8640a48b 100644 --- a/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php +++ b/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php @@ -22,17 +22,17 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['areaidxs'] = 'Aree'; $string['pluginname'] = 'COLLES (Ideale e Reale)'; -$string['summary'] = 'Riepilogo'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['scales'] = 'Valutazioni'; -$string['areaidxs'] = 'Aree'; +$string['summary'] = 'Riepilogo'; +$string['useradio'] = 'Bottoni radio'; $string['useritem'] = 'Tipo di selettore'; $string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; $string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; // Label. $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. diff --git a/template/collesactualpreferred/template.xml b/template/collesactualpreferred/template.xml index 7063150e63c..245d7893417 100644 --- a/template/collesactualpreferred/template.xml +++ b/template/collesactualpreferred/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 cap_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 cap_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 cap_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 cap_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,19 +123,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 cap_radiobutton_15 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -144,19 +144,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 cap_radiobutton_16 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -165,19 +165,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 cap_radiobutton_17 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -186,19 +186,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 cap_radiobutton_18 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -207,44 +207,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 cap_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -253,19 +253,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 cap_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -274,19 +274,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 cap_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -295,19 +295,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 cap_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -316,19 +316,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 cap_radiobutton_25 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -337,19 +337,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 cap_radiobutton_26 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -358,19 +358,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 cap_radiobutton_27 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -379,19 +379,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 cap_radiobutton_28 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -400,44 +400,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 cap_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -446,19 +446,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 cap_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -467,19 +467,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 cap_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -488,19 +488,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 cap_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -509,19 +509,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 cap_radiobutton_35 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -530,19 +530,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 cap_radiobutton_36 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -551,20 +551,20 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 cap_radiobutton_37 - radiobutton_options_01 + 0 + 1 + 0 + + + radiobutton_options_01 radiobutton_labelother_01 2 radiobutton_defaultvalue_01 @@ -572,19 +572,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 cap_radiobutton_38 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -593,44 +593,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_27 1 1 0 0 cap_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -639,19 +639,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_28 1 1 0 0 cap_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -660,19 +660,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_29 1 1 0 0 cap_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -681,19 +681,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_30 1 1 0 0 cap_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -702,19 +702,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_31 1 1 0 0 cap_radiobutton_45 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -723,19 +723,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_32 1 1 0 0 cap_radiobutton_46 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -744,19 +744,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_33 1 1 0 0 cap_radiobutton_47 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -765,19 +765,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_34 1 1 0 0 cap_radiobutton_48 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -786,44 +786,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_35 1 1 0 0 cap_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -832,19 +832,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_36 1 1 0 0 cap_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -853,19 +853,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_37 1 1 0 0 cap_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -874,19 +874,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_38 1 1 0 0 cap_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -895,19 +895,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_39 1 1 0 0 cap_radiobutton_55 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -916,19 +916,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_40 1 1 0 0 cap_radiobutton_56 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -937,19 +937,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_41 1 1 0 0 cap_radiobutton_57 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -958,19 +958,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_42 1 1 0 0 cap_radiobutton_58 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -979,44 +979,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_43 1 1 0 0 cap_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1025,19 +1025,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_44 1 1 0 0 cap_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1046,19 +1046,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_45 1 1 0 0 cap_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1067,19 +1067,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_46 1 1 0 0 cap_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1088,19 +1088,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_47 1 1 0 0 cap_radiobutton_65 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1109,19 +1109,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_48 1 1 0 0 cap_radiobutton_66 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1130,19 +1130,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_49 1 1 0 0 cap_radiobutton_67 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1151,19 +1151,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_50 1 1 0 0 cap_radiobutton_68 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1172,19 +1172,19 @@ 1 - + - 0 - 1 - 0 - - select_content_51 1 1 0 0 cap_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -1192,13 +1192,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_52 1 0 @@ -1206,12 +1201,17 @@ 0 0 cap_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collesactualpreferred/tests/behat/graphs.feature b/template/collesactualpreferred/tests/behat/graphs.feature index 80c7ee2191a..0ddefded04f 100644 --- a/template/collesactualpreferred/tests/behat/graphs.feature +++ b/template/collesactualpreferred/tests/behat/graphs.feature @@ -41,62 +41,62 @@ Feature: Apply a COLLES (actual and preferred) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_8_4 | 1 | - | id_surveypro_field_radiobutton_9_0 | 1 | - | id_surveypro_field_radiobutton_10_1 | 1 | - | id_surveypro_field_radiobutton_11_2 | 1 | - - | id_surveypro_field_radiobutton_14_3 | 1 | - | id_surveypro_field_radiobutton_15_4 | 1 | - | id_surveypro_field_radiobutton_16_0 | 1 | - | id_surveypro_field_radiobutton_17_1 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_20_4 | 1 | - | id_surveypro_field_radiobutton_21_0 | 1 | - - | id_surveypro_field_radiobutton_24_1 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_26_3 | 1 | - | id_surveypro_field_radiobutton_27_4 | 1 | - | id_surveypro_field_radiobutton_28_0 | 1 | - | id_surveypro_field_radiobutton_29_1 | 1 | - | id_surveypro_field_radiobutton_30_2 | 1 | - | id_surveypro_field_radiobutton_31_3 | 1 | - - | id_surveypro_field_radiobutton_34_4 | 1 | - | id_surveypro_field_radiobutton_35_0 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_2 | 1 | - | id_surveypro_field_radiobutton_38_3 | 1 | - | id_surveypro_field_radiobutton_39_4 | 1 | - | id_surveypro_field_radiobutton_40_0 | 1 | - | id_surveypro_field_radiobutton_41_1 | 1 | - - | id_surveypro_field_radiobutton_44_2 | 1 | - | id_surveypro_field_radiobutton_45_3 | 1 | - | id_surveypro_field_radiobutton_46_4 | 1 | - | id_surveypro_field_radiobutton_47_0 | 1 | - | id_surveypro_field_radiobutton_48_1 | 1 | - | id_surveypro_field_radiobutton_49_2 | 1 | - | id_surveypro_field_radiobutton_50_3 | 1 | - | id_surveypro_field_radiobutton_51_4 | 1 | - - | id_surveypro_field_radiobutton_54_0 | 1 | - | id_surveypro_field_radiobutton_55_1 | 1 | - | id_surveypro_field_radiobutton_56_2 | 1 | - | id_surveypro_field_radiobutton_57_3 | 1 | - | id_surveypro_field_radiobutton_58_4 | 1 | - | id_surveypro_field_radiobutton_59_0 | 1 | - | id_surveypro_field_radiobutton_60_1 | 1 | - | id_surveypro_field_radiobutton_61_2 | 1 | - - | id_surveypro_field_select_62 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_8_4 | 1 | + | id_field_radiobutton_9_0 | 1 | + | id_field_radiobutton_10_1 | 1 | + | id_field_radiobutton_11_2 | 1 | + + | id_field_radiobutton_14_3 | 1 | + | id_field_radiobutton_15_4 | 1 | + | id_field_radiobutton_16_0 | 1 | + | id_field_radiobutton_17_1 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_20_4 | 1 | + | id_field_radiobutton_21_0 | 1 | + + | id_field_radiobutton_24_1 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_26_3 | 1 | + | id_field_radiobutton_27_4 | 1 | + | id_field_radiobutton_28_0 | 1 | + | id_field_radiobutton_29_1 | 1 | + | id_field_radiobutton_30_2 | 1 | + | id_field_radiobutton_31_3 | 1 | + + | id_field_radiobutton_34_4 | 1 | + | id_field_radiobutton_35_0 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_2 | 1 | + | id_field_radiobutton_38_3 | 1 | + | id_field_radiobutton_39_4 | 1 | + | id_field_radiobutton_40_0 | 1 | + | id_field_radiobutton_41_1 | 1 | + + | id_field_radiobutton_44_2 | 1 | + | id_field_radiobutton_45_3 | 1 | + | id_field_radiobutton_46_4 | 1 | + | id_field_radiobutton_47_0 | 1 | + | id_field_radiobutton_48_1 | 1 | + | id_field_radiobutton_49_2 | 1 | + | id_field_radiobutton_50_3 | 1 | + | id_field_radiobutton_51_4 | 1 | + + | id_field_radiobutton_54_0 | 1 | + | id_field_radiobutton_55_1 | 1 | + | id_field_radiobutton_56_2 | 1 | + | id_field_radiobutton_57_3 | 1 | + | id_field_radiobutton_58_4 | 1 | + | id_field_radiobutton_59_0 | 1 | + | id_field_radiobutton_60_1 | 1 | + | id_field_radiobutton_61_2 | 1 | + + | id_field_select_62 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collesactualpreferred/version.php b/template/collesactualpreferred/version.php index df55ca3a61f..04ea0d9ab2a 100644 --- a/template/collesactualpreferred/version.php +++ b/template/collesactualpreferred/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collesactualpreferred'; // Full name of the plugin (used for diagnostics). diff --git a/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php b/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php index 70b16f83000..caf334b2b0d 100644 --- a/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php +++ b/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php @@ -22,20 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Preferred)'; -$string['privacy:metadata'] = 'The "COLLES (Preferred)" template plugin does not store any personal data.'; - -$string['summary'] = 'Summary'; -$string['scales'] = 'Scales'; $string['areaidxs'] = 'Questions'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Relevance'; +$string['fieldset_content_02'] = 'Reflective thinking'; $string['label_content_01'] = '

The purpose of this survey is to help us understand what you value in an online learning experience. Each one of the 24 statements below asks about your preferred (ideal) experience in this unit. @@ -45,17 +34,28 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Relevance'; - $string['label_content_02'] = '

In this online unit...

'; +$string['pluginname'] = 'COLLES (Preferred)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "COLLES (Preferred)" template plugin does not store any personal data.'; $string['radiobutton_content_03'] = '

my learning focuses on issues that interest me.

'; $string['radiobutton_content_04'] = '

what I learn is important for my professional practice.

'; $string['radiobutton_content_05'] = '

I learn how to improve my professional practice.

'; $string['radiobutton_content_06'] = '

what I learn connects well with my professional practice.

'; +$string['scales'] = 'Scales'; +$string['summary'] = 'Summary'; + +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + + -$string['fieldset_content_02'] = 'Reflective thinking'; // $string['label_content_02'] = '

In this online unit...

'; diff --git a/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php b/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php index ab3a71a8568..aabccfa4fa4 100644 --- a/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php +++ b/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php @@ -22,18 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Ideale)'; -$string['summary'] = 'Riepilogo'; -$string['scales'] = 'Valutazioni'; $string['areaidxs'] = 'Aree'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Pertinenza'; +$string['fieldset_content_02'] = 'Senso critico'; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande riguarda l\'esperienza ideale in questa unità. @@ -43,17 +34,26 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità online in futuro. Grazie.

'; - -$string['fieldset_content_01'] = 'Pertinenza'; - $string['label_content_02'] = '

In questa unità online...

'; - +$string['pluginname'] = 'COLLES (Ideale)'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_03'] = '

il mio apprendimento si concentra sulle cose che mi interessano.

'; $string['radiobutton_content_04'] = '

quello che imparo è importante per la mia pratica professionale.

'; $string['radiobutton_content_05'] = '

imparo come migliorare la mia pratica professionale.

'; $string['radiobutton_content_06'] = '

quello che imparo si collega bene con la mia pratica professionale.

'; +$string['scales'] = 'Valutazioni'; +$string['summary'] = 'Riepilogo'; + +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + + -$string['fieldset_content_02'] = 'Senso critico'; // $string['label_content_02'] = '

In questa unità online...

'; diff --git a/template/collespreferred/template.xml b/template/collespreferred/template.xml index b7da9be12d9..89ffbd7dc51 100644 --- a/template/collespreferred/template.xml +++ b/template/collespreferred/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 cp_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 cp_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 cp_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 cp_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,44 +123,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 cp_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -169,19 +169,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 cp_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -190,19 +190,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 cp_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -211,19 +211,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 cp_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -232,44 +232,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 cp_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -278,19 +278,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 cp_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -299,19 +299,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 cp_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -320,19 +320,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 cp_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -341,44 +341,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 cp_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -387,19 +387,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 cp_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -408,19 +408,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 cp_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -429,19 +429,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 cp_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -450,44 +450,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 cp_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -496,19 +496,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 cp_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -517,19 +517,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 cp_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -538,19 +538,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 cp_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -559,44 +559,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 cp_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -605,19 +605,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 cp_radiobutton_62 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -626,19 +626,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 cp_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -647,19 +647,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 cp_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -668,19 +668,19 @@ 1 - + - 0 - 1 - 0 - - select_content_27 1 1 0 0 cp_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -688,13 +688,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_28 1 0 @@ -702,12 +697,17 @@ 0 0 cp_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collespreferred/tests/behat/graphs.feature b/template/collespreferred/tests/behat/graphs.feature index 447dc5f398f..fdf4cb7c74b 100644 --- a/template/collespreferred/tests/behat/graphs.feature +++ b/template/collespreferred/tests/behat/graphs.feature @@ -41,32 +41,32 @@ Feature: Apply a COLLES (preferred) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_3 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_0 | 1 | - | id_surveypro_field_radiobutton_19_1 | 1 | - | id_surveypro_field_radiobutton_22_2 | 1 | - | id_surveypro_field_radiobutton_23_3 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_0 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_4 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_3 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_0 | 1 | + | id_field_radiobutton_19_1 | 1 | + | id_field_radiobutton_22_2 | 1 | + | id_field_radiobutton_23_3 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_0 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_4 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collespreferred/version.php b/template/collespreferred/version.php index d4423b3ff29..51ebe298a75 100644 --- a/template/collespreferred/version.php +++ b/template/collespreferred/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collespreferred'; // Full name of the plugin (used for diagnostics). diff --git a/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php b/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php index 4bffc773bb5..73b5ff17d4d 100644 --- a/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php +++ b/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php @@ -22,10 +22,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['item_parentvalue_01'] = ''; +$string['label_content_01'] = '

While thinking about recent events in this class, answer the questions below.

'; +$string['label_leftlabel_01'] = ''; $string['pluginname'] = 'Critical Incidents'; $string['privacy:metadata'] = 'The "Critical Incidents" template plugin does not store any personal data.'; -$string['label_content_01'] = '

While thinking about recent events in this class, answer the questions below.

'; $string['textarea_content_02'] = '

At what moment in class were you most engaged as a learner?

'; $string['textarea_content_03'] = '

At what moment in class were you most distanced as a learner?

'; @@ -33,6 +35,4 @@ $string['textarea_content_05'] = '

What action from anyone in the forums did you find most puzzling or confusing?

'; $string['textarea_content_06'] = '

What event surprised you most?

'; -$string['item_parentvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php b/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php index 4575e444950..81079b0e05f 100644 --- a/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php +++ b/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php @@ -22,9 +22,11 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['item_parentvalue_01'] = ''; +$string['label_content_01'] = '

Rispondi alle seguenti domande pensando alle attività svolte recentemente in classe.

'; +$string['label_leftlabel_01'] = ''; $string['pluginname'] = 'Incidenti critici'; -$string['label_content_01'] = '

Rispondi alle seguenti domande pensando alle attività svolte recentemente in classe.

'; $string['textarea_content_02'] = '

In classe in quale momento sei più partecipe come studente?

'; $string['textarea_content_03'] = '

In classe in quale momento sei meno partecipe come studente?

'; @@ -32,6 +34,4 @@ $string['textarea_content_05'] = '

Quale azione nei forum da parte degli altri partecipanti trovi disorientante e confusionaria?

'; $string['textarea_content_06'] = '

Quale evento ti ha sorpreso di più?

'; -$string['item_parentvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/criticalincidents/template.xml b/template/criticalincidents/template.xml index 14508a4c4ad..301cfa72675 100644 --- a/template/criticalincidents/template.xml +++ b/template/criticalincidents/template.xml @@ -1,26 +1,21 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - textarea_content_02 1 1 @@ -28,21 +23,21 @@ 0 0 ci_textarea_01 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_03 1 1 @@ -50,21 +45,21 @@ 0 0 ci_textarea_02 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_04 1 1 @@ -72,21 +67,21 @@ 0 0 ci_textarea_03 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_05 1 1 @@ -94,21 +89,21 @@ 0 0 ci_textarea_04 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_06 1 1 @@ -116,10 +111,15 @@ 0 0 ci_textarea_05 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 diff --git a/template/criticalincidents/version.php b/template/criticalincidents/version.php index 6312d59f4ba..ad2cc024b19 100644 --- a/template/criticalincidents/version.php +++ b/template/criticalincidents/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_criticalincidents'; // Full name of the plugin (used for diagnostics). diff --git a/template/flags/classes/privacy/provider.php b/template/flags/classes/privacy/provider.php new file mode 100644 index 00000000000..26442aac8b1 --- /dev/null +++ b/template/flags/classes/privacy/provider.php @@ -0,0 +1,44 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_flags\privacy; + +/** + * Privacy Subsystem for template_flags implementing null_provider. + * + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/template/flags/classes/template.php b/template/flags/classes/template.php new file mode 100644 index 00000000000..5127041720c --- /dev/null +++ b/template/flags/classes/template.php @@ -0,0 +1,47 @@ +. + +/** + * Surveypro class to manage flags template + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_flags; + +/** + * The class to manage flags template + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template { + + /** + * Apply template settings. + * + * @param string $tablename + * @param object $record + * @param object $config + * @return [$tablename, $record] + */ + public function apply_template_settings($tablename, $record, $config) { + return [$tablename, $record]; + } +} diff --git a/template/flags/lang/en/surveyprotemplate_flags.php b/template/flags/lang/en/surveyprotemplate_flags.php new file mode 100644 index 00000000000..3590e227f45 --- /dev/null +++ b/template/flags/lang/en/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

Do you recognize this flag?

+

ENFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEhUSExIWFRAXFhcVFRUVFRcVFRYVFRUWFhUVFhUYHSggGB0lHRUVITEhJSktLi4uFx8zODMsNygtLisBCgoKDg0OGhAQGy0lIB0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAJ8BPgMBEQACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAAGAgMEBQcBAAj/xABHEAABAgMDBwcICAYCAgMAAAABAgMABBEFITEGEhNBUWFxByJCUoGRklNigpOhsbLRIzJDcnPB0tMUJGODoqMVVDPxFhcl/8QAGwEAAgMBAQEAAAAAAAAAAAAAAAQBAgMFBgf/xAA0EQACAgECAwQIBwEBAQEAAAAAAQIDEQQhEjFRBRNBkSIyYXGBobHRFDNCUsHh8CMVciT/2gAMAwEAAhEDEQA/AKew8qpiXoK6VrqOX0HmrxT7RuhZTaPY6jsui/fk+q/lGjZP5WSkzROdo3T9m5QVPmKwV790bRsTPP6rsy+jfGV1X8hJnJEXOcJ06RrgAjz7TD6C26hDjZxSsBQ434HfFoycXlMhrJm+UnJa2qq5J3NPkXSSnghy8jXcqvEQ9VrfCZjKheBmtqWY9LL0b7Sm16goXHelQuUN4Jh6M4zWYsXlFrmRIuVPQAdbbKjQYmIAksSdRUit1QnOCTS6pJOFAQe2KtlsHJqZqSE1pVV5NbjQUF1wuwgUQyRKROCDlIMAepBgDtIMAaXyHoq9M/ht/EqEtd6sfiMUeJqVspAl3vwnPgVHMfIe0/5sPevqYJngCFD3sppMZXMiJwYSvSGVTJi2DB3sl2I6f4hn8VHxCJXMW1M26Z+5mrIS4dsMHkzHMskET0wDjnj4Ex1KE+7QrZ6xT5sbYZnk7mxOAyj1InAZPZsGAyepBgjI63LKVSguJIrUUuFTXZdA8ATA0ltJJzqkABSVAEmtVACl1KUMV4cstnBCfUVG/CpoBgKmtIlVojiY1o4O7DiLawslZucvZaJRrcVzWx6XSwwTUxhZKNfNmkYthzZ/J22wM94h1QvOdzWk+icfSPYISnqG+WwxCrfC3YzaWUrbXNZGeRdUXNjht7Lt8KuzodWnsyyW89l8wWn7UeeP0iyRqSLkjgn8zfGbbZ1adPCpeivuRW6kgAEk4AXk8BEG/HhZYTWRkq65RTp0aNmKz2YJ7e6LKDYjf2rCG0N38g4smy2GBRtAB1qPOUeKj7sI0UUjjXaq255m/wCEANr2A/L1Obnt9dFTQecnFPu3xi62j0tHadVu2cPoylLsVwNu1lzZOV80xROfpGx0FmtB5qsR7Rui6k0c3U6Kq7fGH1QWWblg29QZ2Yvqrur904H37o1UkziX6K2rfGV1RZ/8iqLCgpFrGABUzNtvILbyEuNnFKwFDjfgd8TGTi8ohrIFW1kGhVVyjmafJOElPouYjgqvEQ7XrHyn5mUqU+QET0k6wrMdbUhWxQx3pIuUN4MPRtjJZTF5Qa5iJZ4JNTsNCACQdRAOMWbyVxgemJ5Sjco0upgCSABUkbaViVFAyNFiD0AHIAPQAerABovIxMhDsyf6bfxKjn657R+IzQG2UVtfQuiuLax/iY5r5DtLxZF+1GIl4mMMHqZ2uTOpQTARGLZIbYiuRiFJcZNS1ZuXG15sf5iJT3ROpqxp5/8Ay/oboiTQIZPEnz7yggC0pqmGkHwJjtab8qIlb6wPVjbKMztYMoD1YMoD1YNgPQEkuXmghNBUKoRSgIJOCiTsGqn5xVxyyckdx1SsTXXuwphhhFkkRkt8nslZudP0DRKK0Lq+a0PT6XBIJ3RnZdCv1mXjW5GpZP8AJlKSw0k0oPrF5z+awn0CedxUSNwjnW6yUuWyGa6N0luyVbWX0uyMyWSHVAUBHNaTuB6XAXb458reh39L2JbPe30V8/6M/ti235o1ecJGpA5rY4JHvNTvjFyb5notPoqaFiEfj4+ZXJYziEhJKjcABUk7ABeYg2nGKWXyCuxuTZ92i3zoUdW4uHswR237o1jBvmcLV9qUQ9Gr0n18P7CyTyPZlxRtFDrUb1Hio+7CNVFI4F2psufpv4eApdmERYwOCVIgAA7C5Q0GiZtGb/VbBI4qbxHFNeAh6zRvnBmMbl4hNMZKyk6jSsqTfg4yQUk+cnAnbgYQnU08NYOpp+0Lats8S6MDrayOmZeqijSNDpoBIA85OKfdvjGUWjuafW0X7Zw+j+5QFqK5HXUWVnW28zQVz2+qvV91WI9o3RZTaOff2dXZ4YfsCaz7YZfuCsxzqrur904K9+6NFNM4t+guq3xldUTltkRcSEB1QgA8+4h1OY6hK0HEKFRxGw74mMnHdBz5gra2RaTVUsun9Nw1HorxHbXjDdeqfKRjKpPkCM5KuMqzHUFCtihjvBwUN4hyFqktmYuDQyFxoplMCguLcQYPZ0HEGDhXEcYYElcVcyeEKuTyaKFvU1pR71QjqpZSGKlgKJ5SltuHzFfCYRfIaq9ePvQAsM1jBs9ZCrJOaYijY7XSPgARUYSSJ+T7tJuXP9Zv4xFo80K62a/DzXsZrkzae+GzwhgmWz+dPzB2rHwJjqUy/wCa/wB1FbF6RR58acZXB7PiOMOE9pInjDhO58HGHCdDkTxkcJZ2NYr80aNI5utaua2OKtfAVMVlqIw5slVNml5OZDybA0kyQ+sXnP5rKfQ6XpGm4QnbrJy9XZDEKN8JZZc2pyisNDMl0hxQFARzWk02dbgLt8ISt6Hc0vZE7N7Xwr5/0AlsZQTE0avOEpxCBzWxwSPeanfGDbfM9JptLRp1itfHx8yA2kqISkEqNwAFSTsAGMVGnJJZb2DGwuT592inzoW+rcp0jhgjtv3RrGpvmcbVdtVV+jV6T+X9mhWNYEvKijLYCsCs85w8VG+m4UG6NoxS5HnNTrLtQ82S+Hh5FkYsKiFwAUmUFvysmnOmHUpJ+qn6zivuoF544bTGkKpT5IhyS5mXW5ynvLVSWaS22NbgC1q4gHNTwv4w9DRxXrmDv6ACIeQuTbLtR6WXpGHVNr1lJuO5STcobiDFZQjNYkiYya5GmZN8qyDRE63mnyzQJTxW3iNV6a8BCNuhfOD+AxG/qE07kvIWgjTMKSCrB1gggnz04E7cDvjm2U4eGsM6+l7Uup2zxR6P7gFb2RczLVUU6RofaNgmg85OKfdvjBwcT0Om7Q0+o2Tw+j/h+INKaiuRyVZY2fbrzNBXSN9Vd9B5qsR7RujRTaOZqezard8YfVfYJZO1WHrgrMXhmqoK/dOB9+6NVJM4N+gtp3xldUPuy5EWExg1EADcwlLicxxAWnYoVHHcd8SpOLyge4LWpkiL1S6qf01m70V49/fDUNT+4ylWvAFpqXcaVmuJKVbDr3g4EbxDKsT5GTi0M50TxEYOFURxk4OExVsnAV8nrRU4791PxGFtRyRrWaQbO+hdNMG1/AYVfIZoX/SPvRnDDVBCjZ7yFaQ4TSINW8DLjsWSF52CrKfpMMn+qj4hF4rc52sszTNexmiF1SzdDB5IynKtkicfBxzxXwpjp0RzBC1j3KvRxv3ZnxHtHB3ZHEKQyL6mKuslSLKyMmJmaP0DZUgGhcPNbHp6zuFTujKyUYc2aRTYXyWQCGBnvEOEXmvNbHYce27dCc72+WxvGvfCEz2UyWua0M8i4EXIHDb2Xb4VczpVdn2Peey+YNz9svPH6RZI1JFyRwT+ZvjN5Z1KK4U+ovj4jDbxJAF5OAF5PZEYGlfjmE1jZOrcoXVaNGzFZ7ME9vdFlW2KXdrxhtDd/I0WwGJeWH0SAFYFZvWeKjf2C6NFFLkcXUay69+m/h4BCzPgxYWJaJgGACtt3KSWk01fdSkkVSgc5xX3UC88cI0hVKfqoq5JczLcpOVR92qJVOgb66qKePDoo17TvEdCvRxjvLcwld0M+fdUtRWtRUtV6lKJUonaVG8w2klsjDLfMbiAOAxGScHQqJyGD2dBkjBNsq1X5ZekYdU2vWUm47lJNyhuIMEoxmsSWS0ZOPI07JrlbBoidbzT5ZoEp4rbxHFNeAhCzReMH8DeN3UJ57JuQtBGmZUkKVg6wQQT56cCdtaHfHOspw8NYZ2NJ2rdTtnij0f8MArfyLmpaqinSND7RupoPOTin2jfGDg4nodN2jp9RtnD6P8AhgwtoGKpjcqyws+3Xmbq6Rvqrvp91WI9o3RpGbRy9T2dVbvjD6r7BFI2sw/cDmOdRd1T5pwV790aqaZw9RoLad8ZXVEp2WIiwkRlNGACPNSiXE5q0hSdhFe7ZEptcgwDFp5H4qYV6Cz7lfPvhiN/7jNw6AxNSq21ZriClWwj2g6xvEbxalyM2sDQEXSIyaByQy2e8/uQj4lRhqliKNKma7OSYTLPH+k58CoSfJjen/Nh719TEc66FD6BJ4I7rkSkK2WERxyLiU7CXYDJXMsja6gf5CJXMXui3TN+xm5SFlJQLxfG55gw/L4UtGZ/EHwJjs6f8qP+6idvrFBGpmW1g5NzU4aMNEprQuK5raeKzjwFTujOy2EPWZeNbZptgcm0rLjSTSg8sXkK5rCeKT9biq7dCFusk/V2Ga6N8JZZKtfLiXZGjlkh0gUFOaymmFKfW4C7fCErTu6Xsa2e9nor5/0Adr2w/Mmrq6jUgXIHBP5mpjFyb5nfo0dNC9BfHxK0S+cQACVG4ACpJ2ADGIyXnXHGWEFn8nz7gznfok9XFw9mCe2/dGsYN8zharX0w2r9J/ItUZNJl/qJv1qN6j2xqkkca2+dj9JiCpScYkyHmbQIgAemcqWmBV1wDYnFR4JF/bhF4wcuRDaQK2zylzDgKJcaFHXNFOnh0Ue07xDdenivW3MpWdANdfUtRWtRUs3qUolSidpUbzDsZLwF3l8zmdF+Irg9WDIHIMkjdYxyXPZ0HEB4KieIjAoKieIjA820opKgKgY/PhdFuJBwkmyrVfll6Rh1TS9ZScRsUk3KG4giCUYzWJLIKTXI0/JrlbBoidbp/WaBI4raxHFNeAhKzReMPI3jcvEJ53JuQtFGmZUkFX2rBBBPnpFxO2tDvjnWU4eJLDOxpe1Lqds8S6P+AAt/IualqqzdI0Om2CaDzk4p9o3xhKDR6DT9o0ajbOH0f3BlbcQmNyrLGzrdeZurpG+qvUPNViPaN0XU2jmajs2q3fGH1X2CezrWYfuBzHOougJPmnBXv3RqppnDv0FtO+MrqiwVIxYSPCRgA89YyHU5jiAtOxQr2jYd4iVJp5QYBq1eTFRqqVVf5Jw+xK/yV3w3XqfCaMpV55FryPWS6xMzTb7Sm1htu5YpXnKvBwUN4qItq5RlCLi8kVJpvJpVuuAS734TnwGEJchzT/mw96+p8+rcuhZI9vbPchuuRYRnMSy2VGBsrXBzYRZMN0mpf8Zv4xFU90M6itR01n/y/obcpUNHiTEcprCmJq0ZnRNkp0gqtXNbTzE4rOPAVO6OpXdCuqPExaUHKWxeWVkXKy3PmSHli8g81lPZ0/Su3QtZq5S2jsawpXvZNtHlBbaGZLpCyBQU5rSeFMey7fCMrDq0dnSlhz2XzA21cpH5k/SuFSdSBcgcEj3mpjJ5fM7unjVQvQj8fHzIjb9SABUnAC8k7hFeEc/ER5sL7AyNceop5YZRsxcPZgntv3RaNbfM5+p7ZqhtX6T+X9mi2LYUvLCjTYCqUKzzlnio+4UG6NoxS5Hn9RrLtQ/Tfw8PIsVNRYVIr0oDqgAFcp3pWWTV5xKSb0oxWr7qBeeOG+NIVSn6qKuSXMyy2cqFrJDCdGjrGhWfyT7eMMx03DzM3b0BpxRJqSSTiSak8SY0xgrnIkKieJkYFhUWUiGhYVF1Iq0KCosmQdzotkAwc5M50dNjxOftwn+Jh7TbumRnMgJsYqa8S/0RX8TH2h3bGDkRM9drxL/RB+Jj7Se7ZIlciHr85bRBBAGc5UUvJ+rq2a4PxMfaHdMkO5JTKrkuNa7ytZoCAClP0fNEStTH2kd0xDfJ9NH7RjxOftxf8XD2kdyyS3yazh+1l/G5+3FlrYe0juZFpZGQFqS69JLzTLS9qXHBXcpOioobiCIiWqqksSTfkSqpx5M1DJ9c7m5s4JcqGDjC1877za0ADiD2CEbO7/Rn4myz4kK3si5WZqrN0Tp6bdBU+cnBXHHfGEq0zp6XtO+jbOY9H/AFP8mk0Cc1xkp1ElaSRvGaad8Z90zrLtrTtbxl8iOrk3m+ux4l/og7tkf+vp+kvJfctrJsC0mKAuMuN9Va3DQearMqPaN0XSkjn6i/RXb8LT6pL6ZChuSNBUAHWAagdtBXujQ5TxnYlMyMBBPYlgIAH3FgCAAfyimvoHvw1/AYh8jWj82PvRgzjkYI9ZbPcYSKmJYtHMmWcu1QRm2dWmvhRa5Pn+al/wAZv4xEx5oz1r//AD2e5mwTUyE8YaPDA9ak84R9HmlV/wBZSkjHEUSe67jEMvDhb9Ll7AKtKxZ2YNVutlNSQgKUEip1AIv4m+KOMnzOnTq9NUvRi/f4/UjDImZPSa8S/wBERwM2/wDSp6P5fcelshXifpFpCfMqonvAA4xPAUs7Shj0E8+0vpOwUMD6NNDrUb1Ht+UXSSOZbqLLfWf2JCXXEazEmJZSVvqTcqAAjkrXQvEwAVOUTFqvVRKLlmG+uVuKeP8AqzUdlTsIhip0reWX/veUlxeAAv8AJVaClFS32FLN6lKcdUonaVFuphv8ZX4JmLpk+YwrknnvKS/jc/biHq6/aHcyI7vJZOjpy/jc/bij1NftLd3Igv8AJzNpxUz2KX+iM3fD2k92yGvIqZGKm/Er9MR38Se7YlOSEx1mvEr9MStREju2PN5FzB6bXiX+iLfiY+0ju2SE5BTJ+0Z8S/0Rb8VH2kd0zeEuNK6Se8Qhka4JdH5DEzJNK6SfEIjIcEuj8iombNSk1Ck+IYa+MGQ4JdGD85VN2dd94e/XEhwy6ENM0B0h3wEYfQlsWgOsO8QBwvoWctaKesO8QBwy6FrLWknrDvEBPBLoWTFoo66e8QBwS6MmInUddPiEGQ4JdH5DomkddPiERknu59H5Hi62emnxCJyRwS6PyEZ6OunxCIyHBLo/I6FN9dPiETlBwS6PyFB5sdNPiEGUHBLo/I4ubQOmnxCIyg4J9H5FdOWgjrp7xE5Dgl0BTKC0ElpwZw+ovWOqYh8i9UWpx28UY6pUYnoZyyybIs64rJj2lq8WTlRQfbwTbBT/ADDKqgUcQbzsUDTj8ovFbiOtmlTNdUzRLQtAYBQ2jnA1G/djDOTxnDLoQELCz9YHtEAcMuheWfIpOKk94gyHdz6PyLVuSaHTT4hBlBwS6PyFmUa66fEIMoO7l0fkR3pFvUpPiEGUHdy6PyK2akE9ZPeIjIcEuj8inmpJPWHeInIcEujK/Sls3KHeIA4ZdC7snKMC4qGzGAjhfQKJS1Wlj66e8QE8EuhKLqD00+IRGSe7n0fkMOFB6Se8ROQ7ufR+RCmGkHpJ7xEZI7uXR+RVTMkg9JPeInIcEuj8isekE9ZPeIA4JdGMCXA6Q7xAHDLoSG6DpDvEAcEuhmDd5AAvOGEK4PcK3BYshKBnEJJIN+cDrpQAX4VvrEYwT3rlsJdezidQNbhvuqd9MYhjEUsEV2WB1QJlJ1ZK9+WpGiZzraWiMRFthXLQpJiGi0ZseQsRGDeNjH0KGyIwbxsHkqGwRXhN42DiSNgiMGqsFimwQYLqZ2g2QE8R67ZEYDjOGmwROCHMbURsEGDOU2RnSIukK2WEN1UWSErLGeYRnGBlKo8Ui5aRQRkzt1w4YjjTWcdgrtAwvNKxKKWTwImZoJTmgX021peTeRcSLiDqi6Eptt5K1RKjea8b8YDNewlS8uNkUbHqaiQUgahFRrPCIKxsETgo7TmeNggwR3osKGwQYLq0Vmg6hEFspiFsDZE5KSryRnZcbIsmKTrIrjFMIshOdbQ2hebBhFYWyiycxMDYIo4nQq1WSWnNOoRXA4pZOlsbBADQgtDYIko0NqaGyJMnEQWhsiSjRzRjZAVwTnilsfVIUTqCRXNzeduSb+8xbIo4SZXuv1NaUGAAwG4bsYC8ZOIpt6K4N4WklDkVwNRsFKQDAWlFSK+Zloumc67TkFaSIuc+UWjiVQApDqXIjBrGY8lyIN42DqXIjBqrB0ORGDVTFByDBZTPFyDBPGJLsGCjmNKcicGUrCM6uJwK2TI5NYsLN5ZZ2ezrjOTOppKsblpLIBrUEi4UAvFeluAp7YhDdsschE3NpvCRtANAKYDm02j8oshVp+JULMSYSeR6WarENm9FeSaTQRQebUURnHIlIWnMazosY8RzPgI4hQXAWUxxDkRg0jYPocirRvGwWRWINMJjLjUWTMJ1kN1iLJidlJFUkiLZFHFxH2ZqkQ4m9eoaJ7UyDFGjoQvTHgaxBummcIgIaE5uqAzaJwS0m9QxJFCkm8Urm7se/dFxXE3yK/NBio0kpDLkvEpmM6COpBEWFnFxFIciMFoTJTTsVaG4WDxAMQbNKSIcxLRZMSu05XOskRpk5s6nFjdYkyyLSuIwXUxxLkRg1UxwORGDRTFB2At3h7SwB3gkuQFXMbU5E4M3MZWqJMJSHZVqpiGzWitykXTaaCMjuQjwxwIWYlFZMiuqiyFLJDSE1MSYxXEyybTQRmzqQioxGHXIlIXsmRyYsLtnICuRJMSQcrAVydC4CVIcQ5EGsZklt2KtDULB8KrEG6aYlbcGSsq8kV1mLJis6iI6xFkxKdPQZBIidjFOUWSWpqKuIzXqWiW3M1ivCOR1CY4HAYMGqmmdUquJrAGxz+CfT9i76tfyi2BH8RCP6l5ofaYdN2hc9Wr5RDixiGsqfOS80Oqsh5WDDvql/KI3LSspl+teaIb1jPj7B31a/lFlkTnKtcpLzQymTeH2TngV8onBSN8F+peaJbMq95Fz1a/lFWmNV6qv9y80Sk2c+fsHfVL+UVwxn8RS/wBS80MvWI+fsHfVL+UWWRayVMv1LzRWzFivj7F31a/lF0zn2KvwkvNEJci6MW1+BXyiRVyivFeYjQL6ivCflEh3seq8zoZX1FeE/KAt30eq8xWhX1FeE/KIwT30eq8z2hX1F+E/KDAd9HqvM4WV9RXhPygwQ7o9V5iSyvqK8J+USV72PVeYpmRdUaBtZ4IV8oAjODfNeaLuUsd9Iziw7QCpOjXQDbWkZyydjSupfqXmjyzFB+TI7ioshabIjqosKTZKkGCogAEkmgAFSScAAMTFZDGngkuJk+YkXh9i76tfyiEmXt1NXhJeaISpF7yLnq1fKL4FHdW/1LzQn+Ae8k56tXygwyve1/uXmj38A95Jz1avlBhh3tf7l5o5/wAe75Jz1a/lBhle9r/cvNCDIO+Sc8CvlAQ7a/3LzQhUk75JzwK+UBR2w/cvNCf4Z3ya/Ar5RJHfQX6l5oebYc8mvwK+URg1jqYfuXmiW1KveSc9Wr5RVxGoaqv9y80S0SD5+wd9Wv5RHCxmOpqf6l5oUbJfP2D3ql/KIwyXdS/1x80MuWO//wBd71S/lE7mMrKf3rzRGcsV/wAg76pfyi24tN1P9S80Rl2M/wCRc9Wr5RbcWl3fhJeaGf8Aj3h9k54FfKAorIr9S80OJl3vJOeBXyiMGsdTFfqXmh5Mu75JzwK+URg1Wqh+5eaN6ckwsXQyeQKecs1SbxAA3J2oto0VWkABFLzaH074AKq07K1iACoSpSDfABayNob4CMF3LTQMBOBx+WSsQAD9pZPg4CAAYnsnyMBABUPWctOqACMWFDVAAnRq2QAKTLqOqACUxZi1QAGOTdhUoSIACS1wEyzwHknPgVES5G2n/Nh719TAlG6FT3U3uMOKiwrNkcCpiRdLilgI8mubMy5/rN/GIpF+khvUpR0s/wD5f0NNnn85UNnhiLSADlIAFJRAB0twANLagAjusQAQX2YAIalFJgAmSdoU1wAEMhaW+AC+lZ6uuAME5LgMACHGAYAIb0jABXvWeNkAENyzRsgAR/AQAZG3ygWknCaPqmf0R1O5q6fUW7yQ8eUK0zjNf6WP24utPS/D5v7lXbMjP5YT6sZiv9pn8kQPS1+C+pHfSGW8sJ9BqmYI9Br9EZPTwXh9S6tZNTyjWmRQzR9Ux+3F400vnH6/ch2TGHssp9WMxX+0yPciLPS1+C+pHeyGP/l08Ptz6tr9EZvTw6Fu8ZcWHblsTB+heObrWptoNj0ii/gKmM5xphzRdObNQybVMNisxNqfWdWjbbQOASkKPEnsEKTlF+qsGqT8QmamgYzJFOS6FaoAK6cshuhUSAkXkkgADaScICVFt4QA29bksglLA0q+tg2O3FXZdvjJ2rwOzpuxbp+lZ6K6eP8AXxBRdqTBJOeBuCEUHCoJineM6a7HoX6fmxxi05okJS4SomgAbQSTsACb4O8Zb/ydNFZksJe1/cOsncnbSXRb7+gb6ujaU6ezNontv3Rdcb5nJ1M9BXtXDifveP7DlhaEfRBYU4lIJBKc+huClJTSleAEbYeMnHbTZX28/wDQPfhOfAYrLkaUfmx96+pgxVdC2D20mR3VRYVnIdkmqmsVkzXS15eS2stz+YZ/Fb+IQQW5btCX/Ca9jNKF8NHhziHUqqAoEpNFUIJSdh2GJawAsJiAHm24APTcopSaJcU2rUpISe8KBBEQy9c1F5az/vYBtsotRiqtLpG+uhtskDzkZtR7RvjNuSOzp1oLtuHD6Nv65KA5Szflv8G/0xXjY9/5un/b839zrOU0ylVVKDidaVJSnuKQKRKmzKzsymSxFY/3tLuTthh+6uY51V3VPmqwPv3RoppnGv0NtW/NdUV1s2fNAlTL9PMUlFOxWbXv742jKH6kJNPwBh7KG0GVZq3FIVvQ37Dm0PZDEYVszbkh5rLm0BhMn1bX6I0jVX0KOciUjlBtMYTR9Ux+3Gioq6fX7kOyQ6nlFtT/ALZ9Ux+3F1p6f2/N/cr3shX/ANi2p/2z6lj9uJ/DU/t+b+5HfTEq5QbTOM1/pY/bifw1X7fr9w76YhWXlpf9n/Ux+3Efhaun1DvZCDl1aP8A2f8AUz+iI/DV9Ce+kDRRF3ApkReIrui3MWlyLRmVcRy4xpsyu6G1NRnKvoWUidZNjTD97bZzNbirmx6WvgKmMpXKvZmir4jUMk8hpFICn1ad7qq5rQO5HS9IkbhClurlLZbGsKlEL5myABzKADAC4AboVyaleplaIAHET2aKqNALySaAb66oCUm3hFPaXKI23VLI0q+tg2O3FXZdvjOVmOR1NP2VOe9j4V8wMtbKGYmjV5wqTqQLkDgkXdpqd8YybfM9HpqKdOv+ax7fHzITZKiAASo3AAVJO4DGK4G3YkssL7CyGddot9Whb6uLpHDBPbeNkaRqb3ZyNV23XX6NS4n18P7Ct+0LNspAqUpXS4f+R9Y99CddyYaq08peqjzWq11tzzZL4eHkZ9lLypzL9USw/h2utcp4j72COy/fHRr0kY7y3OfO7oPcj8wS9NKUoqUpDZKiSSTnKvJN5MU1vqxSLU5ech9bT1WXfw1/AY5z5DlH5sfejElKuhc9jOQyBnGJF0nORZIGamM+Z04rggLshVZln8VHxCNI80c3WPNU/czVQIYPIGQZSzjjNoPraWpC88XpNK8xNxGBG43R0qoqVaTF5yakEdgcomCZpH91sfE3+ae6Mp6TxgWjb1NJsuaafQHGXEuI2pNabiMQdxvhSUXF4ZqmmTSiKkiS3ABQ21knLzFVFOY710XE/eGCvfvirgmPaftC6nbOV0f+2AO2skpiXqrN0jY6aATQecjEe0b4ycGjuaftCm7bOH0f3B8prFRxxJslbDzV1c9HVVfTgcR7t0WjNo5+o0Fdu+MP2Fqial5kZigAo9BYBqfNOB98axs6HEv0NlW/NFdOZJholbRvFaBRNBzbs3Wb6ih7xjDEbn4iLigTnkKQshSCjYk9laHA9kNQsWDKURsLjVTKOIsLjRTK8IrOi/GRg9nQcRGDtYOIMHgYlMMHaRbCZAlTUZusspE+yLAmZm9ps5nlFVS2PS14YCpjCdir5s1UHI0TJbJGUZIVMjTuDUsUaHodL0qjcIWs1c5bLY1jVFGkhLDqQKAClABcANgEKGhVT2TZHObPdABC/j35f696BiTgBx1QEpNvCKm1OURgDNab0jm03NjtxV2d8ZynjkdPTdmux/8AV8K+YD2paTsyauLqNSRcgcE/mb4ycm+Z6CnR01LFa+PiQEsKJASCSbgAKknYAMYC8ocKy+QS2VkW+uinvokbMXD2YJ7e6LqDfM5V/asK9q938gnQ7JWcm/NS5SuOc8sVA7BU7hUwxXU3yRxNRrLLfzJfDwA3KDlJfd5kuCyjWo0Lpupjgjsv3iHq9MlvLcRlb0Alx0qJUolSjeVKJKidpJvJhpbGL35iaxJGA95JT9LMfcR8SoT1nJf7ob0h5bL1GXfw1/CY575DdP5kfejGCqt0YHqpPieCdKM0FTFGx7T08Kyz0w5WJSC6zOw/YQ/mWPxUfEIsuYhqvyZ+5msGGDyRjGWQ/npj74+BMdWj8tCtnMqAI3wZtkiQtF1hekZcU2vak0ruIwUNxqIrNRksMmLa5B5YnKeq5M0j+62Papv8090IWaZfoGI2dQ4kLebdTntrStO1Jr2HYdxhWUXHZmuSxbnEmIAeBBwMAFFbWSkvMVUU6NzrooCfvJwV798UcEx7T9oXU7Zyuj/gBbWyQmGTWgcb66K3AXkqTiOyo3xm4NHco7Qpu25Po/4ZVOobTeBUKScFHXqodW/jjEG7g5HGbWdQesjqKqQBhzTiMIspNCV/Z9c9+T6osG35eYGYoAE9BdLz5pwPvjSM+hxr9DbV4ZXsKm0skCL2jTzFYdise+sMxu6iLgDU1LONHNcSUq3jHgcD2RvGWeRm44GwuNFJlcCguLKZGBQVFuJlcCyI03ILOxrCmJk/RI5mtxXNbHpa+AqYzldGHMsq2zUcmMipRqipj+YcuuUKNCmxuvO9Ko3CFLNXKW0djaNSW5oCdEsAUAAFABQADYBChqQpqwkKvTABUTNnuM1VWiReSTQAbSYCUm3hFBN8ouhqlsaVW03NjtxV2d8Uc+h0qezJy3s2XzBK18pHps1fWSNSBzUJ4JHvNTGMnJnodLVpqViEfj4leJQLICQSo3AAVJOwAYxXLN501NZzgJLM5N5tYz1/RJ6uLhHDBPbfujVQb5nD1HaFdTxU+L6FquaasoUWlCVka+c8se+ncI3rpb9VHH1Gsst/Ml8PAp7W5QnnAQ3RhN4KgQpy4X34JVfgK8djddKXrbicpvwASbtEuVrUkmpUSSVG+tSbyK30OENppGLyRM4RbiRGGezhBxIMHCuI40GAy5NJkpcfoMUI+JUKap5SNqlgNJ9t1xty400az/iYRfIapWbIr2r6mdy0sAKmFWz3FWnUd2Lee1CBImyzwRHiwvzJ9gqpMs/ioH+QiY8zHVfkT9zNYSmphg8gY1lomk/MffHwJjr6f8tClvrFEpUXlIokIrGbeS56kGAH5OacaVntrKFbUnHcRgRuMRKCktyVJoMrGy8IomYTT+ogfEj5d0Kz037TWNnUObPtlLiQttYWjak1HA7DuhVprmarctpe0QcYgCcl9Oo6/dABSW1ktLzNVFOY6emi7xJwV798VcEx7T9oXU7Zyuj/ANsAls5JTEvVWbpGx00Amg85GI9o3xk4NHd0/aFN+2cPo/4YPlAMVHXAsLPtZ1qgrno6q7+44j3bosptCF/Z1Vu+MPqglk5mUmxo1gJUfs3KUJ81WB9h3RrGw4mo7Ouq3xldUVlscmpvVLLofJrJp6K8R214iG4X/uOa4dAGtCzHWFZjzam1agoXHeki5Q3gmG4Yl6plJNEcIi/CUya3k3kZJsEKmRp3NihRof2+l6VRuEJWauctlsMRqig9Qww4AEkDYMANwhU0GHrEUL0mACG6260Co3JF5JNABvOqAlJt4RQWhyhpaqloaRe28NjtxV2d8ZufQ6dHZc5b2eivn/QH2tlK/NGrzhUnUgc1A4JHvNTGUm3zPQ6Wqihegvj4kFICyABVRuAAqSdwGMV3GnKtrLCqxuTp16inVBlHVuU4ezBPbfujSMJPmcPV9pUQ2q9J9fAt52UlbKTUuJQsi4Vznl8AL6dw4Q1XTKXqo4V+rnZ67+AKT3KRNunRsEstmtV3KcpTGp5qBtpU7DDkdMo7y3EnbnkDZqCVuLJcX9ZxSgsk804m81FRnHZshlT2xgycSumJrPNThUkC66vDHVfF04lWmNUTBiAZkczEwcEA4me0Yg4IBxM6EJg4YBmRofI2Wg7MlYu0bdPEqFNbwqMcG9OfE0q1rTZDDwSkf+Jwf4GOc+Q7p3i2PvX1MOU+ThC2D2k7nJiAIkySOxBYnWEP5lj8Vv4xFo8xfVfkT9zNolpel5hg8gYVl64P+QmaYaQfAmOpVL/mhWa9IHwIslkqOBEaKJVs7SLYIyepBgDxTBwk5LCyUuIIcbcU2qprQgZyQK3A3KvuvFL4xnBPZovGWAxkctUJGY+KGuaVoGcBS8KUjfrpgdUKT0r/AEmytXiFMnM6ROkaWHEHpJNRXfsO4wrKLi8M1TyS259acYgCU1ao1wAVtrWHKTNVU0bh6aKAk+cnBXv3xRwTH9N2jdTtnK6MCrXyaeYqRRxvro1DzkYj2jfGbg0d3T9pU3bZw+j+5S1EUH8l1Y+U78vRIVnt9Rd9B5qsU+7dF1NoR1HZ9F2+MPqgwk7ekp1OidSkE/ZugFJPmqNxOzA7o2hbh7bHB1PZttW+Mrqijtjk0bUrOl3dGNaFgrA+6rHsNeMOw1bxiSOU6V4B/msLuJoYTNhh+xU0K0OhIF5JUAAN5OEBKTbwgVn8tXJclLKtMRrvzO/pdl2+M3Yjq09kXSXFNYXz/oErXyompk1fUVJ1IFyBwSNe81MZNuXidnTQhpliMPj4+ZATMJUaZpqcABU9giMMaeoqa9LYKbByND9FPOpZR1cXD2YJ7b90XVcnzOXqu1KIbVLify/sJpuTs+zUZ2mQlRF1+e8vgBzqdwG6GqqHJ+ijgajV2WbzfwAa2eUGZXVMvVpHXNC6fyR2VO+HoaPHrbiMrugGuurUoqWSpZvUpRKlE7STeYZWVskZN5PNPlJrTcQcCDqMS5EYOOO5xqcdwoAAKADsiMoMMTdBsG56ggwg3OZog4UTlns2DhQZPZsRwhkO+SZoF2Yr1EfEqFNWsJG9JoNptJDLv4a/hMIPkN0fmx96MfELns9jtYgjJ5KawEqLZaZPgJmWCfLN/GImPMz1UUtPPPRmnT9qFZzUYQyeLMWysbP8a/XHPFfCmOpRHMExW17lWBDGEjLJ2JA9WAD0GwHonIDqXyE5t2sVpeAcQDviMBkapE4IJMhPOsKz2nFIXtScdygblDcQYpKuMlhotGbXIO7D5QEKoibbzT5VsEjipvEcU14CErNG1vA3jcvEOZWVafQHGVpcbPSQQocLsDuMJSi4vDNk8nl2QRhEEjZs1Y2wAVNp5INvVNMxzrpur94YK9++KuKY5Rrrats5XR/7YD7WySmmKqzdI2OkgE0HnJxHtG+MnFo7Wn11Vu2cPo/uUgQYrk6HCy4s3KCZYGalecnUlYzgOF9RwrSJU2hW3s+m15kt/ZsGGUGUjDZKGklx0XGtUoSd5N57O+NJWJcjlaTsmy1KU3hP4sBrRm33jz3CRWoSDRA4J/M3xk5Z5nZq0Eafy+fXxIOc4nfEbG3FdAv7MsJ1dFPDMbN/NKSsjdfQdvdF1Uc+/tlQfCo5a8gvatGy5JoqVLlIwKzVa1E6q/8AoRvXXl4icHUaqy55sfw8AIyky5DxKZVnQN9dVFOns+qjXtO8Q/Xp616zyITsfgBy+cSoqJUcSSSTxJvMNKEfBmTlLxPBs7YtwvwZXi9h7NVtgxPqGYnudsEGZBseJOyI4n0DHtOV3RHEuhOPacqIOKJPDI9UQZiRhnronMQwz1BtiPR6huHvJIEaWYzlEcxFLq9JUK6zHCsG1JodqJZ0LvPNdGvUeod0c98hyj82PvRjqc2mMLbntP8An1OhSRBuHFBCTMbBBgo7/CKJlhS6lzLAJxdbHeoRaOMi2pjKVM2+jNol5FtsYVMMHkjDsu1f/oTP4g+BMdah/wDOP+6iti9IoKxo5FMHCYjiJwJJMV4gwezojiJ4TmdBxhwnc8wd4HCd0hie8I4Doci3ehwHdLE98RwEyy7Zell6RhxTa9ZSbjuUk3KG4gxWU4SWJIlKUeRpWT/K6mgTOMgHyzQOb6TeI4prwEJWaZc4G8bOodN5Ry6gFAGhFcDgYUNRRt+X6p7oAELyhY1JPdAAOW7JyMzVWjLbp+0bFCT5ycFe/fFJQTOhpu0rqNua6MBrTsh1k6loJoFC7vSbwe+MnBo7tHalVvhh9H/R/9k='; +$string['boolean_filename_01'] = 'ENflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/lang/es/surveyprotemplate_flags.php b/template/flags/lang/es/surveyprotemplate_flags.php new file mode 100644 index 00000000000..f841aa21340 --- /dev/null +++ b/template/flags/lang/es/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

¿Reconoces esta bandera?

+

ESFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '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'; +$string['boolean_filename_01'] = 'ESflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/lang/it/surveyprotemplate_flags.php b/template/flags/lang/it/surveyprotemplate_flags.php new file mode 100644 index 00000000000..c261cccc069 --- /dev/null +++ b/template/flags/lang/it/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

Riconosci questa bandiera?

+

ITFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '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'; +$string['boolean_filename_01'] = 'ITflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/pix/icon.png b/template/flags/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f0470bc8beb397ac8fa5b5fef4904b74abf5198d GIT binary patch literal 625 zcmV-%0*?KOP)<~e5aB&bz6^zoBBY3DP$_f}2M1F(h4@kN3)49G5o`12J%>`o zw8r?1clZ3bdpM|~U~t%7tq&lT1@GPq9_#CmeFAMF(|bGDei}E z7l2Xq7~2)I-S$Co*yEmOr#~|I%!u4_5Npl%&(W^O6D^zHKUrs$OBsbx;F^NC036Vl z_l|u8l5{4{`Bv5SfH~l(w#TNgXSck|`hhVo+}sW}z&I37F9QD1RKlKtG>{HNQlp#l zPurfu?gThXW&u+zFhxt>>Q=A+oB5xB1<2B0`7b~fuzd>D0EkiuLHLIRw%ns%eDIqf|7d^`c6buf#3k{!Q2;0uwJ()G-a&rkT$KgY*XV$Erx>2*+7pITM00000 LNkvXXu0mjf6VDRf literal 0 HcmV?d00001 diff --git a/template/flags/pix/icon.svg b/template/flags/pix/icon.svg new file mode 100644 index 00000000000..a1fdefde9d6 --- /dev/null +++ b/template/flags/pix/icon.svg @@ -0,0 +1,579 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/flags/template.xml b/template/flags/template.xml new file mode 100644 index 00000000000..78a3ac8d52f --- /dev/null +++ b/template/flags/template.xml @@ -0,0 +1,27 @@ + + + + + boolean_content_01 + + boolean_filename_01 + boolean_filecontent_01 + + 1 + 0 + 0 + 1 + 0 + boolean_extranote_01 + 0 + 0 + 0 + + + 2 + 1 + strfbool01 + + + + diff --git a/template/flags/version.php b/template/flags/version.php new file mode 100644 index 00000000000..ef05fb86a6e --- /dev/null +++ b/template/flags/version.php @@ -0,0 +1,30 @@ +. + +/** + * Defines the version of surveyprotemplate_flags template subplugin + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2024042200; +$plugin->release = '1.0'; +$plugin->requires = 2024042200; // Requires this Moodle version. +$plugin->component = 'surveyprotemplate_flags'; // Full name of the plugin (used for diagnostics). diff --git a/template/oneofeachenable/classes/privacy/provider.php b/template/oneofeachenable/classes/privacy/provider.php new file mode 100644 index 00000000000..90227db75e9 --- /dev/null +++ b/template/oneofeachenable/classes/privacy/provider.php @@ -0,0 +1,44 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_oneofeachenable\privacy; + +/** + * Privacy Subsystem for template_oneofeachenable implementing null_provider. + * + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/template/oneofeachenable/classes/template.php b/template/oneofeachenable/classes/template.php new file mode 100644 index 00000000000..8f654357a59 --- /dev/null +++ b/template/oneofeachenable/classes/template.php @@ -0,0 +1,47 @@ +. + +/** + * Surveypro class to manage oneofeachenable template + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_oneofeachenable; + +/** + * The class to manage oneofeachenable template + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template { + + /** + * Apply template settings. + * + * @param string $tablename + * @param object $record + * @param object $config + * @return [$tablename, $record] + */ + public function apply_template_settings($tablename, $record, $config) { + return [$tablename, $record]; + } +} diff --git a/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php b/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php new file mode 100644 index 00000000000..bbc4addaf17 --- /dev/null +++ b/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php @@ -0,0 +1,248 @@ +. + +/** + * Strings for component 'surveyprotemplate_oneofeachenable', language 'en' + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['age_content_01'] = 'age_content_01'; +$string['age_content_02'] = 'age_content_02'; +$string['age_content_03'] = 'age_content_03'; +$string['age_content_04'] = 'age_content_04'; +$string['age_content_05'] = 'age_content_05'; +$string['age_extranote_01'] = 'age_extranote_01'; +$string['age_extranote_02'] = 'age_extranote_02'; +$string['age_extranote_03'] = 'age_extranote_03'; +$string['age_extranote_04'] = 'age_extranote_04'; +$string['age_extranote_05'] = 'age_extranote_05'; +$string['age_filecontent_01'] = 'agefilecontent01'; +$string['age_filecontent_02'] = 'agefilecontent02'; +$string['age_filename_01'] = 'age_filename_01'; +$string['age_filename_02'] = 'age_filename_02'; +$string['autofill_content_01'] = 'autofill_content_01'; +$string['autofill_content_02'] = 'autofill_content_02'; +$string['autofill_content_03'] = 'autofill_content_03'; +$string['autofill_extranote_01'] = 'autofill_extranote_01'; +$string['autofill_extranote_02'] = 'autofill_extranote_02'; +$string['autofill_extranote_03'] = 'autofill_extranote_03'; +$string['boolean_content_01'] = 'boolean_content_01'; +$string['boolean_content_02'] = 'boolean_content_02'; +$string['boolean_content_03'] = 'boolean_content_03'; +$string['boolean_content_04'] = 'boolean_content_04'; +$string['boolean_content_05'] = 'boolean_content_05'; +$string['boolean_content_06'] = 'boolean_content_06'; +$string['boolean_content_07'] = 'boolean_content_07'; +$string['boolean_extranote_01'] = 'boolean_extranote_01'; +$string['boolean_extranote_02'] = 'boolean_extranote_02'; +$string['boolean_extranote_03'] = 'boolean_extranote_03'; +$string['boolean_extranote_04'] = 'boolean_extranote_04'; +$string['boolean_extranote_05'] = 'boolean_extranote_05'; +$string['boolean_extranote_06'] = 'boolean_extranote_06'; +$string['boolean_extranote_07'] = 'boolean_extranote_07'; +$string['character_content_01'] = 'character_content_01'; +$string['character_content_02'] = 'character_content_02'; +$string['character_content_03'] = 'character_content_03'; +$string['character_defaultvalue_01'] = 'character_defaultvalue_01'; +$string['character_defaultvalue_02'] = 'character_defaultvalue_02'; +$string['character_defaultvalue_03'] = 'character_defaultvalue_03'; +$string['character_extranote_01'] = 'character_extranote_01'; +$string['character_extranote_02'] = 'character_extranote_02'; +$string['character_extranote_03'] = 'character_extranote_03'; +$string['checkbox_content_01'] = 'checkbox_content_01'; +$string['checkbox_content_02'] = 'checkbox_content_02'; +$string['checkbox_content_03'] = 'checkbox_content_03'; +$string['checkbox_defaultvalue_01'] = 'checkbox_defaultvalue_01'; +$string['checkbox_defaultvalue_02'] = 'checkbox_defaultvalue_02'; +$string['checkbox_defaultvalue_03'] = 'checkbox_defaultvalue_03'; +$string['checkbox_extranote_01'] = 'checkbox_extranote_01'; +$string['checkbox_extranote_02'] = 'checkbox_extranote_02'; +$string['checkbox_extranote_03'] = 'checkbox_extranote_03'; +$string['checkbox_labelother_01'] = 'checkbox_labelother_01'; +$string['checkbox_labelother_02'] = 'checkbox_labelother_02'; +$string['checkbox_labelother_03'] = 'checkbox_labelother_03'; +$string['checkbox_options_01'] = 'checkbox_options_01'; +$string['checkbox_options_02'] = 'checkbox_options_02'; +$string['checkbox_options_03'] = 'checkbox_options_03'; +$string['date_content_01'] = 'date_content_01'; +$string['date_content_02'] = 'date_content_02'; +$string['date_content_03'] = 'date_content_03'; +$string['date_extranote_01'] = 'date_extranote_01'; +$string['date_extranote_02'] = 'date_extranote_02'; +$string['date_extranote_03'] = 'date_extranote_03'; +$string['datetime_content_01'] = 'datetime_content_01'; +$string['datetime_content_02'] = 'datetime_content_02'; +$string['datetime_content_03'] = 'datetime_content_03'; +$string['datetime_extranote_01'] = 'datetime_extranote_01'; +$string['datetime_extranote_02'] = 'datetime_extranote_02'; +$string['datetime_extranote_03'] = 'datetime_extranote_03'; +$string['fieldset_content_01'] = 'fieldset_content_01'; +$string['fieldset_content_02'] = 'fieldset_content_02'; +$string['fieldset_content_03'] = 'fieldset_content_03'; +$string['fieldset_content_04'] = 'fieldset_content_04'; +$string['fieldset_extranote_01'] = 'fieldset_extranote_01'; +$string['fieldset_extranote_02'] = 'fieldset_extranote_02'; +$string['fieldset_extranote_03'] = 'fieldset_extranote_03'; +$string['fieldset_extranote_04'] = 'fieldset_extranote_04'; +$string['fileupload_content_01'] = 'fileupload_content_01'; +$string['fileupload_content_02'] = 'fileupload_content_02'; +$string['fileupload_content_03'] = 'fileupload_content_03'; +$string['fileupload_extranote_01'] = 'fileupload_extranote_01'; +$string['fileupload_extranote_02'] = 'fileupload_extranote_02'; +$string['fileupload_extranote_03'] = 'fileupload_extranote_03'; +$string['integer_content_01'] = 'integer_content_01'; +$string['integer_content_02'] = 'integer_content_02'; +$string['integer_content_03'] = 'integer_content_03'; +$string['integer_extranote_01'] = 'integer_extranote_01'; +$string['integer_extranote_02'] = 'integer_extranote_02'; +$string['integer_extranote_03'] = 'integer_extranote_03'; +$string['label_content_01'] = 'label_content_01'; +$string['label_content_02'] = 'label_content_02'; +$string['label_content_03'] = 'label_content_03'; +$string['label_content_04'] = 'label_content_04'; +$string['label_leftlabel_01'] = 'label_leftlabel_01'; +$string['label_leftlabel_02'] = 'label_leftlabel_02'; +$string['label_leftlabel_03'] = 'label_leftlabel_03'; +$string['label_leftlabel_04'] = 'label_leftlabel_04'; +$string['multiselect_content_01'] = 'multiselect_content_01'; +$string['multiselect_content_02'] = 'multiselect_content_02'; +$string['multiselect_content_03'] = 'multiselect_content_03'; +$string['multiselect_defaultvalue_01'] = 'multiselect_defaultvalue_01'; +$string['multiselect_defaultvalue_02'] = 'multiselect_defaultvalue_02'; +$string['multiselect_defaultvalue_03'] = 'multiselect_defaultvalue_03'; +$string['multiselect_extranote_01'] = 'multiselect_extranote_01'; +$string['multiselect_extranote_02'] = 'multiselect_extranote_02'; +$string['multiselect_extranote_03'] = 'multiselect_extranote_03'; +$string['multiselect_options_01'] = 'multiselect_options_01'; +$string['multiselect_options_02'] = 'multiselect_options_02'; +$string['multiselect_options_03'] = 'multiselect_options_03'; +$string['numeric_content_01'] = 'numeric_content_01'; +$string['numeric_content_02'] = 'numeric_content_02'; +$string['numeric_content_03'] = 'numeric_content_03'; +$string['numeric_extranote_01'] = 'numeric_extranote_01'; +$string['numeric_extranote_02'] = 'numeric_extranote_02'; +$string['numeric_extranote_03'] = 'numeric_extranote_03'; +$string['pluginname'] = 'oneofeachenable'; +$string['privacy:metadata'] = 'The "oneofeachenable" template plugin does not store any personal data.'; + +$string['radiobutton_content_01'] = 'radiobutton_content_01'; +$string['radiobutton_content_02'] = 'radiobutton_content_02'; +$string['radiobutton_content_03'] = 'radiobutton_content_03'; +$string['radiobutton_content_04'] = 'radiobutton_content_04'; +$string['radiobutton_content_05'] = 'radiobutton_content_05'; +$string['radiobutton_content_06'] = 'radiobutton_content_06'; +$string['radiobutton_defaultvalue_01'] = 'radiobutton_defaultvalue_01'; +$string['radiobutton_defaultvalue_02'] = 'radiobutton_defaultvalue_02'; +$string['radiobutton_defaultvalue_03'] = 'radiobutton_defaultvalue_03'; +$string['radiobutton_defaultvalue_04'] = 'radiobutton_defaultvalue_04'; +$string['radiobutton_defaultvalue_05'] = 'radiobutton_defaultvalue_05'; +$string['radiobutton_defaultvalue_06'] = 'radiobutton_defaultvalue_06'; +$string['radiobutton_extranote_01'] = 'radiobutton_extranote_01'; +$string['radiobutton_extranote_02'] = 'radiobutton_extranote_02'; +$string['radiobutton_extranote_03'] = 'radiobutton_extranote_03'; +$string['radiobutton_extranote_04'] = 'radiobutton_extranote_04'; +$string['radiobutton_extranote_05'] = 'radiobutton_extranote_05'; +$string['radiobutton_extranote_06'] = 'radiobutton_extranote_06'; +$string['radiobutton_labelother_01'] = 'radiobutton_labelother_01'; +$string['radiobutton_labelother_02'] = 'radiobutton_labelother_02'; +$string['radiobutton_labelother_03'] = 'radiobutton_labelother_03'; +$string['radiobutton_labelother_04'] = 'radiobutton_labelother_04'; +$string['radiobutton_labelother_05'] = 'radiobutton_labelother_05'; +$string['radiobutton_labelother_06'] = 'radiobutton_labelother_06'; +$string['radiobutton_options_01'] = 'radiobutton_options_01'; +$string['radiobutton_options_02'] = 'radiobutton_options_02'; +$string['radiobutton_options_03'] = 'radiobutton_options_03'; +$string['radiobutton_options_04'] = 'radiobutton_options_04'; +$string['radiobutton_options_05'] = 'radiobutton_options_05'; +$string['radiobutton_options_06'] = 'radiobutton_options_06'; +$string['rate_content_01'] = 'rate_content_01'; +$string['rate_content_02'] = 'rate_content_02'; +$string['rate_content_03'] = 'rate_content_03'; +$string['rate_content_04'] = 'rate_content_04'; +$string['rate_content_05'] = 'rate_content_05'; +$string['rate_content_06'] = 'rate_content_06'; +$string['rate_defaultvalue_01'] = 'rate_defaultvalue_01'; +$string['rate_defaultvalue_02'] = 'rate_defaultvalue_02'; +$string['rate_defaultvalue_03'] = 'rate_defaultvalue_03'; +$string['rate_defaultvalue_04'] = 'rate_defaultvalue_04'; +$string['rate_defaultvalue_05'] = 'rate_defaultvalue_05'; +$string['rate_defaultvalue_06'] = 'rate_defaultvalue_06'; +$string['rate_extranote_01'] = 'rate_extranote_01'; +$string['rate_extranote_02'] = 'rate_extranote_02'; +$string['rate_extranote_03'] = 'rate_extranote_03'; +$string['rate_extranote_04'] = 'rate_extranote_04'; +$string['rate_extranote_05'] = 'rate_extranote_05'; +$string['rate_extranote_06'] = 'rate_extranote_06'; +$string['rate_options_01'] = 'rate_options_01'; +$string['rate_options_02'] = 'rate_options_02'; +$string['rate_options_03'] = 'rate_options_03'; +$string['rate_options_04'] = 'rate_options_04'; +$string['rate_options_05'] = 'rate_options_05'; +$string['rate_options_06'] = 'rate_options_06'; +$string['rate_rates_01'] = 'rate_rates_01'; +$string['rate_rates_02'] = 'rate_rates_02'; +$string['rate_rates_03'] = 'rate_rates_03'; +$string['rate_rates_04'] = 'rate_rates_04'; +$string['rate_rates_05'] = 'rate_rates_05'; +$string['rate_rates_06'] = 'rate_rates_06'; +$string['recurrence_content_01'] = 'recurrence_content_01'; +$string['recurrence_content_02'] = 'recurrence_content_02'; +$string['recurrence_content_03'] = 'recurrence_content_03'; +$string['recurrence_extranote_01'] = 'recurrence_extranote_01'; +$string['recurrence_extranote_02'] = 'recurrence_extranote_02'; +$string['recurrence_extranote_03'] = 'recurrence_extranote_03'; +$string['select_content_01'] = 'select_content_01'; +$string['select_content_02'] = 'select_content_02'; +$string['select_content_03'] = 'select_content_03'; +$string['select_defaultvalue_01'] = 'select_defaultvalue_01'; +$string['select_defaultvalue_02'] = 'select_defaultvalue_02'; +$string['select_defaultvalue_03'] = 'select_defaultvalue_03'; +$string['select_extranote_01'] = 'select_extranote_01'; +$string['select_extranote_02'] = 'select_extranote_02'; +$string['select_extranote_03'] = 'select_extranote_03'; +$string['select_labelother_01'] = 'select_labelother_01'; +$string['select_labelother_02'] = 'select_labelother_02'; +$string['select_labelother_03'] = 'select_labelother_03'; +$string['select_options_01'] = 'select_options_01'; +$string['select_options_02'] = 'select_options_02'; +$string['select_options_03'] = 'select_options_03'; +$string['shortdate_content_01'] = 'shortdate_content_01'; +$string['shortdate_content_02'] = 'shortdate_content_02'; +$string['shortdate_content_03'] = 'shortdate_content_03'; +$string['shortdate_extranote_01'] = 'shortdate_extranote_01'; +$string['shortdate_extranote_02'] = 'shortdate_extranote_02'; +$string['shortdate_extranote_03'] = 'shortdate_extranote_03'; +$string['textarea_content_01'] = 'textarea_content_01'; +$string['textarea_content_02'] = 'textarea_content_02'; +$string['textarea_content_03'] = 'textarea_content_03'; +$string['textarea_content_04'] = 'textarea_content_04'; +$string['textarea_content_05'] = 'textarea_content_05'; +$string['textarea_content_06'] = 'textarea_content_06'; +$string['textarea_extranote_01'] = 'textarea_extranote_01'; +$string['textarea_extranote_02'] = 'textarea_extranote_02'; +$string['textarea_extranote_03'] = 'textarea_extranote_03'; +$string['textarea_extranote_04'] = 'textarea_extranote_04'; +$string['textarea_extranote_05'] = 'textarea_extranote_05'; +$string['textarea_extranote_06'] = 'textarea_extranote_06'; +$string['time_content_01'] = 'time_content_01'; +$string['time_content_02'] = 'time_content_02'; +$string['time_content_03'] = 'time_content_03'; +$string['time_extranote_01'] = 'time_extranote_01'; +$string['time_extranote_02'] = 'time_extranote_02'; +$string['time_extranote_03'] = 'time_extranote_03'; diff --git a/template/oneofeachenable/pix/icon.png b/template/oneofeachenable/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f0470bc8beb397ac8fa5b5fef4904b74abf5198d GIT binary patch literal 625 zcmV-%0*?KOP)<~e5aB&bz6^zoBBY3DP$_f}2M1F(h4@kN3)49G5o`12J%>`o zw8r?1clZ3bdpM|~U~t%7tq&lT1@GPq9_#CmeFAMF(|bGDei}E z7l2Xq7~2)I-S$Co*yEmOr#~|I%!u4_5Npl%&(W^O6D^zHKUrs$OBsbx;F^NC036Vl z_l|u8l5{4{`Bv5SfH~l(w#TNgXSck|`hhVo+}sW}z&I37F9QD1RKlKtG>{HNQlp#l zPurfu?gThXW&u+zFhxt>>Q=A+oB5xB1<2B0`7b~fuzd>D0EkiuLHLIRw%ns%eDIqf|7d^`c6buf#3k{!Q2;0uwJ()G-a&rkT$KgY*XV$Erx>2*+7pITM00000 LNkvXXu0mjf6VDRf literal 0 HcmV?d00001 diff --git a/template/oneofeachenable/pix/icon.svg b/template/oneofeachenable/pix/icon.svg new file mode 100644 index 00000000000..a1fdefde9d6 --- /dev/null +++ b/template/oneofeachenable/pix/icon.svg @@ -0,0 +1,579 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/oneofeachenable/template.xml b/template/oneofeachenable/template.xml new file mode 100644 index 00000000000..781d046a543 --- /dev/null +++ b/template/oneofeachenable/template.xml @@ -0,0 +1,1965 @@ + + + + + boolean_content_01 + 1 + 0 + 0 + 0 + 0 + boolean_001 + boolean_extranote_01 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + age_content_01 + 1 + 0 + 0 + 0 + 0 + age_001 + age_extranote_01 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -2138101200 + -2148555600 + -2132830800 + + + + + age_content_02 + + age_filename_01 + age_filecontent_01 + + + age_filename_02 + age_filecontent_02 + + 1 + 0 + 0 + 0 + 0 + age_002 + age_extranote_02 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -1264942800 + -1580562000 + -1141304400 + + + + + age_content_03 + 1 + 0 + 0 + 0 + 0 + age_003 + age_extranote_03 + 0 + 1 + 1 + + 1 + 1 + + + + 1 + -1359637200 + -1580562000 + -1141304400 + + + + + age_content_04 + 1 + 0 + 0 + 0 + 0 + age_004 + age_extranote_04 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -1454331600 + -1580562000 + -1141304400 + + + + + age_content_05 + 1 + 0 + 0 + 0 + 0 + age_005 + age_extranote_05 + 0 + 1 + 1 + + 1 + 1 + + + + 1 + -1233406800 + -1580562000 + -1141304400 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_02 + 1 + 0 + 0 + 0 + 0 + boolean_002 + boolean_extranote_02 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + label_content_01 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_01 + + + + + fieldset_content_01 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_01 + 0 + 0 + 0 + + + 2 + + + + + autofill_content_01 + 1 + 0 + 0 + 0 + 0 + autofill_001 + autofill_extranote_01 + 0 + 1 + 0 + + + 0 + userid + + + + + autofill_content_02 + 1 + 0 + 0 + 0 + 0 + autofill_002 + autofill_extranote_02 + 0 + 1 + 0 + + + 0 + userid + submissionid + cammello + + + + + autofill_content_03 + 1 + 0 + 0 + 0 + 0 + autofill_003 + autofill_extranote_03 + 0 + 1 + 0 + + + 0 + userid + + + + + fieldset_content_02 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_02 + 0 + 0 + 0 + + + 2 + + + + + boolean_content_03 + 1 + 0 + 0 + 0 + 0 + boolean_003 + boolean_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + 1 + 1 + strfbool01 + + + + + + boolean_content_04 + 1 + 0 + 0 + 0 + 0 + boolean_004 + boolean_extranote_04 + 0 + 1 + 0 + + 8 + 1 + + + + 1 + 1 + strfbool01 + + + + + + boolean_content_05 + 1 + 0 + 0 + 0 + 0 + boolean_005 + boolean_extranote_05 + 0 + 1 + 0 + + 8 + 1 + + + + 3 + 0 + strfbool01 + + + + + + fieldset_content_03 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_03 + 0 + 0 + 0 + + + 2 + + + + + character_content_01 + 1 + 0 + 0 + 0 + 0 + character_001 + character_extranote_01 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_01 + PATTERN_EMAIL + 0 + + + + + character_content_02 + 1 + 0 + 0 + 0 + 0 + character_002 + character_extranote_02 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_02 + 00000 + 5 + 5 + + + + + character_content_03 + 1 + 0 + 0 + 0 + 0 + character_003 + character_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_03 + PATTERN_URL + 0 + + + + + <hr class="fieldsetendcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + checkbox_content_01 + 1 + 0 + 0 + 0 + 0 + checkbox_001 + checkbox_extranote_01 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_01 + checkbox_labelother_01 + checkbox_defaultvalue_01 + 0 + 1 + 2 + 0 + 0 + + + + + checkbox_content_02 + 1 + 0 + 0 + 0 + 0 + checkbox_002 + checkbox_extranote_02 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_02 + checkbox_labelother_02 + checkbox_defaultvalue_02 + 0 + 1 + 2 + 0 + 0 + + + + + checkbox_content_03 + 1 + 0 + 0 + 0 + 0 + checkbox_003 + checkbox_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_03 + checkbox_labelother_03 + checkbox_defaultvalue_03 + 0 + 1 + 2 + 0 + 0 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_06 + 1 + 0 + 0 + 0 + 0 + boolean_006 + boolean_extranote_06 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + date_content_01 + 1 + 0 + 0 + 0 + 0 + date_001 + date_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 952081200 + 1593252000 + + + + + date_content_02 + 1 + 0 + 0 + 0 + 0 + date_002 + date_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 5223600 + 1609412400 + + + + + date_content_03 + 1 + 0 + 0 + 0 + 0 + date_003 + date_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 951994800 + 1609412400 + + + + + datetime_content_01 + 1 + 0 + 0 + 0 + 0 + datetime_001 + datetime_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 1 + 18330600 + strftime01 + 5184000 + 20991540 + + + + + datetime_content_02 + 1 + 0 + 0 + 0 + 0 + datetime_002 + datetime_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 5 + -3600 + strftime01 + 5184000 + 28857540 + + + + + datetime_content_03 + 1 + 0 + 0 + 0 + 0 + datetime_003 + datetime_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 1 + 7825200 + strftime01 + 5184000 + 18313140 + + + + + fileupload_content_01 + 1 + 0 + 0 + 0 + 0 + fileupload_001 + fileupload_extranote_01 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + fileupload_content_02 + 1 + 0 + 0 + 0 + 0 + fileupload_002 + fileupload_extranote_02 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + fileupload_content_03 + 1 + 0 + 0 + 0 + 0 + fileupload_003 + fileupload_extranote_03 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + integer_content_01 + 1 + 0 + 0 + 0 + 0 + integer_001 + integer_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 17 + 10 + 20 + + + + + integer_content_02 + 1 + 0 + 0 + 0 + 0 + integer_002 + integer_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 3 + 0 + 0 + 20 + + + + + integer_content_03 + 1 + 0 + 0 + 0 + 0 + integer_003 + integer_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 64 + 0 + 128 + + + + + multiselect_content_01 + 1 + 0 + 0 + 0 + 0 + multiselect_001 + multiselect_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_01 + multiselect_defaultvalue_01 + 0 + 1 + 0 + 0 + 4 + + + + + multiselect_content_02 + 1 + 0 + 0 + 0 + 0 + multiselect_002 + multiselect_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_02 + multiselect_defaultvalue_02 + 0 + 1 + 0 + 0 + 4 + + + + + multiselect_content_03 + 1 + 0 + 0 + 0 + 0 + multiselect_003 + multiselect_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_03 + multiselect_defaultvalue_03 + 1 + 1 + 0 + 0 + 4 + + + + + numeric_content_01 + 1 + 0 + 0 + 0 + 0 + numeric_001 + numeric_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 3 + 0 + 0 + + + + + numeric_content_02 + 1 + 0 + 0 + 0 + 0 + numeric_002 + numeric_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 185 + 0 + 178.0000000000 + 200.0000000000 + 0 + + + + + numeric_content_03 + 1 + 0 + 0 + 0 + 0 + numeric_003 + numeric_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 3.00 + 0 + 2 + + + + + radiobutton_content_01 + 1 + 0 + 0 + 0 + 0 + radiobutton_001 + radiobutton_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_01 + radiobutton_labelother_01 + 1 + radiobutton_defaultvalue_01 + 1 + 0 + + + + + radiobutton_content_02 + 1 + 0 + 0 + 0 + 0 + radiobutton_002 + radiobutton_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_02 + radiobutton_labelother_02 + 3 + radiobutton_defaultvalue_02 + 1 + 0 + + + + + radiobutton_content_03 + 1 + 0 + 0 + 0 + 0 + radiobutton_003 + radiobutton_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_03 + radiobutton_labelother_03 + 1 + radiobutton_defaultvalue_03 + 1 + 0 + + + + + radiobutton_content_04 + 1 + 0 + 0 + 0 + 0 + radiobutton_004 + radiobutton_extranote_04 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_04 + radiobutton_labelother_04 + 1 + radiobutton_defaultvalue_04 + 1 + 1 + + + + + radiobutton_content_05 + 1 + 0 + 0 + 0 + 0 + radiobutton_005 + radiobutton_extranote_05 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_05 + radiobutton_labelother_05 + 3 + radiobutton_defaultvalue_05 + 1 + 1 + + + + + radiobutton_content_06 + 1 + 0 + 0 + 0 + 0 + radiobutton_006 + radiobutton_extranote_06 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_06 + radiobutton_labelother_06 + 1 + radiobutton_defaultvalue_06 + 1 + 1 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_07 + 1 + 0 + 0 + 0 + 0 + boolean_007 + boolean_extranote_07 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + rate_content_01 + 1 + 0 + 0 + 1 + 0 + rate_001 + rate_extranote_01 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_01 + rate_rates_01 + 3 + rate_defaultvalue_01 + 1 + + 0 + + + + + rate_content_02 + 1 + 0 + 0 + 1 + 0 + rate_002 + rate_extranote_02 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_02 + rate_rates_02 + 1 + rate_defaultvalue_02 + 1 + + 0 + + + + + rate_content_03 + 1 + 0 + 0 + 1 + 0 + rate_003 + rate_extranote_03 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_03 + rate_rates_03 + 1 + rate_defaultvalue_03 + 1 + + 0 + + + + + rate_content_04 + 1 + 0 + 0 + 1 + 0 + rate_004 + rate_extranote_04 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_04 + rate_rates_04 + 1 + rate_defaultvalue_04 + 1 + + 0 + + + + + rate_content_05 + 1 + 0 + 0 + 1 + 0 + rate_005 + rate_extranote_05 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_05 + rate_rates_05 + 1 + rate_defaultvalue_05 + 1 + + 0 + + + + + rate_content_06 + 1 + 0 + 0 + 1 + 0 + rate_006 + rate_extranote_06 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_06 + rate_rates_06 + 3 + rate_defaultvalue_06 + 1 + + 0 + + + + + recurrence_content_01 + 1 + 0 + 0 + 0 + 0 + recurrence_001 + recurrence_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 25009200 + strftime01 + 39600 + 31489200 + + + + + recurrence_content_02 + 1 + 0 + 0 + 0 + 0 + recurrence_002 + recurrence_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 5310000 + strftime01 + 39600 + 15588000 + + + + + recurrence_content_03 + 1 + 0 + 0 + 0 + 0 + recurrence_003 + recurrence_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 3 + 39600 + strftime01 + 5137200 + 23540400 + + + + + select_content_01 + 1 + 0 + 0 + 0 + 0 + select_001 + select_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_01 + select_labelother_01 + 1 + select_defaultvalue_01 + 1 + + + + + select_content_02 + 1 + 0 + 0 + 0 + 0 + select_002 + select_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_02 + select_labelother_02 + 3 + select_defaultvalue_02 + 1 + + + + + select_content_03 + 1 + 0 + 0 + 0 + 0 + select_003 + select_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_03 + select_labelother_03 + 1 + select_defaultvalue_03 + 1 + + + + + shortdate_content_01 + 1 + 0 + 0 + 0 + 0 + shortdate_001 + shortdate_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1238580000 + strftime01 + 1154426400 + 1312192800 + + + + + shortdate_content_02 + 1 + 0 + 0 + 0 + 0 + shortdate_002 + shortdate_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 3 + 39600 + strftime01 + 13082400 + 965124000 + + + + + shortdate_content_03 + 1 + 0 + 0 + 0 + 0 + shortdate_003 + shortdate_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 5137200 + strftime01 + 39600 + 1606820400 + + + + + fieldset_content_04 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_04 + 0 + 1 + 0 + + + 2 + + + + + textarea_content_01 + 1 + 0 + 0 + 0 + 0 + textarea_001 + textarea_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 100 + 500 + + + + + textarea_content_02 + 1 + 0 + 0 + 0 + 0 + textarea_002 + textarea_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 0 + + + + + textarea_content_03 + 1 + 0 + 0 + 0 + 0 + textarea_003 + textarea_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 0 + + + + + textarea_content_04 + 1 + 0 + 0 + 0 + 0 + textarea_004 + textarea_extranote_04 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + textarea_content_05 + 1 + 0 + 0 + 0 + 0 + textarea_005 + textarea_extranote_05 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + textarea_content_06 + 1 + 0 + 0 + 0 + 0 + textarea_006 + textarea_extranote_06 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + time_content_01 + 1 + 0 + 0 + 0 + 0 + time_001 + time_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1 + -3600 + strftime01 + 0 + -60 + + + + + time_content_02 + 1 + 0 + 0 + 0 + 0 + time_002 + time_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 3 + -3600 + strftime01 + 18000 + 63000 + + + + + time_content_03 + 1 + 0 + 0 + 0 + 0 + time_003 + time_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1 + 41400 + strftime01 + 28800 + 57540 + + + + + label_content_02 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_02 + + + + + label_content_03 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_03 + + + + + label_content_04 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_04 + + + diff --git a/template/oneofeachenable/version.php b/template/oneofeachenable/version.php new file mode 100644 index 00000000000..f768820f4c9 --- /dev/null +++ b/template/oneofeachenable/version.php @@ -0,0 +1,30 @@ +. + +/** + * Defines the version of surveyprotemplate_oneofeachenable template subplugin + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2024042200; +$plugin->release = '1.0'; +$plugin->requires = 2024042200; // Requires this Moodle version. +$plugin->component = 'surveyprotemplate_oneofeachenable'; // Full name of the plugin (used for diagnostics). diff --git a/templatemaster/version.php b/templatemaster/version.php index 881a651d9e9..cfdc29df759 100644 --- a/templatemaster/version.php +++ b/templatemaster/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 1965100401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 1965100401; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_templatemaster'; // Full name of the plugin (used for diagnostics). diff --git a/tests/behat/backup_restore.feature b/tests/behat/backup_restore.feature index cfaf2ea6daa..a55454d6a21 100644 --- a/tests/behat/backup_restore.feature +++ b/tests/behat/backup_restore.feature @@ -8,6 +8,8 @@ Feature: Backup and restore a surveypro Given the following "courses" exist: | fullname | shortname | category | numsections | | Course 1 | C1 | 0 | 3 | + And the following config values are set as admin: + | enableasyncbackup | 0 | And I log in as "admin" @javascript @@ -64,7 +66,7 @@ Feature: Backup and restore a surveypro And I should see "What do you usually get for breakfast?" And I should see "When were you born?" And I should see "Please, write down date and time of your last flight to Los Angeles." - And I should see "Please, upload your CV in PDF format" + And I should see "Please, upload your CV in PDF" And I should see "How many people does your family counts?" And I should see "What do you usually get for breakfast?" And I should see "Type the best approximation of π you know" diff --git a/tests/behat/backup_simple.feature b/tests/behat/backup_simple.feature index 21f0549b057..0257faef22b 100644 --- a/tests/behat/backup_simple.feature +++ b/tests/behat/backup_simple.feature @@ -11,6 +11,8 @@ Feature: Backup a surveypro And the following "activities" exist: | activity | course | name | intro | section | | surveypro | C1 | Test surveypro | Surveypro description | 1 | + And the following config values are set as admin: + | enableasyncbackup | 0 | And I log in as "admin" @javascript diff --git a/tests/behat/behat_mod_surveypro.php b/tests/behat/behat_mod_surveypro.php index 1d937f2fa56..3bfaaa0a9cd 100644 --- a/tests/behat/behat_mod_surveypro.php +++ b/tests/behat/behat_mod_surveypro.php @@ -41,6 +41,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class behat_mod_surveypro extends behat_base { + use core_behat_file_helper; /** * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'. @@ -184,12 +185,14 @@ public function i_should_see_items($givennumber, $status) { case 'available': $xpath = "//a[contains(@id,'makereserved')] | //img[contains(@id, 'makereserved')]"; $nodes = $container->findAll('xpath', $xpath); + $rednodes = $container->findAll('xpath', "//img[contains(@title, 'Unreservable')]"); break; case 'searchable': $nodes = $container->findAll('xpath', "//img[contains(@id, 'removefromsearch')]"); break; case 'not searchable': $nodes = $container->findAll('xpath', "//img[contains(@id, 'addtosearch')]"); + $rednodes = $container->findAll('xpath', "//img[contains(@title, 'Unsearchable')]"); break; case 'visible': $nodes = $container->findAll('xpath', "//tr[contains(@id, 'itemslist') and not(contains(@class, 'emptyrow')) and not(contains(@class, 'dimmed'))]"); @@ -200,7 +203,11 @@ public function i_should_see_items($givennumber, $status) { default: throw new Exception('Unrecognised status "' . $status . '."'); } - $tablerows = count($nodes); + if (!isset($rednodes)) { // Red because red is the outline of the icons for unchangeable settings. + $tablerows = count($nodes); + } else { + $tablerows = count($nodes) + count($rednodes); + } if (intval($givennumber) == $tablerows) { return; @@ -208,22 +215,22 @@ public function i_should_see_items($givennumber, $status) { switch ($status) { case 'reserved': - $message = sprintf('%d reserved items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d reserved items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'available': - $message = sprintf('%d available items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d available items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'searchable': - $message = sprintf('%d searchable items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d searchable items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'not searchable': - $message = sprintf('%d unsearchable items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d unsearchable items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'visible': - $message = sprintf('%d visible items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d visible items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'hidden': - $message = sprintf('%d hidden items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d hidden items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; default: throw new Exception('Unrecognised status "' . $status . '."'); @@ -266,7 +273,7 @@ public function surveypro_has_the_following_items($surveyproname, TableNode $dat $record = get_dummy_contents($type, $plugin, $content); // Add the item. - $item = surveypro_get_item($cm, $surveypro, 0, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, 0, $type, $plugin); $item->item_save($record); } } diff --git a/tests/behat/change_of_mind.feature b/tests/behat/change_of_mind.feature index abc8a19cba7..ba374173452 100644 --- a/tests/behat/change_of_mind.feature +++ b/tests/behat/change_of_mind.feature @@ -67,7 +67,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Choose a direction" Then I should see "Question without parent" - And I set the field "id_surveypro_field_select_4" to "South" + And I set the field "id_field_select_4" to "South" And I set the field "Question without parent" to "This should remain" And I press "<< Previous page" @@ -166,17 +166,17 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Which pet do you like more?" And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_2 | 1 | + | id_field_radiobutton_4_2 | 1 | And I press "Next page >>" Then I should not see "Choose a direction" And I set the following fields to these values: - | id_surveypro_field_checkbox_7_1 | 1 | + | id_field_checkbox_7_1 | 1 | And I set the field "Question without parent" to "This should remain" And I press "<< Previous page" And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_3 | 1 | + | id_field_radiobutton_4_3 | 1 | And I press "<< Previous page" And I set the field "Is it true?" to "0" @@ -187,7 +187,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Choose a direction" Then I should see "Question without parent" - And I set the field "id_surveypro_field_select_6" to "South" + And I set the field "id_field_select_6" to "South" And I press "Submit" Then I should not see "Some answers of this response have been found as unverified." @@ -277,7 +277,7 @@ Feature: Delete of no longer allowed answers on user change of mind And I set the field "Write down your email, please" to "su@nowhere.net" And I set the following fields to these values: - | id_surveypro_field_radiobutton_2_1 | 1 | + | id_field_radiobutton_2_1 | 1 | And I press "Next page >>" Then I should see "Was it carved in marble?" Then I should not see "Is it A4 format?" @@ -288,7 +288,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Which artwork did you make?" And I set the following fields to these values: - | id_surveypro_field_radiobutton_2_0 | 1 | + | id_field_radiobutton_2_0 | 1 | And I press "Next page >>" Then I should see "Is it A4 format?" Then I should not see "Was it carved in marble?" diff --git a/tests/behat/duplicate_response.feature b/tests/behat/duplicate_response.feature index b05f8d6dfb3..cea217bac7c 100644 --- a/tests/behat/duplicate_response.feature +++ b/tests/behat/duplicate_response.feature @@ -39,7 +39,7 @@ Feature: Duplicate a response Then I should see "and never modified?" And I press "Continue" - # Edit the duplicatet response + # Edit the duplicated response And I click on "//a[contains(@id,'edit_submission_row_2')]" "xpath_element" And I set the field "Is it true?" to "No" And I press "Submit" diff --git a/tests/behat/item_action.feature b/tests/behat/item_action.feature index 28e6a6f600d..b68b727aafb 100644 --- a/tests/behat/item_action.feature +++ b/tests/behat/item_action.feature @@ -42,36 +42,32 @@ Feature: Execute item actions And I follow "Layout" Then I should see "0" reserved items - # 21 and not 22 available items because pagebreak doesn't have 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 D<0K~$ literal 0 HcmV?d00001 diff --git a/tests/fixtures/usertemplate/MMM_2023103100.xml b/tests/fixtures/usertemplate/MMM_2024032800.xml similarity index 95% rename from tests/fixtures/usertemplate/MMM_2023103100.xml rename to tests/fixtures/usertemplate/MMM_2024032800.xml index 0d8fd9dbc7a..a08891df37f 100644 --- a/tests/fixtures/usertemplate/MMM_2023103100.xml +++ b/tests/fixtures/usertemplate/MMM_2024032800.xml @@ -1,52 +1,46 @@ - + - 0 - 1 - 1 - - <p><img src="@@PLUGINFILE@@/MMM_logo.png" alt="MMM" width="313" height="70" /></p> MMM_logo.png iVBORw0KGgoAAAANSUhEUgAAATkAAABGCAYAAAHA5dPHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUU0NTA5QjhCRTNDMTFFMjg1OTdDMzU0MDYyMjIwNUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUU0NTA5QjlCRTNDMTFFMjg1OTdDMzU0MDYyMjIwNUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTQ1MDlCNkJFM0MxMUUyODU5N0MzNTQwNjIyMjA1QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFRTQ1MDlCN0JFM0MxMUUyODU5N0MzNTQwNjIyMjA1QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PonyXXsAAEPRSURBVHjaxJQxLENB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 1 - 1 - 1 - - - - + 0 0 1 - 0 + 1 + 1 + + + + <p>This is a demo survey to quickly see some features of the items. This not a real survey, question are silly or non complete or meaningless (and, for sure, written in a bad English), but they are examples of what you can get playing with this module.</p> <p>I divided this survey in several pages. Each page is focused on a specific field element.<br />The four format elements are used here and there on needs.</p> <p>Of course you can even submit a survey... but I do not think you will never get a good outcome from its analysis. :-)</p> <p>Enjoy it.</p> 1 0 + 0 + 1 + 0 + + 1 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -60,19 +54,19 @@ 0 age_001 This is a mandatory question. You MUST provide an answer. + 0 + 0 + 0 + + 2 -1 -570715200 1004616000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -86,19 +80,19 @@ 0 age_002 This is an optional question. You CAN provide an answer but you can also check the "No answer" box. + 0 + 0 + 0 + + 2 -1 -2148552000 -2119608000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -112,19 +106,19 @@ 0 age_003 Here the default has been set to 72 years and 7 months. You are not forced to read this question because it was already answered. You can fly. + 0 + 0 + 0 + + 1 -2130235200 -2148552000 -2119608000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -138,25 +132,24 @@ 0 age_004 Here the default is "No answer" and the question can not be mandatory. Here you are not forced to read this question because it was already answered. You can fly too. + 0 + 0 + 0 + + 3 -2148552000 -2119608000 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>user ID</p> 1 0 @@ -164,24 +157,23 @@ III autofill_005 This type of field was added to allow relations between output of different surveys + 0 + 0 + 0 + + 0 userid - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -190,19 +182,19 @@ 4.1 boolean_001 First instance of boolean question using radio buttons as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -211,19 +203,19 @@ 4.2 boolean_002 The same boolean question using drop down menu as user interface and "yes" as default + 0 + 0 + 0 + + 1 1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -232,19 +224,19 @@ 4.3 boolean_003 The same boolean question using drop down menu as user interface and "No answer" as default + 0 + 0 + 0 + + 3 1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -253,19 +245,19 @@ 4.4 boolean_004 Still boolean question but using horizontal radio button menu as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -274,26 +266,25 @@ 4.5 boolean_005 Still boolean question but using vertical radio button menu as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -302,6 +293,11 @@ 5 0 checkbox_001 + 0 + 0 + 0 + + milk coffee butter @@ -315,13 +311,8 @@ milk 1 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -330,6 +321,11 @@ milk 5 0 checkbox_002 + 0 + 0 + 0 + + 1::milk 2::coffee 3::butter @@ -345,20 +341,14 @@ Apple juice 0 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>When did you get your last car?</p> 1 0 @@ -366,19 +356,19 @@ Apple juice 0 0 shortdate_001 + 0 + 1 + 0 + + 2 strftime01 946728000 1378036800 - + - 0 - 0 - 0 - - <p>When did you get your last car?</p> 1 0 @@ -386,26 +376,25 @@ Apple juice 0 1 shortdate_002 + 0 + 0 + 0 + + 3 strftime01 43200 1380628800 - + 0 - 0 0 - + - 0 - 0 - 0 - - <p>Date of birth</p> 1 0 @@ -413,6 +402,11 @@ Apple juice 0 0 date_001 + 0 + 0 + 0 + + 2 43200 strftime01 @@ -420,13 +414,8 @@ Apple juice 1262347200 - + - 0 - 0 - 0 - - <p>Date of birth</p> 1 0 @@ -434,6 +423,11 @@ Apple juice 0 0 date_002 + 0 + 0 + 0 + + 3 43200 strftime01 @@ -441,20 +435,14 @@ Apple juice 1262347200 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>In which day and at what time do you remember the event?</p> 1 0 @@ -462,6 +450,11 @@ Apple juice 0 0 datetime_001 + 0 + 0 + 0 + + 1 2 0 @@ -470,20 +463,14 @@ Apple juice 1609459140 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Please, attach your Curriculum Vitae.</p> 1 0 @@ -492,18 +479,17 @@ Apple juice two.one fileupload_001 only one file in a the format you prefer + 0 + 0 + + 1 0 * - + - 0 - 0 - 0 - - <p>Please, attach your Curriculum Vitae.</p> 1 0 @@ -512,25 +498,23 @@ Apple juice two.two fileupload_002 only one file in pdf or compressed in zip format + 0 + 0 + + 1 0 .pdf, .zip - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>How many days do you foreseen for your Easter holidays?</p> 1 0 @@ -538,19 +522,19 @@ Apple juice 0 1 integer_001 + 0 + 0 + 0 + + 3 0 0 13 - + - 0 - 0 - 0 - - <p>How many days do you foreseen for your Easter holidays?</p> 1 1 @@ -558,26 +542,25 @@ Apple juice 0 1 integer_002 + 0 + 0 + 0 + + 2 -1 0 13 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -585,6 +568,11 @@ Apple juice 0 0 multiselect_001 + 0 + 0 + 0 + + milk sugar jam @@ -598,20 +586,14 @@ chocolate 4 - + 1 - 0 0 - + - 1 - 1 - 0 - - <p>Which is the mean room temperature you prefer?</p> 1 0 @@ -619,33 +601,37 @@ chocolate 0 0 numeric_001 - 25 + 1 + 1 + 0 + + + 25.0 0 - 12 - 30 + 12.0000000000 + 30.0000000000 1 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 radiobutton_001 + 0 + 1 + 0 + + Sea Mountain Hill @@ -656,19 +642,19 @@ Lake 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 radiobutton_002 + 0 + 0 + 0 + + Sea Mountain Hill @@ -680,19 +666,19 @@ Lake 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 0 0 radiobutton_003 + 0 + 0 + 0 + + Sea Mountain Hill @@ -704,20 +690,14 @@ Lake 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -725,6 +705,10 @@ Lake 1 1 rate_001 + 0 + 0 + + Italian English Spanish @@ -742,13 +726,8 @@ Optimum 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 @@ -756,6 +735,10 @@ Optimum 1 1 rate_002 + 0 + 0 + + Italian English Spanish @@ -778,13 +761,8 @@ Good 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -792,6 +770,10 @@ Good 1 1 rate_003 + 0 + 0 + + Italian English Spanish @@ -809,20 +791,14 @@ Optimum 0 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>When do you usually celebrate your name-day?</p> 1 0 @@ -830,6 +806,11 @@ Optimum 0 0 recurrence_001 + 0 + 1 + 0 + + 2 43200 strftime01 @@ -837,26 +818,25 @@ Optimum 31492800 - + 1 - 0 0 - + - 1 - 1 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 select_001 + 1 + 1 + 0 + + sea mountain lake @@ -866,20 +846,14 @@ hill 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Write a short description of yourself.</p> 1 0 @@ -887,21 +861,21 @@ hill 0 0 textarea_001 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 1000 - + - 0 - 0 - 0 - - <p>Write a short description of yourself.</p> 1 0 @@ -909,28 +883,27 @@ hill 0 0 textarea_002 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 1000 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>At what time do you usually get up in the morning in a working day?</p> 1 0 @@ -938,6 +911,11 @@ hill 0 0 time_001 + 0 + 1 + 0 + + 1 2 0 @@ -946,13 +924,8 @@ hill 35940 - + - 0 - 0 - 0 - - <p>At what time do you usually get up in the morning in a working day?</p> 1 0 @@ -960,6 +933,11 @@ hill 0 0 time_002 + 0 + 0 + 0 + + 1 2 0 @@ -968,20 +946,14 @@ hill 14340 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number.</p> 1 0 @@ -989,19 +961,19 @@ hill 0 0 character_001 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + - 0 - 0 - 0 - - <p>Enter your email address.</p> 1 0 @@ -1009,18 +981,18 @@ hill 0 0 character_002 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site.</p> 1 0 @@ -1028,54 +1000,59 @@ hill 0 0 character_003 + 0 + 0 + 0 + + 1 PATTERN_URL 0 - + - 1 - 0 + 0 0 - + - 0 - 0 - 0 - - <p>Do you have the driving licence?</p> 1 1 0 0 boolean_006 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + With driving licence 0 - 0 0 - - 60 - 1 - - With driving licence 2 - + + <p>Please specify the category?</p> + 1 + 0 + 1 + 0 + select_002 0 0 0 @@ -1085,12 +1062,6 @@ hill - <p>Please specify the category?</p> - 1 - 0 - 1 - 0 - select_002 A::for motorcycles B::for cars C::for tracks @@ -1098,23 +1069,24 @@ C::for tracks 0 - + + Without driving licence 0 - 0 0 - - 60 - 0 - - Without driving licence 2 - + + <p>When did you plan to get it?</p> + 1 + 0 + 1 + 0 + select_003 0 0 0 @@ -1124,12 +1096,6 @@ C::for tracks - <p>When did you plan to get it?</p> - 1 - 0 - 1 - 0 - select_003 soon with the time when I will be allowed by the law (I am still not 18) diff --git a/tests/fixtures/usertemplate/item_action_test.xml b/tests/fixtures/usertemplate/item_action.xml similarity index 92% rename from tests/fixtures/usertemplate/item_action_test.xml rename to tests/fixtures/usertemplate/item_action.xml index 2a9267d5e02..78afbc87b4d 100644 --- a/tests/fixtures/usertemplate/item_action_test.xml +++ b/tests/fixtures/usertemplate/item_action.xml @@ -1,25 +1,20 @@ - + + <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4></h4><h4>First part of the test</h4> + 1 + 0 0 0 0 - <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4></h4><h4>First part of the test</h4> - 1 - 0 0 - + - 0 - 0 - 0 - - Very first parent<br /> 1 1 @@ -27,6 +22,11 @@ 0 1 veryfirstparent + 0 + 0 + 0 + + 0::Ambiguous answer 1::Positive answer 2::Negative answer @@ -35,8 +35,15 @@ 1 - + + <p>Second generation, first parent question<br /></p> + 1 + 1 + 1 + 0 + 1.a + vfp_a 0 0 0 @@ -46,21 +53,22 @@ - <p>Second generation, first parent question<br /></p> - 1 - 1 - 1 - 0 - 1.a - vfp_a 2 1 strfbool01 - + + <p>Third generation, first cousin<br /></p> + 1 + 1 + 2 + 0 + 1.a.1 + 0 + vfp_a_one 0 0 0 @@ -70,14 +78,6 @@ - <p>Third generation, first cousin<br /></p> - 1 - 1 - 2 - 0 - 1.a.1 - 0 - vfp_a_one 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -88,8 +88,15 @@ 0 - + + <p>Fourth generation first brother question<br /></p> + 1 + 1 + 3 + 0 + 1.a.1.first + vfp_a_one_1st 0 0 0 @@ -99,13 +106,6 @@ - <p>Fourth generation first brother question<br /></p> - 1 - 1 - 3 - 0 - 1.a.1.first - vfp_a_one_1st 4thpositive::positive 4thneutral::neutral 4thnegative::negative @@ -114,8 +114,15 @@ 0 - + + <p>Fourth generation second brother question<br /></p> + 1 + 1 + 3 + 0 + 1.a.1.second + vfp_a_one_2nd 0 0 0 @@ -125,13 +132,6 @@ - <p>Fourth generation second brother question<br /></p> - 1 - 1 - 3 - 0 - 1.a.1.second - vfp_a_one_2nd 4thpositive::positive 4thneutral::neutral 4thnegative::negative @@ -140,8 +140,16 @@ 0 - + + <p>Second generation, second parent question<br /></p> + 1 + 1 + 1 + 0 + 1.b + 0 + vfp_b 0 0 0 @@ -151,14 +159,6 @@ - <p>Second generation, second parent question<br /></p> - 1 - 1 - 1 - 0 - 1.b - 0 - vfp_b 2ndpositive::positive 2ndneutral::neutral 2ndnegative::negative @@ -169,8 +169,15 @@ 0 - + + Third generation, second cousin<br /> + 1 + 1 + 2 + 0 + 1.b.1 + vfp_b_one 0 0 0 @@ -180,13 +187,6 @@ - Third generation, second cousin<br /> - 1 - 1 - 2 - 0 - 1.b.1 - vfp_b_one 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -195,8 +195,15 @@ 1 - + + <p>Fourth generation unique question<br /></p> + 1 + 1 + 3 + 0 + 1.b.1.a + vfp_b_one_1st 0 0 0 @@ -206,13 +213,6 @@ - <p>Fourth generation unique question<br /></p> - 1 - 1 - 3 - 0 - 1.b.1.a - vfp_b_one_1st 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -221,32 +221,32 @@ 0 - + + <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4>Second part of the test<br /></h4> + 1 + 0 0 0 0 - <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4>Second part of the test<br /></h4> - 1 - 0 0 - + - 0 - 0 - 0 - - <div>Simple parent</div> 1 1 0 0 first + 0 + 0 + 0 + + 0::Ambiguous answer 1::Positive answer 2::Negative answer @@ -255,8 +255,14 @@ 1 - + + <p>Second generation, first question<br /></p> + 1 + 1 + 1 + 0 + firstone 0 0 0 @@ -266,20 +272,21 @@ - <p>Second generation, first question<br /></p> - 1 - 1 - 1 - 0 - firstone 2 1 strfbool01 - + + <p>Second generation, second question<br /></p> + 1 + 1 + 1 + 0 + 0 + firsttwo 0 0 0 @@ -289,13 +296,6 @@ - <p>Second generation, second question<br /></p> - 1 - 1 - 1 - 0 - 0 - firsttwo 22positive::positive 22neutral::neutral 22negative::negative @@ -306,8 +306,14 @@ 0 - + + <p>Second generation, third question<br /></p> + 1 + 1 + 1 + 0 + firstthree 0 0 0 @@ -317,12 +323,6 @@ - <p>Second generation, third question<br /></p> - 1 - 1 - 1 - 0 - firstthree 23positive::positive 23neutral::neutral 23negative::negative diff --git a/tests/fixtures/usertemplate/parent-child_2023103100.xml b/tests/fixtures/usertemplate/parent-child_2024032800.xml similarity index 91% rename from tests/fixtures/usertemplate/parent-child_2023103100.xml rename to tests/fixtures/usertemplate/parent-child_2024032800.xml index 89c44566325..5b2a51efbd3 100644 --- a/tests/fixtures/usertemplate/parent-child_2023103100.xml +++ b/tests/fixtures/usertemplate/parent-child_2024032800.xml @@ -1,12 +1,7 @@ - + - 0 - 0 - 0 - - <p>Before starting I need to let you know few details at general level.</p> <p>In a parent child relation almost each item can be a child while only few items can be parent.</p> <p>Almost each field and each formats (with exception of autofill and page-break) can be child. On the contrary, only "boolean", "checkbox", "integer", "multiselect", "radio button" and "select" can be parent.</p> @@ -27,16 +22,16 @@ <p>A closing note: of course, you can not evaluate the presence of a child item in "second" pages when you are in preview mode because data submitted by items in the "first" page are not saved to database. In preview mode case, each child will be shown in "second" pages.</p> 1 0 - 1 - - - - 0 0 0 - + + 1 + + + + Example with boolean item: Is this true or false?</p> 1 0 @@ -44,30 +39,25 @@ 0 1 boolean_001 + 0 + 0 + 0 + + 2 -1 strfbool01 - + 1 - 0 0 - + - 0 - 0 - 0 - - 2 - 1 - - - Enter you name<br>(Just a detail: I marked this question as mandatory question. The attribute is actually considered ONLY if the parent item allows his child otherwise the attribute is neglected). 1 0 @@ -77,22 +67,22 @@ 0 character_001 This item is allowed if the answer to its parent is TRUE - 1 - PATTERN_FREE - 0 - - - - 0 0 0 2 - 0 + 1 - + + 1 + PATTERN_FREE + 0 + + + + Number of friends you would like to invite to your next birthday party. 1 0 @@ -102,32 +92,36 @@ 0 integer_001 This item is allowed if the answer to its parent is FALSE + 0 + 0 + 0 + + 2 + 0 + + + 2 -1 0 105 - + + As you can see, by answering "No answer" to the parent item you get disabled the first such as the second child too. + 1 + 0 0 0 0 - As you can see, by answering "No answer" to the parent item you get disabled the first such as the second child too. - 1 - 0 0 - + - 0 - 0 - 0 - - Example with checkbox item: What do you always want to find on your desk in the office? 1 0 @@ -136,6 +130,11 @@ 2 0 checkbox_001 + 0 + 0 + 0 + + rubber pen pencil @@ -147,24 +146,14 @@ A4 paper 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 7 - 1;1;1;0 - - - Write something. 1 0 @@ -174,22 +163,22 @@ A4 paper 0 character_002 child item displayed only if 'rubber & pen & pencil' is answered to the parent item - 1 - PATTERN_FREE - 0 - - - - 0 0 0 7 - 0;1;0;0 + 1;1;1;0 - + + 1 + PATTERN_FREE + 0 + + + + Please describe the best motor you have ever seen. 1 0 @@ -199,20 +188,24 @@ A4 paper 0 textarea_001 This item should be enabled if the answer to the parent item is "pen" ONLY but this is a missing funtionality as described in MDL-25067 + 0 + 0 + 0 + + 7 + 0;1;0;0 + + + + 0 1 10 60 - 0 0 - + - 0 - 0 - 0 - - Example with numeric (small integer) item: Enter an integer value. 1 0 @@ -221,30 +214,25 @@ A4 paper 3 0 integer_002 + 0 + 0 + 0 + + 2 -1 0 30 - + 1 - 0 0 - + - 0 - 0 - 0 - - 11 - 11 - - - Enter you name. 1 0 @@ -254,22 +242,22 @@ A4 paper 0 character_003 This item is enabled if the answer to the parent item is 11 - 1 - PATTERN_FREE - 0 - - - - 0 0 0 11 - 22 + 11 - + + 1 + PATTERN_FREE + 0 + + + + Number of friends you would like to invite to your next birthday party. 1 0 @@ -279,19 +267,23 @@ A4 paper 0 integer_003 This item is enabled if the answer to the parent item is 22 + 0 + 0 + 0 + + 11 + 22 + + + 2 -1 0 105 - + - 0 - 0 - 0 - - Example with multiselect item: What do you eat for breakfast? (click or shift-click to change the selection). 1 0 @@ -300,6 +292,11 @@ A4 paper 4 0 multiselect_001 + 0 + 0 + 0 + + b::bread m::milk j::jam @@ -314,24 +311,14 @@ ham 4 - + 1 - 0 0 - + - 0 - 0 - 0 - - 15 - 3;0 - - - You preferred room temperature? 1 0 @@ -341,22 +328,22 @@ ham 0 numeric_001 This item is allowed when the answer to its parent is "ham bread" - 27 - 0 - 2 - - - - 0 0 0 15 - 2;3;4 + 3;0 - + + 27.00 + 0 + 2 + + + + Enter a full date. 1 0 @@ -366,6 +353,15 @@ ham 0 date_001 This item is allowed when the answer to its parent is "jam ham tomatoes" + 0 + 0 + 0 + + 15 + 2;3;4 + + + 2 43200 strftime01 @@ -373,13 +369,8 @@ ham 1609416000 - + - 0 - 0 - 0 - - Example with radio button item: which countryside do you like more for your summer holidays? 1 0 @@ -387,6 +378,11 @@ ham 0 5 radiobutton_001 + 0 + 0 + 0 + + Mountain Hill Sea @@ -398,24 +394,14 @@ City 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 19 - 3 - - - When did you buy your last car? 1 0 @@ -425,23 +411,23 @@ City 0 shortdate_001 This item is allowed when the answer to its parent is "Lake" - 2 - strftime01 - 43200 - 1606824000 - - - - 0 0 0 19 - 0 + 3 - + + 2 + strftime01 + 43200 + 1606824000 + + + + Order the following languages as you better can make use of them. 1 0 @@ -451,6 +437,14 @@ City 0 rate_001 This item is allowed when the answer to its parent is "Mountain" + 0 + 0 + + 19 + 0 + + + English Greek Spanish @@ -471,13 +465,8 @@ bad 0 - + - 0 - 0 - 0 - - Example with select item: Indicate your preferred direction. 1 0 @@ -485,6 +474,11 @@ bad 0 6 select_001 + 0 + 0 + 0 + + top bottom right @@ -493,24 +487,14 @@ left 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 23 - 1 - - - How old were you when you first travelled alone? 1 0 @@ -520,23 +504,23 @@ left 0 age_001 This item is allowed If your answer to previous question was "bottom" - 2 - -1 - -2635200 - 3339835200 - - - - 0 0 0 23 - 0 + 1 - + + 2 + -1 + -2635200 + 3339835200 + + + + Please attach your curriculum vitae. 1 0 @@ -545,6 +529,14 @@ left 6.b fileupload_001 This item is allowed only by answering "Top" to its parent. I asked for the option to disable it in MDL-28194. That issue is still open but, in spite of this, the item can be disabled. + 0 + 0 + + 23 + 0 + + + 1 0 * diff --git a/tests/generator_test.php b/tests/generator_test.php index 7e9e62f37f4..71cd1d64231 100644 --- a/tests/generator_test.php +++ b/tests/generator_test.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace mod_surveypro; + /** * PHPUnit data generator test. * @@ -29,14 +31,14 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class generator_test extends advanced_testcase { +final class generator_test extends \advanced_testcase { /** * Test_create_instance. * * @return void */ - public function test_create_instance() { + public function test_create_instance(): void { global $DB; $this->resetAfterTest(); @@ -61,7 +63,7 @@ public function test_create_instance() { * * @return void */ - public function test_apply_mastertemplate() { + public function test_apply_mastertemplate(): void { global $DB; $this->resetAfterTest(); diff --git a/tests/lib_test.php b/tests/lib_test.php index 82db4c79428..a776a5b6e36 100644 --- a/tests/lib_test.php +++ b/tests/lib_test.php @@ -18,6 +18,11 @@ use advanced_testcase; +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/mod/surveypro/lib.php'); + /** * The class to verify all the lib.php global functions do work as expected. * @@ -25,7 +30,7 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class lib_test extends advanced_testcase { +final class lib_test extends advanced_testcase { /** * surveypro_cutdownstring provider @@ -35,9 +40,9 @@ class lib_test extends advanced_testcase { public function surveypro_cutdownstring_provider(): array { return [ 'plain_short_string' => ['Hello world!', 60, 'Hello world!'], - 'utf8_short_string' => ['Hello 🌍 !', 60, 'Hello 🌍 !'], + 'utf8_short_string' => ['Hello 🌍 !', 60, 'Hello 🌍 !'], 'plain_cut_string' => ['Hello world!', 10, 'Hello w...'], - 'utf8_cut_string' => ['Hello 🌍 !', 9, 'Hello 🌍 !'], + 'utf8_cut_string' => ['Hello 🌍 !', 9, 'Hello 🌍 !'], ]; } @@ -50,7 +55,7 @@ public function surveypro_cutdownstring_provider(): array { * @param int $maxlength The length passed * @param string $expected The expected result */ - public function test_surveypro_cutdownstring($plainstring, $maxlength, $expected) { + public function test_surveypro_cutdownstring($plainstring, $maxlength, $expected): void { // Let's test that surveypro_cutdownstring() works as expected. $this->assertSame($expected, surveypro_cutdownstring($plainstring, $maxlength)); } @@ -116,7 +121,7 @@ public function surveypro_pre_process_checkboxes_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_surveypro_pre_process_checkboxes($userinput, $expected) { + public function test_surveypro_pre_process_checkboxes($userinput, $expected): void { // Let's test that surveypro_pre_process_checkboxes() works as expected. surveypro_pre_process_checkboxes($userinput); $this->assertEquals($expected, $userinput); diff --git a/tests/mastertemplate_test.php b/tests/mastertemplate_test.php index 3dbc2a1d643..a6ba95e9a24 100644 --- a/tests/mastertemplate_test.php +++ b/tests/mastertemplate_test.php @@ -26,7 +26,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \mod_surveypro\mastertemplate */ -class mastertemplate_test extends advanced_testcase { +final class mastertemplate_test extends advanced_testcase { /** * Data provider for surveyprotemplate_get_plugin_name_provider() @@ -51,7 +51,7 @@ public function surveyprotemplate_get_plugin_name_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_surveyprotemplate_get_plugin_name($userinput, $expected) { + public function test_surveyprotemplate_get_plugin_name($userinput, $expected): void { $this->resetAfterTest(); $this->setAdminUser(); diff --git a/tests/separator_test.php b/tests/separator_test.php index a09156ebed5..a3c82f3f649 100644 --- a/tests/separator_test.php +++ b/tests/separator_test.php @@ -32,7 +32,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \surveyprofield_radiobutton */ -class separator_test extends advanced_testcase { +final class separator_test extends advanced_testcase { /** * Data provider for test_userform_get_separator() @@ -53,90 +53,84 @@ class separator_test extends advanced_testcase { public function userform_get_separator_provider(): array { $userinput = []; $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
']; $test01 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', '
']; $test02 = [$userinput, $expected]; // Test03: defaultoption = SURVEYPRO_NOANSWERDEFAULT is not compatible with required = 1 $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', ' ']; $test04 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', '
', ' ']; $test05 = [$userinput, $expected]; // Test06: defaultoption = SURVEYPRO_NOANSWERDEFAULT is not compatible with required = 1 $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; $expected = ['
']; $test07 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', '
']; $test08 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_NOANSWERDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; $expected = ['
']; $test09 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', ' ', '
']; $test10 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', '
', ' ', '
']; $test11 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_NOANSWERDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', ' ', '
']; $test12 = [$userinput, $expected]; return [ - $test01, - $test02, - $test04, - $test05, - $test07, - $test08, - $test09, - $test10, - $test11, - $test12, + $test01, $test02, + $test04, $test05, + $test07, $test08, $test09, + $test10, $test11, $test12, ]; } @@ -147,7 +141,7 @@ public function userform_get_separator_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_userform_get_separator($userinput, $expected) { + public function test_userform_get_separator($userinput, $expected): void { $this->resetAfterTest(); $this->setAdminUser(); @@ -161,9 +155,9 @@ public function test_userform_get_separator($userinput, $expected) { // Define parameters. $itemman->set_defaultoption($userinput['defaultoption']); // Needed to define $invitation. + $itemman->set_options($userinput['options']); // Needed to define $labels. $itemman->set_labelother($userinput['labelother']); // Needed to define $addother. $itemman->set_required($userinput['required']); // Needed to define $mandatory. - $itemman->set_options($userinput['options']); // Needed to define $labels. $returned = $itemman->userform_get_separator(); $this->assertEquals($expected, $returned); diff --git a/tests/setup_test.php b/tests/setup_test.php index 7949ca11ce0..c263b71506f 100644 --- a/tests/setup_test.php +++ b/tests/setup_test.php @@ -29,14 +29,14 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class setup_test extends advanced_testcase { +final class setup_test extends advanced_testcase { /** * Test that all the global settings are stored properly and with expected defaults. * * Any new setting and/or change of default will require a change here. */ - public function test_global_config_defaults() { + public function test_global_config_defaults(): void { $this->assertCount(0, (array)get_config('surveypro')); $this->assertCount(4, (array)get_config('mod_surveypro')); diff --git a/tools.php b/tools.php index 1f3ae31dd92..8a5a8d0c466 100644 --- a/tools.php +++ b/tools.php @@ -37,8 +37,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('tools'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); diff --git a/utemplates.php b/utemplates.php index 075913be640..4193873fe3a 100644 --- a/utemplates.php +++ b/utemplates.php @@ -41,8 +41,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('utemplates'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); @@ -255,25 +255,46 @@ $applyman->prevent_direct_user_input(); $utemplates = $applyman->get_utemplates_items(); - // Begin of: define $applyutemplate return url. - $formurl = new \moodle_url('/mod/surveypro/utemplates.php', ['s' => $cm->instance, 'section' => 'apply']); - // End of: define $applyutemplate return url. - - // Begin of: prepare params for the form. - $formparams = new \stdClass(); - $formparams->utemplates = $utemplates; - $formparams->inlineform = false; - $applyutemplate = new utemplate_applyform($formurl, $formparams); - // End of: prepare params for the form. - - // Begin of: manage form submission. - if ($applyman->formdata = $applyutemplate->get_data()) { - // Here I don't need to execute validate_xml because xml was validated at upload time - // Here I only need to verfy that plugin versions still match - // $applyman->check_items_versions(); - $applyman->apply_template(); + if ($action != SURVEYPRO_APPLYUTEMPLATE) { + // Begin of: define $applyutemplate return url. + $formurl = new \moodle_url('/mod/surveypro/utemplates.php', ['s' => $cm->instance, 'section' => 'apply']); + // End of: define $applyutemplate return url. + + // Begin of: prepare params for the form. + $formparams = new \stdClass(); + $formparams->utemplates = $utemplates; + $formparams->inlineform = false; + $applyutemplate = new utemplate_applyform($formurl, $formparams); + // End of: prepare params for the form. + + // Begin of: manage form submission. + if ($applyman->formdata = $applyutemplate->get_data()) { + // Bloody scenario. + // I upload a usertemplate on monday. + // I update surveypro on tuesday. This may make monday's usertemplates obsolete. + // I arrive here and I try to apply an OBSOLETE usertemplate. + // Somebody has to tell me I can not carry on. + // $applyman->check_items_versions(); + $applyman->lastminute_template_check(); + $xmlvalidationoutcome = $applyman->get_xmlvalidationoutcome(); + if (!isset($xmlvalidationoutcome->key)) { + $applyman->apply_template(); + } + } + // End of: manage form submission. + } else { + if ($confirm == SURVEYPRO_CONFIRMED_YES) { + $applyman->lastminute_template_check(); + $xmlvalidationoutcome = $applyman->get_xmlvalidationoutcome(); + if (!isset($xmlvalidationoutcome->key)) { + $applyman->apply_template(); + + $paramurl = ['s' => $this->cm->instance, 'section' => 'itemslist']; + $returnurl = new \moodle_url('/mod/surveypro/layout.php', $paramurl); + redirect($returnurl); + } + } } - // End of: manage form submission. // Set $PAGE params. $paramurl = ['s' => $surveypro->id, 'area' => 'utemplates', 'section' => 'apply']; @@ -293,7 +314,10 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_utemplates_action_bar(); - $applyman->friendly_stop(); + $applyman->lastminute_stop(); + if ($action == SURVEYPRO_APPLYUTEMPLATE) { + $applyman->ask_for_confirmation(); + } $riskyediting = ($surveypro->riskyeditdeadline > time()); $utilitylayoutman = new utility_layout($cm, $surveypro); diff --git a/version.php b/version.php index 5e3d0b2e9be..462c1ecad64 100644 --- a/version.php +++ b/version.php @@ -26,6 +26,6 @@ $plugin->component = 'mod_surveypro'; $plugin->maturity = MATURITY_BETA; -$plugin->version = 2024022700; -$plugin->release = '4.4dev'; -$plugin->requires = 2023100900; +$plugin->version = 2024062403; +$plugin->release = '4.4'; +$plugin->requires = 2024042200; diff --git a/view.php b/view.php index 82f0db0ae74..3c0a4f52014 100644 --- a/view.php +++ b/view.php @@ -24,28 +24,27 @@ use mod_surveypro\utility_layout; use mod_surveypro\utility_page; -use mod_surveypro\utility_mform; use mod_surveypro\view_cover; -use mod_surveypro\view_submissionlist; -use mod_surveypro\view_submissionform; -use mod_surveypro\view_submissionsearch; +use mod_surveypro\view_responselist; +use mod_surveypro\view_responsesubmit; +use mod_surveypro\view_responsesearch; -use mod_surveypro\local\form\userform; -use mod_surveypro\local\form\usersearch; +use mod_surveypro\local\form\response_submitform; +use mod_surveypro\local\form\response_searchform; require_once(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/lib.php'); $defaultsection = surveypro_get_defaults_section_per_area('surveypro'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); // Course_module id. +$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); // Verify I used correct names all along the module code. -$validsections = ['cover', 'submissionslist', 'submissionform', 'searchsubmissions']; +$validsections = ['cover', 'submissionslist', 'responsesubmit', 'responsesearch']; if (!in_array($section, $validsections)) { $message = 'The section param \''.$section.'\' is invalid.'; debugging('Error at line '.__LINE__.' of file '.__FILE__.'. '.$message , DEBUG_DEVELOPER); @@ -138,7 +137,7 @@ } // Calculations. - $submissionlistman = new view_submissionlist($cm, $context, $surveypro); + $submissionlistman = new view_responselist($cm, $context, $surveypro); $submissionlistman->setup($submissionid, $action, $mode, $confirm, $searchquery); if ($action == SURVEYPRO_RESPONSETOPDF) { @@ -178,13 +177,13 @@ } } -// MARK submissionform. +// MARK responsesubmit. // This section serves the page to... // - add a new submission [$mode = SURVEYPRO_NEWRESPONSEMODE]; // - edit existing submissions [$mode = SURVEYPRO_EDITMODE]; // - view in readonly mode [$mode = SURVEYPRO_READONLYMODE]; // - preview submission form [$mode = SURVEYPRO_PREVIEWMODE]; -if ($section == 'submissionform') { +if ($section == 'responsesubmit') { // Get additional specific params. $submissionid = optional_param('submissionid', 0, PARAM_INT); $formpage = optional_param('formpage', 1, PARAM_INT); // Form page number. @@ -193,16 +192,14 @@ $overflowpage = optional_param('overflowpage', 0, PARAM_INT); // Went the user to a overflow page? // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - - $submissionformman = new view_submissionform($cm, $context, $surveypro); - $submissionformman->setup($submissionid, $formpage, $mode); + $responsesubmitman = new view_responsesubmit($cm, $context, $surveypro); + $responsesubmitman->setup($submissionid, $formpage, $mode); $utilitylayoutman = new utility_layout($cm, $surveypro); $utilitylayoutman->add_custom_css(); - // Begin of: define $user_form return url. - $paramurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionform']; + // Begin of: define responsesubmit return url. + $paramurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'responsesubmit']; $formurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); // End of: define $user_form return url. @@ -212,80 +209,87 @@ $formparams->surveypro = $surveypro; $formparams->submissionid = $submissionid; $formparams->mode = $mode; - $formparams->userformpagecount = $submissionformman->get_userformpagecount(); + $formparams->userformpagecount = $responsesubmitman->get_userformpagecount(); $formparams->canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $context); - $formparams->userfirstpage = $submissionformman->get_userfirstpage(); // The user first page - $formparams->userlastpage = $submissionformman->get_userlastpage(); // The user last page + $formparams->userfirstpage = $responsesubmitman->get_userfirstpage(); // The user first page + $formparams->userlastpage = $responsesubmitman->get_userlastpage(); // The user last page $formparams->overflowpage = $overflowpage; // Went the user to a overflow page? // End of: prepare params for the form. if ($begin == 1) { - $submissionformman->next_not_empty_page(true, 0); // True means direction = right. - $nextpage = $submissionformman->get_nextpage(); // The page of the form to select subset of fields - $submissionformman->set_formpage($nextpage); + $responsesubmitman->next_not_empty_page(true, 0); // True means direction = right. + $nextpage = $responsesubmitman->get_nextpage(); // The page of the form to select subset of fields + $responsesubmitman->set_formpage($nextpage); } - $formparams->formpage = $submissionformman->get_formpage(); // The page of the form to select subset of fields + $formparams->formpage = $responsesubmitman->get_formpage(); // The page of the form to select subset of fields // End of: prepare params for the form. $editable = ($mode == SURVEYPRO_READONLYMODE) ? false : true; - $userform = new userform($formurl, $formparams, 'post', '', ['id' => 'userentry'], $editable); + $attributes = ['id' => 'userentry', 'class' => 'narrowlines']; + $userform = new response_submitform($formurl, $formparams, 'post', '', $attributes, $editable); // Begin of: manage form submission. if ($userform->is_cancelled()) { + // If the submission was canceled + // and the surveypro_submission record (1) exists and (2) has not the creation time, add it. + if ($DB->record_exists('surveypro_submission', ['id' => $submissionid, 'timecreated' => null])) { + $timenow = time(); + $DB->set_field('surveypro_submission', 'timecreated', $timenow, ['id' => $submissionid]); + } $localparamurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionslist']; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $localparamurl); redirect($redirecturl, get_string('usercanceled', 'mod_surveypro')); } - if ($submissionformman->formdata = $userform->get_data()) { - $submissionformman->save_user_data(); // SAVE SAVE SAVE SAVE. + if ($responsesubmitman->formdata = $userform->get_data()) { + $responsesubmitman->save_user_response(); // SAVE SAVE SAVE SAVE. // If "pause" button has been pressed, redirect. - $pausebutton = isset($submissionformman->formdata->pausebutton); + $pausebutton = isset($responsesubmitman->formdata->pausebutton); if ($pausebutton) { $localparamurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionslist']; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $localparamurl); redirect($redirecturl); // Go somewhere. } - $paramurl['submissionid'] = $submissionformman->get_submissionid(); - $paramurl['section'] = 'submissionform'; + $paramurl['submissionid'] = $responsesubmitman->get_submissionid(); + $paramurl['section'] = 'responsesubmit'; // If "previous" button has been pressed, redirect. - $prevbutton = isset($submissionformman->formdata->prevbutton); + $prevbutton = isset($responsesubmitman->formdata->prevbutton); if ($prevbutton) { - $submissionformman->next_not_empty_page(false); - $paramurl['formpage'] = $submissionformman->get_nextpage(); - $paramurl['overflowpage'] = $submissionformman->get_overflowpage(); + $responsesubmitman->next_not_empty_page(false); + $paramurl['formpage'] = $responsesubmitman->get_nextpage(); + $paramurl['overflowpage'] = $responsesubmitman->get_overflowpage(); $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); // Redirect to the first non empty page. } // If "next" button has been pressed, redirect. - $nextbutton = isset($submissionformman->formdata->nextbutton); + $nextbutton = isset($responsesubmitman->formdata->nextbutton); if ($nextbutton) { - $submissionformman->next_not_empty_page(true); - $paramurl['formpage'] = $submissionformman->get_nextpage(); - $paramurl['overflowpage'] = $submissionformman->get_overflowpage(); + $responsesubmitman->next_not_empty_page(true); + $paramurl['formpage'] = $responsesubmitman->get_nextpage(); + $paramurl['overflowpage'] = $responsesubmitman->get_overflowpage(); $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); // Redirect to the first non empty page. } // Surveypro has been submitted. Notify people. - $submissionformman->notifypeople(); + $responsesubmitman->notifypeople(); // If none redirected you, reload THE RIGHT page WITHOUT $paramurl['mode']. // This is necessary otherwise if the user switches language using the corresponding menu // just after a new response is submitted - // the browser redirects to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&view=1&lang=it§ion=submissionform + // the browser redirects to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&view=1&lang=it§ion=responsesubmit // and not to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&lang=it§ion=collectedsubmissions // alias it goes to the page to get one more response // instead of remaining in the view submissions page. $paramurl = []; $paramurl['s'] = $surveypro->id; - // $paramurl['responsestatus'] = $submissionformman->get_responsestatus(); - $paramurl['justsubmitted'] = 1 + $submissionformman->get_userdeservesthanks(); - $paramurl['formview'] = $submissionformman->get_mode(); // In which way am I using this form? + // $paramurl['responsestatus'] = $responsesubmitman->get_responsestatus(); + $paramurl['justsubmitted'] = 1 + $responsesubmitman->get_userdeservesthanks(); + $paramurl['formview'] = $responsesubmitman->get_mode(); // In which way am I using this form? $paramurl['section'] = 'submissionslist'; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); @@ -293,7 +297,7 @@ // End of: manage form submission. // Set $PAGE params. - $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'submissionform', 'mode' => $mode]; + $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'responsesubmit', 'mode' => $mode]; if (!empty($submissionid)) { $paramurl['submissionid'] = $submissionid; } @@ -338,28 +342,28 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_view_action_bar(); - $submissionformman->noitem_stopexecution(); - $submissionformman->nomoresubmissions_stopexecution(); - $submissionformman->warning_submission_copy(); - $submissionformman->display_page_x_of_y(); + $responsesubmitman->noitem_stopexecution(); + $responsesubmitman->nomoresubmissions_stopexecution(); + $responsesubmitman->warning_submission_copy(); + $responsesubmitman->display_page_x_of_y(); // Begin of: calculate prefill for fields and prepare standard editors and filemanager. // If sumission already exists. - $prefill = $submissionformman->get_prefill_data(); - $prefill['formpage'] = $submissionformman->get_formpage(); + $prefill = $responsesubmitman->get_prefill_data(); + $prefill['formpage'] = $responsesubmitman->get_formpage(); // End of: calculate prefill for fields and prepare standard editors and filemanager. $userform->set_data($prefill); $userform->display(); - // If surveypro is multipage and $submissionformman->tabpage == SURVEYPRO_READONLYMODE. + // If surveypro is multipage and $responsesubmitman->tabpage == SURVEYPRO_READONLYMODE. // I need to add navigation buttons manually // Because the surveypro is not displayed as a form but as a simple list of graphic user items. - $submissionformman->add_readonly_browsing_buttons(); + $responsesubmitman->add_readonly_browsing_buttons(); } -// MARK searchsubmissions. -if ($section == 'searchsubmissions') { +// MARK responsesearch. +if ($section == 'responsesearch') { // Get additional specific params. $formpage = optional_param('formpage', 1, PARAM_INT); // Form page number. @@ -367,12 +371,10 @@ require_capability('mod/surveypro:searchsubmissions', $context); // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - - $submissionsearchman = new view_submissionsearch($cm, $context, $surveypro); + $responsesearchman = new view_responsesearch($cm, $context, $surveypro); // Begin of: define $searchform return url. - $paramurl = ['s' => $cm->instance, 'section' => 'searchsubmissions']; + $paramurl = ['s' => $cm->instance, 'section' => 'responsesearch']; $formurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); // End of: define $searchform return url. @@ -381,7 +383,7 @@ $formparams->cm = $cm; $formparams->surveypro = $surveypro; $formparams->canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $context); - $searchform = new usersearch($formurl, $formparams, 'post', '', ['id' => 'usersearch']); + $searchform = new response_searchform($formurl, $formparams, 'post', '', ['id' => 'usersearch', 'class' => 'narrowlines']); // End of: prepare params for the form. // Begin of: manage form submission. @@ -391,11 +393,11 @@ redirect($returnurl); } - if ($submissionsearchman->formdata = $searchform->get_data()) { + if ($responsesearchman->formdata = $searchform->get_data()) { // In this routine I do not execute a real search. // I only define the param searchquery for the url. $paramurl = ['s' => $cm->instance, 'section' => 'submissionslist']; - if ($searchquery = $submissionsearchman->get_searchparamurl()) { + if ($searchquery = $responsesearchman->get_searchparamurl()) { $paramurl['searchquery'] = $searchquery; } $returnurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); @@ -404,7 +406,7 @@ // End of: manage form submission. // Set $PAGE params. - $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'searchsubmissions']; + $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'responsesearch']; $url = new \moodle_url('/mod/surveypro/view.php', $paramurl); $PAGE->set_url($url); $PAGE->set_context($context); From 87ef663bf7634d5b826462f11493d9b3288d1850 Mon Sep 17 00:00:00 2001 From: Kordan Date: Tue, 12 Mar 2024 16:04:12 +0100 Subject: [PATCH 2/2] This PR contains the content of three major improvements achieved in the last two months. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those three improvements can be described as follows: 1. translation of the content and content_format fields from the item plugin specific tables (surveypro(field|format)_itemplugin) to the parent table (surveypro_item). This first result is described in the content_among_basics branch (https://github.com/kordan/moodle-mod_surveypro/tree/content_among_basics). I have never created a pull request for this branch because I have never been able to perform a rebase that satisfied me. In practice: the method, named in master "item_add_mandatory_base_fields" was renamed in the branch to "item_add_defaults_for_base_fields". By rebasing content_among_basics on master the rename of the method was discarded so, after the rebase, I still found the original name. I spent a few days trying to understand the reason for this behavior. I asked my colleagues and then abandoned the problem. 2. translation of the most frequent properties (among all item plugins) from the specific item plugin tables (surveypro(field|format)_itemplugin) to the parent table (surveypro_item). This second step is clearly the natural continuation of the previous one and, for this reason, I created this new branch (https://github.com/kordan/moodle-mod_surveypro/tree/others_to_base_property) on top of content_among_basics. 3. Once I had a clear idea of how the itemplugin attributes were managed, I finally proceeded to adapt surveypro to php8.2 by creating the php8.2 branch. Obviously this branch was created on top of others_to_base_propertye, consequently, the php8.2 merge makes the first two branches useless. The outcome of "content_among_basics" is described in (1). The outcome of "others_to_base_property" is described in (2). The outcome of "php8.2" is described in (3). ===================================================== (1) Content and contentformat moved among base fields As part of a work of standardization and modernization of the module aimed at making the code homogeneous and, consequently, easily understandable and modifiable, I realized that the use of PHP 8.2 highlights a significant and very long series of errors that I must absolutely address. The first error among these is that the class of each item (item = fields + format) must have its own properties that it must manage on its own. But to define the list of properties of each item I have to decide which properties to consider "common" to all items and which to consider "specific" to each individual item. There are two reflections related to this problem: - Theoretically there are very few properties common to all items. Among these I only see: hidden, insearchform and reserved. All the others cannot be common to ALL items because, for example, the "pagebreak" item only has these three properties just mentioned; I already accepted this "lack" of properties ACTUALLY common to all items when I chose to create the itemsetup form (the form to setup a new item for the surveypro) from the union of a "item_setupbaseform" and an "itemsetupform". The item_setupbaseform has the fields it has and each item has a rule that says what it wants in its form and what it doesn't want to appear. (Each item defines a static vector called insetupform which declares what it wants to appear in the item_setupbaseform and what not. Obviously there is no similar vector for the specific form of each item because, having been created for the single item, it contains only and exclusively whatever you want.) I therefore realize that the answer to the question: which properties must be classified as "common" to all items and which, instead, must be classified as "specific" of each individual item is in the list of fields that I included, 10 years ago, in the "item_setupbaseform" and in the "itemsetupform". So in order to make the code more homogeneous and self-consistent, I have to start moving all the "common" fields from the tables of each individual item ('surveypro'.$type.'_'.$plugin) to the surveypro_item table. The two most difficult fields to move are 'content' and 'contentformat'. This is the reason that led me to this PR. - I lose compatibility with the past. I will write somewhere that if you want to keep your usertemplates and mastertemplates, you need to: -- before upgrading surveypro you have to load each usertemplate and mastertemplate into a course; -- upgrade your surveypro; -- regenerate each usertemplate and each mastertemplate. obviously the next PR I will make will relate to moving the other "common" properties from the specific tables to the surveypro_item table (and I will create them on top of this one). ===================================================== (2) Each common propery is now saved to surveypro_item When "content_among_basics" (that saves content and contentformat to surveypro_item and no longer into db tables of item plugins) and this PR will land to mastwer, I hope all will be ready to start to modify surveypro to let it correctly run in php8.2 and 8.3. With this PR the situation of properties should be: ``` | AGE | AUTOFILL | BOOLEAN | CHARACTER | CHECKBOX | DATE | DATETIME | FILEUPLOAD | INTEGER | MULTISELECT | NUMERIC | RADIOBUTTON | RATE | RECURRENCE | SELECT | SHORTDATE | TEXTAREA | TIME | FIELDSET | FIELDSETEND | LABEL | PAGEBREAK | id (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | surveyproid (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | type (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | plugin (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | content | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | √ | NO | contentformat | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | required | √ | NO | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | indent | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | position | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | customnumber | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | √ | NO | hideinstructions | √ | NO | NO | √ | √ | √ | √ | NO | √ | √ | √ | NO | √ | √ | NO | √ | √ | √ | NO | NO | NO | NO | variable | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | extranote | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | NO | NO | NO | NO | hidden | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | insearchform | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | reserved | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | sortindex (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | formpage (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | parentid | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | parentvalue | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | timecreated (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | timemodified (h) | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– ``` All the properties in the first column are relative to a field of the table surveypro_item. All the properties in the first column correspond to a field of the item_setupbaseform that is the initial part of each itemsetupform. Not all the items use ALL of that properties. They declare the use of each property throught $this->insetupform[] = (false|true); If $this->insetupform[] == false, the corresponding field in the formbase is not displayed in item_setupbaseform (and the useless default goes into the database). Marked with (h) are properties hidden to user. In the next table the list of specific properties item per item. These properties are save in surveypro(field|format)_. Yes, some of them coincide, but the number of plugins sharing the same property is too low and even the semantic is too specific of each single plugin so I decided to save these properties among the fields of the child table and not in surveypro_item. ``` | AGE | AUTOFILL | BOOLEAN | CHARACTER | CHECKBOX | DATE | DATETIME | FILEUPLOAD | INTEGER | MULTISELECT | NUMERIC | RADIOBUTTON | RATE | RECURRENCE | SELECT | SHORTDATE | TEXTAREA | TIME | FIELDSET | FIELDSETEND | LABEL | PAGEBREAK | –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– | defaultoption | hiddenfield | defaultoption | trimonsave | options | defaultoption | step | maxfiles | defaultoption | options | defaultvalue | options | options | defaultoption | options | defaultoption | trimonsave | step | defaultstatus | | fullwidth | | defaultvalue | element01 | defaultvalue | defaultvalue | labelother | defaultvalue | defaultvalue | maxbytes | defaultvalue | defaultvalue | signed | labelother | rates | defaultvalue | labelother | defaultvalue | useeditor | defaultoption | | leftlabel | | lowerbound | element02 | downloadformat | pattern | defaultvalue | downloadformat | defaultvalue | filetypes | lowerbound | noanswerdefault | lowerbound | defaultoption | defaultoption | downloadformat | defaultoption | downloadformat | arearows | defaultvalue | | upperbound | element03 | style | minlength | noanswerdefault | lowerbound | downloadformat | | upperbound | downloadformat | upperbound | defaultvalue | defaultvalue | lowerbound | defaultvalue | lowerbound | areacols | downloadformat | | element04 | | maxlength | downloadformat | upperbound | lowerbound | | minimumrequired | decimals | downloadformat | downloadformat | upperbound | downloadformat | upperbound | minlength | lowerbound | | element05 | | minimumrequired | | upperbound | | maximumrequired | | adjustment | style | | maxlength | upperbound | | maximumrequired | | heightinrows | | differentrates | | adjustment | ``` ===================================================== (3) php8.2 This improvement makes surveypro compatible with php8.2. There is some small problem, however, that I don't understand and which, for this reason, I describe below. (a) I see a theoretical problem that I believe is closely related to my request for help in: https://moodle.org/mod/forum/discuss.php?d=457241 The problem that php8.2 raises is practically always linked to the fact that I can not evaluate a property without first declare it. One of the properties common to all surveypro items is "content" (alias, the content of the question) followed by the content_format. To define an item via the corresponding form at submission time, the HTML editor is processed through file_prepare_standard_editor that changes the content_editor property. When I pass the object $item to the file_prepare_standard_editor method, php8.2 raises an exception claiming that the content_editor property (that I must have defined previously) and that I have defined as protected cannot be modified because it is protected. I know it is a good practice to always define properties as protected so my question is: How should I behave? Do I have to make the property public? (b) Furthermore, but this is a completely secondary detail, protected $content_editor is considered an error by Code Checker. ``` FILE: /home/runner/work/moodle-mod_surveypro/moodle-mod_surveypro/moodle/mod/surveypro/classes/itembase.php 93 | ERROR | [x] Member variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.MemberNameUnderscore) 1128 | ERROR | [x] Variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.VariableNameUnderscore) 1129 | ERROR | [x] Variable "content_editor" must not contain underscores. | | (moodle.NamingConventions.ValidVariableName.VariableNameUnderscore) ``` (c) In php8.2 and moodle master, I frequently get the error "Javascript code and/or AJAX requests are not ready after 10 seconds". At my eyes, it seems related to TinyMCE editor. Executing a submission of the item_setupbaseform with values that inhibit the submission itself, when the form is reloaded it is impossible to paste something in the content textarea. (d) I'm having a problem with style sheets. Moodle 4.4 defines the style class: ``` .mb-3, .my-3 { margin-bottom: 1rem !important; } ``` To override this class I am forced to use: ``` .path-mod-surveypro #userentry .mb-3, .path-mod-surveypro #usersearch .mb-3 { margin-bottom: 0 !important; } ``` specifying NECESSARILY !important to be able to override the parent class. The "!important" specification, however, is classified by Grunt (in the context of the GHA) as an error: ``` mod/surveypro/styles.css 28:22 ✖ Unexpected !important declaration-no-important 348:24 ✖ Unexpected !important declaration-no-important 356:24 ✖ Unexpected !important declaration-no-important 361:24 ✖ Unexpected !important declaration-no-important 366:22 ✖ Unexpected !important declaration-no-important 374:22 ✖ Unexpected !important declaration-no-important 379:22 ✖ Unexpected !important declaration-no-important 384:24 ✖ Unexpected !important declaration-no-important 392:24 ✖ Unexpected !important declaration-no-important 397:24 ✖ Unexpected !important declaration-no-important 402:22 ✖ Unexpected !important declaration-no-important 409:22 ✖ Unexpected !important declaration-no-important 414:22 ✖ Unexpected !important declaration-no-important 419:24 ✖ Unexpected !important declaration-no-important 426:24 ✖ Unexpected !important declaration-no-important 431:24 ✖ Unexpected !important declaration-no-important 436:22 ✖ Unexpected !important declaration-no-important 443:22 ✖ Unexpected !important declaration-no-important 448:22 ✖ Unexpected !important declaration-no-important 453:25 ✖ Unexpected !important declaration-no-important 460:25 ✖ Unexpected !important declaration-no-important 465:25 ✖ Unexpected !important declaration-no-important 470:23 ✖ Unexpected !important declaration-no-important 477:23 ✖ Unexpected !important declaration-no-important 482:23 ✖ Unexpected !important declaration-no-important 487:25 ✖ Unexpected !important declaration-no-important 494:25 ✖ Unexpected !important declaration-no-important 499:25 ✖ Unexpected !important declaration-no-important 28 problems (28 errors, 0 warnings) ``` --- .github/workflows/moodle-ci.yml | 6 +- TODO.txt | 20 +- backup/moodle2/backup_surveypro_stepslib.php | 20 +- classes/event/submission_created.php | 2 +- classes/event/submission_modified.php | 2 +- classes/event/submission_viewed.php | 2 +- classes/formbase.php | 7 +- classes/itembase.php | 1354 ++++++++---- classes/layout_branchingvalidation.php | 5 +- classes/layout_itemlist.php | 90 +- classes/layout_itemsetup.php | 4 +- classes/local/form/item_chooser.php | 6 +- classes/local/form/item_setupbaseform.php | 22 +- classes/local/form/mtemplate_applyform.php | 6 +- classes/local/form/mtemplate_createform.php | 4 + ...usersearch.php => response_searchform.php} | 18 +- .../{userform.php => response_submitform.php} | 180 +- classes/local/form/utemplate_importform.php | 5 +- classes/local/ipe/layout_customnumber.php | 5 +- classes/local/ipe/layout_required.php | 5 +- classes/local/ipe/layout_variable.php | 12 +- classes/mtemplate_apply.php | 134 +- classes/mtemplate_save.php | 229 +- classes/output/action_bar.php | 8 +- classes/plugininfo/surveyprofield.php | 6 +- classes/plugininfo/surveyproformat.php | 6 +- classes/privacy/provider.php | 2 +- classes/templatebase.php | 286 ++- classes/tools_export.php | 7 +- classes/tools_import.php | 10 +- classes/utemplate_apply.php | 191 +- classes/utemplate_import.php | 16 - classes/utemplate_manage.php | 28 +- classes/utemplate_save.php | 114 +- classes/utility_layout.php | 4 +- classes/utility_mform.php | 66 - classes/view_cover.php | 2 +- ...bmissionlist.php => view_responselist.php} | 57 +- ...sionsearch.php => view_responsesearch.php} | 6 +- ...issionform.php => view_responsesubmit.php} | 202 +- db/access.php | 44 +- db/install.xml | 9 + db/upgrade.php | 86 + ...kup_surveyprofield_age_subplugin.class.php | 5 +- field/age/classes/item.php | 446 ++-- field/age/db/install.xml | 31 +- field/age/db/upgrade.php | 62 + field/age/lang/en/surveyprofield_age.php | 12 +- field/age/lang/it/surveyprofield_age.php | 43 + field/age/tests/behat/itemform.feature | 4 +- field/age/tests/behat/submit_age.feature | 4 +- .../tests/behat/use_advanced_elements.feature | 8 +- ...2023103100.xml => age_only_2024032800.xml} | 228 +- field/age/version.php | 4 +- ...urveyprofield_autofill_subplugin.class.php | 5 +- field/autofill/classes/item.php | 518 +++-- field/autofill/db/install.xml | 34 +- field/autofill/db/upgrade.php | 65 +- .../lang/en/surveyprofield_autofill.php | 6 +- ...23000.xml => autofill_only_2024032800.xml} | 52 +- field/autofill/version.php | 4 +- ...surveyprofield_boolean_subplugin.class.php | 5 +- field/boolean/classes/item.php | 298 ++- field/boolean/db/install.xml | 30 +- field/boolean/db/upgrade.php | 63 +- .../lang/en/surveyprofield_boolean.php | 8 +- field/boolean/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_boolean.feature | 4 +- ...123000.xml => boolean_only_2024032800.xml} | 341 +-- field/boolean/version.php | 4 +- ...rveyprofield_character_subplugin.class.php | 5 +- field/character/classes/item.php | 349 +-- field/character/classes/itemsetupform.php | 19 +- field/character/db/install.xml | 32 +- field/character/db/upgrade.php | 64 +- .../lang/en/surveyprofield_character.php | 14 +- .../lang/es_mx/surveyprofield_character.php | 12 +- field/character/tests/behat/itemform.feature | 2 +- field/character/tests/behat/trim.feature | 9 +- ...0.xml => text_(short)_only_2024032800.xml} | 208 +- field/character/version.php | 4 +- ...urveyprofield_checkbox_subplugin.class.php | 5 +- field/checkbox/classes/item.php | 429 ++-- field/checkbox/db/install.xml | 38 +- field/checkbox/db/upgrade.php | 61 + .../lang/en/surveyprofield_checkbox.php | 18 +- field/checkbox/mform/advcheckbox.php | 77 - field/checkbox/mform/checkbox.php | 76 - field/checkbox/tests/behat/itemform.feature | 12 +- .../behat/settings_configuration_01.feature | 20 +- .../behat/settings_configuration_02.feature | 16 +- .../behat/settings_configuration_03.feature | 12 +- .../behat/settings_configuration_04.feature | 8 +- .../behat/settings_configuration_05.feature | 16 +- ...23000.xml => checkbox_only_2024032800.xml} | 454 ++-- field/checkbox/version.php | 4 +- ...up_surveyprofield_date_subplugin.class.php | 5 +- field/date/classes/item.php | 516 +++-- field/date/db/install.xml | 32 +- field/date/db/upgrade.php | 63 +- field/date/lang/en/surveyprofield_date.php | 10 +- field/date/tests/behat/itemform.feature | 6 +- field/date/tests/behat/submit_date.feature | 6 +- ...023103100.xml => date_only_2024032800.xml} | 214 +- field/date/version.php | 4 +- ...urveyprofield_datetime_subplugin.class.php | 5 +- field/datetime/classes/item.php | 670 ++++-- field/datetime/db/install.xml | 34 +- field/datetime/db/upgrade.php | 63 +- .../lang/en/surveyprofield_datetime.php | 12 +- field/datetime/tests/behat/itemform.feature | 10 +- .../tests/behat/submit_datetime.feature | 10 +- ....xml => date_and_time_only_2024032800.xml} | 233 +- field/datetime/version.php | 4 +- ...veyprofield_fileupload_subplugin.class.php | 5 +- field/fileupload/classes/item.php | 275 ++- field/fileupload/db/install.xml | 28 +- field/fileupload/db/upgrade.php | 61 + .../lang/en/surveyprofield_fileupload.php | 12 +- field/fileupload/mform/fileupload.php | 159 -- .../tests/behat/submit_attachment.feature | 18 +- ...000.xml => attachment_only_2024032800.xml} | 30 +- field/fileupload/version.php | 4 +- ...surveyprofield_integer_subplugin.class.php | 5 +- field/integer/classes/item.php | 231 +- field/integer/db/install.xml | 30 +- field/integer/db/upgrade.php | 67 +- .../lang/en/surveyprofield_integer.php | 10 +- .../lang/it/surveyprofield_integer.php | 4 +- field/integer/tests/behat/itemform.feature | 2 +- .../tests/behat/submit_integer.feature | 2 +- ...123000.xml => integer_only_2024032800.xml} | 111 +- field/integer/version.php | 4 +- ...eyprofield_multiselect_subplugin.class.php | 5 +- field/multiselect/classes/item.php | 397 ++-- field/multiselect/db/install.xml | 36 +- field/multiselect/db/upgrade.php | 61 + .../lang/en/surveyprofield_multiselect.php | 24 +- .../multiselect/tests/behat/itemform.feature | 2 +- .../behat/settings_configuration_01.feature | 20 +- .../behat/settings_configuration_02.feature | 14 +- .../behat/settings_configuration_03.feature | 10 +- .../behat/settings_configuration_04.feature | 12 +- .../behat/settings_configuration_05.feature | 12 +- ...00.xml => multiselect_only_2024032800.xml} | 209 +- field/multiselect/version.php | 4 +- ...surveyprofield_numeric_subplugin.class.php | 5 +- field/numeric/classes/item.php | 367 +-- field/numeric/db/install.xml | 32 +- field/numeric/db/upgrade.php | 63 +- .../lang/en/surveyprofield_numeric.php | 16 +- field/numeric/tests/behat/itemform.feature | 2 +- ...123000.xml => numeric_only_2024032800.xml} | 128 +- field/numeric/version.php | 4 +- ...eyprofield_radiobutton_subplugin.class.php | 5 +- field/radiobutton/classes/item.php | 358 +-- field/radiobutton/classes/itemsetupform.php | 5 +- field/radiobutton/db/install.xml | 34 +- field/radiobutton/db/upgrade.php | 63 +- .../lang/en/surveyprofield_radiobutton.php | 15 +- field/radiobutton/mform/radiobutton.php | 85 - .../radiobutton/tests/behat/itemform.feature | 14 +- .../tests/behat/submit_radiobutton.feature | 4 +- .../tests/behat/two_option_test.feature | 8 +- .../{mum_or_dad_test.xml => mum_or_dad.xml} | 120 +- ...00.xml => radiobutton_only_2024032800.xml} | 294 +-- field/radiobutton/version.php | 4 +- ...up_surveyprofield_rate_subplugin.class.php | 5 +- field/rate/classes/item.php | 344 +-- field/rate/classes/itemsetupform.php | 10 +- field/rate/db/install.xml | 36 +- field/rate/db/upgrade.php | 63 +- field/rate/lang/en/surveyprofield_rate.php | 24 +- field/rate/tests/behat/itemform.feature | 104 +- field/rate/tests/behat/submit_rate.feature | 24 +- ...015123000.xml => rate_only_2024032800.xml} | 234 +- field/rate/version.php | 4 +- ...veyprofield_recurrence_subplugin.class.php | 5 +- field/recurrence/classes/item.php | 444 ++-- field/recurrence/db/install.xml | 32 +- field/recurrence/db/upgrade.php | 63 +- .../lang/en/surveyprofield_recurrence.php | 12 +- field/recurrence/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_recurrence.feature | 4 +- ...100.xml => recurrence_only_2024032800.xml} | 233 +- field/recurrence/version.php | 4 +- ..._surveyprofield_select_subplugin.class.php | 5 +- field/select/classes/item.php | 300 ++- field/select/classes/itemsetupform.php | 1 - field/select/db/install.xml | 32 +- field/select/db/upgrade.php | 63 +- .../select/lang/en/surveyprofield_select.php | 12 +- .../select/lang/it/surveyprofield_select.php | 2 +- field/select/tests/behat/itemform.feature | 4 +- .../select/tests/behat/submit_select.feature | 6 +- ...5123000.xml => select_only_2024032800.xml} | 294 +-- field/select/version.php | 4 +- ...rveyprofield_shortdate_subplugin.class.php | 5 +- field/shortdate/classes/item.php | 441 ++-- field/shortdate/classes/itemsetupform.php | 2 +- field/shortdate/db/install.xml | 32 +- field/shortdate/db/upgrade.php | 63 +- .../lang/en/surveyprofield_shortdate.php | 10 +- field/shortdate/tests/behat/itemform.feature | 4 +- .../tests/behat/submit_shortdate.feature | 4 +- ...0.xml => date_(short)_only_2024032800.xml} | 230 +- field/shortdate/version.php | 4 +- ...urveyprofield_textarea_subplugin.class.php | 5 +- field/textarea/classes/item.php | 338 +-- field/textarea/classes/itemsetupform.php | 2 +- field/textarea/db/install.xml | 34 +- field/textarea/db/upgrade.php | 63 +- .../lang/en/surveyprofield_textarea.php | 14 +- .../lang/es_mx/surveyprofield_textarea.php | 12 +- .../lang/it/surveyprofield_textarea.php | 10 +- field/textarea/mform/textarea_editor.php | 119 - field/textarea/mform/textarea_plain.php | 120 - field/textarea/tests/behat/itemform.feature | 4 +- .../behat/settings_configuration.feature | 4 +- field/textarea/tests/behat/trim.feature | 5 +- ...23000.xml => textarea_only_2024032800.xml} | 116 +- field/textarea/version.php | 4 +- ...up_surveyprofield_time_subplugin.class.php | 5 +- field/time/classes/item.php | 455 ++-- field/time/db/install.xml | 34 +- field/time/db/upgrade.php | 63 +- field/time/lang/en/surveyprofield_time.php | 12 +- field/time/tests/behat/itemform.feature | 20 +- field/time/tests/behat/submit_time.feature | 4 +- ...023103100.xml => time_only_2024032800.xml} | 233 +- field/time/version.php | 4 +- ...rveyproformat_fieldset_subplugin.class.php | 2 +- format/fieldset/classes/item.php | 105 +- format/fieldset/classes/itemsetupform.php | 2 +- format/fieldset/db/install.xml | 24 +- format/fieldset/db/upgrade.php | 20 + .../lang/en/surveyproformat_fieldset.php | 2 +- format/fieldset/version.php | 4 +- format/fieldsetend/classes/item.php | 81 +- .../lang/en/surveyproformat_fieldsetend.php | 2 +- format/fieldsetend/version.php | 4 +- ..._surveyproformat_label_subplugin.class.php | 5 +- format/label/classes/item.php | 159 +- format/label/classes/itemsetupform.php | 2 +- format/label/db/install.xml | 26 +- format/label/db/upgrade.php | 65 +- .../label/lang/en/surveyproformat_label.php | 6 +- format/label/mform/label.php | 86 - format/label/version.php | 4 +- format/pagebreak/classes/item.php | 93 +- .../lang/en/surveyproformat_pagebreak.php | 2 +- format/pagebreak/version.php | 4 +- index.php | 27 +- lang/en/surveypro.php | 111 +- lang/es/surveypro.php | 98 +- lang/es_mx/surveypro.php | 100 +- lang/it/surveypro.php | 32 +- layout.php | 21 +- lib.php | 25 +- mod_form.php | 16 +- mtemplates.php | 21 +- pix/stamp.png | Bin 0 -> 379 bytes pix/stamp.svg | 54 + report/attachments/classes/filterform.php | 2 +- report/attachments/classes/form.php | 13 +- report/attachments/classes/report.php | 1 - .../lang/en/surveyproreport_attachments.php | 4 +- .../behat/attachment_functionality.feature | 3 - report/attachments/version.php | 4 +- report/attachments/view.php | 2 +- report/colles/classes/report.php | 12 +- report/colles/graph.php | 4 +- .../colles/lang/en/surveyproreport_colles.php | 34 +- report/colles/version.php | 4 +- report/frequency/classes/filterform.php | 7 +- report/frequency/classes/report.php | 3 +- report/frequency/graph.php | 2 +- .../lang/en/surveyproreport_frequency.php | 4 +- .../lang/it/surveyproreport_frequency.php | 2 +- report/frequency/version.php | 4 +- report/lateusers/classes/report.php | 1 - report/lateusers/version.php | 4 +- report/responsesperuser/classes/report.php | 1 - report/responsesperuser/version.php | 4 +- report/userspercount/classes/report.php | 1 - .../lang/en/surveyproreport_userspercount.php | 2 +- report/userspercount/version.php | 4 +- reports.php | 4 +- styles.css | 214 +- .../attls/lang/en/surveyprotemplate_attls.php | 34 +- .../attls/lang/it/surveyprotemplate_attls.php | 32 +- template/attls/template.xml | 254 +-- template/attls/version.php | 4 +- .../en/surveyprotemplate_collesactual.php | 34 +- .../it/surveyprotemplate_collesactual.php | 32 +- template/collesactual/template.xml | 396 ++-- .../collesactual/tests/behat/graphs.feature | 52 +- .../tests/behat/reportswithanswers.feature | 156 +- .../tests/behat/reportswithoutanswers.feature | 53 +- template/collesactual/version.php | 4 +- ...urveyprotemplate_collesactualpreferred.php | 10 +- ...urveyprotemplate_collesactualpreferred.php | 10 +- template/collesactualpreferred/template.xml | 686 +++--- .../tests/behat/graphs.feature | 112 +- template/collesactualpreferred/version.php | 4 +- .../en/surveyprotemplate_collespreferred.php | 34 +- .../it/surveyprotemplate_collespreferred.php | 32 +- template/collespreferred/template.xml | 396 ++-- .../tests/behat/graphs.feature | 52 +- template/collespreferred/version.php | 4 +- .../surveyprotemplate_criticalincidents.php | 6 +- .../surveyprotemplate_criticalincidents.php | 6 +- template/criticalincidents/template.xml | 78 +- template/criticalincidents/version.php | 4 +- template/flags/classes/privacy/provider.php | 44 + template/flags/classes/template.php | 47 + .../flags/lang/en/surveyprotemplate_flags.php | 32 + .../flags/lang/es/surveyprotemplate_flags.php | 32 + .../flags/lang/it/surveyprotemplate_flags.php | 32 + template/flags/pix/icon.png | Bin 0 -> 625 bytes template/flags/pix/icon.svg | 579 +++++ template/flags/template.xml | 27 + template/flags/version.php | 30 + .../classes/privacy/provider.php | 44 + template/oneofeachenable/classes/template.php | 47 + .../en/surveyprotemplate_oneofeachenable.php | 248 +++ template/oneofeachenable/pix/icon.png | Bin 0 -> 625 bytes template/oneofeachenable/pix/icon.svg | 579 +++++ template/oneofeachenable/template.xml | 1965 +++++++++++++++++ template/oneofeachenable/version.php | 30 + templatemaster/version.php | 4 +- tests/behat/backup_restore.feature | 4 +- tests/behat/backup_simple.feature | 2 + tests/behat/behat_mod_surveypro.php | 23 +- tests/behat/change_of_mind.feature | 14 +- tests/behat/duplicate_response.feature | 2 +- tests/behat/item_action.feature | 34 +- tests/behat/lib_behattest.php | 94 +- tests/behat/parent_boolean.feature | 37 +- tests/behat/parent_checkbox.feature | 280 +-- tests/behat/parent_integer.feature | 48 +- tests/behat/parent_multiselect.feature | 168 +- tests/behat/parent_radiobutton.feature | 48 +- tests/behat/parent_select.feature | 44 +- ...readonly_browse_allowed_pages_only.feature | 2 +- tests/behat/restore_simple.feature | 91 +- .../behat/see_groupsubmissions_part01.feature | 4 +- .../behat/see_groupsubmissions_part02.feature | 2 +- .../behat/see_groupsubmissions_part03.feature | 2 +- .../behat/see_groupsubmissions_part04.feature | 7 +- tests/behat/submission_test.feature | 56 +- tests/behat/thankspage.feature | 7 +- tests/behat/timezone_independent.feature | 80 +- tests/behat/usertemplate_apply.feature | 8 +- tests/behat/usertemplate_applyall.feature | 72 +- tests/behat/usertemplate_create.feature | 6 +- tests/fixtures/demo_course-20160108.mbz | Bin 72980 -> 0 bytes tests/fixtures/demo_course-20240410.mbz | Bin 0 -> 89037 bytes ...{MMM_2023103100.xml => MMM_2024032800.xml} | 604 +++-- .../{item_action_test.xml => item_action.xml} | 200 +- ...103100.xml => parent-child_2024032800.xml} | 342 ++- tests/generator_test.php | 8 +- tests/lib_test.php | 15 +- tests/mastertemplate_test.php | 4 +- tests/separator_test.php | 56 +- tests/setup_test.php | 4 +- tools.php | 4 +- utemplates.php | 66 +- version.php | 6 +- view.php | 128 +- 370 files changed, 17553 insertions(+), 10561 deletions(-) rename classes/local/form/{usersearch.php => response_searchform.php} (89%) rename classes/local/form/{userform.php => response_submitform.php} (81%) delete mode 100644 classes/utility_mform.php rename classes/{view_submissionlist.php => view_responselist.php} (97%) rename classes/{view_submissionsearch.php => view_responsesearch.php} (96%) rename classes/{view_submissionform.php => view_responsesubmit.php} (87%) create mode 100644 field/age/lang/it/surveyprofield_age.php rename field/age/tests/fixtures/usertemplate/{age_only_2023103100.xml => age_only_2024032800.xml} (92%) rename field/autofill/tests/fixtures/usertemplate/{autofill_only_2015123000.xml => autofill_only_2024032800.xml} (92%) rename field/boolean/tests/fixtures/usertemplate/{boolean_only_2015123000.xml => boolean_only_2024032800.xml} (77%) rename field/character/tests/fixtures/usertemplate/{textshort_only_2015123000.xml => text_(short)_only_2024032800.xml} (87%) delete mode 100644 field/checkbox/mform/advcheckbox.php delete mode 100644 field/checkbox/mform/checkbox.php rename field/checkbox/tests/fixtures/usertemplate/{checkbox_only_2015123000.xml => checkbox_only_2024032800.xml} (93%) rename field/date/tests/fixtures/usertemplate/{date_only_2023103100.xml => date_only_2024032800.xml} (91%) rename field/datetime/tests/fixtures/usertemplate/{datetime_only_2023103100.xml => date_and_time_only_2024032800.xml} (88%) delete mode 100644 field/fileupload/mform/fileupload.php rename field/fileupload/tests/fixtures/usertemplate/{attachment_only_2015123000.xml => attachment_only_2024032800.xml} (90%) rename field/integer/tests/fixtures/usertemplate/{integer_only_2015123000.xml => integer_only_2024032800.xml} (88%) rename field/multiselect/tests/fixtures/usertemplate/{multiselect_only_2015123000.xml => multiselect_only_2024032800.xml} (87%) rename field/numeric/tests/fixtures/usertemplate/{numeric_only_2015123000.xml => numeric_only_2024032800.xml} (84%) delete mode 100644 field/radiobutton/mform/radiobutton.php rename field/radiobutton/tests/fixtures/usertemplate/{mum_or_dad_test.xml => mum_or_dad.xml} (90%) rename field/radiobutton/tests/fixtures/usertemplate/{radiobutton_only_2015123000.xml => radiobutton_only_2024032800.xml} (92%) rename field/rate/tests/fixtures/usertemplate/{rate_only_2015123000.xml => rate_only_2024032800.xml} (89%) rename field/recurrence/tests/fixtures/usertemplate/{recurrence_only_2023103100.xml => recurrence_only_2024032800.xml} (87%) rename field/select/tests/fixtures/usertemplate/{select_only_2015123000.xml => select_only_2024032800.xml} (92%) rename field/shortdate/tests/fixtures/usertemplate/{dateshort_only_2023103100.xml => date_(short)_only_2024032800.xml} (88%) delete mode 100644 field/textarea/mform/textarea_editor.php delete mode 100644 field/textarea/mform/textarea_plain.php rename field/textarea/tests/fixtures/usertemplate/{textarea_only_2015123000.xml => textarea_only_2024032800.xml} (87%) rename field/time/tests/fixtures/usertemplate/{time_only_2023103100.xml => time_only_2024032800.xml} (89%) delete mode 100644 format/label/mform/label.php create mode 100644 pix/stamp.png create mode 100644 pix/stamp.svg create mode 100644 template/flags/classes/privacy/provider.php create mode 100644 template/flags/classes/template.php create mode 100644 template/flags/lang/en/surveyprotemplate_flags.php create mode 100644 template/flags/lang/es/surveyprotemplate_flags.php create mode 100644 template/flags/lang/it/surveyprotemplate_flags.php create mode 100644 template/flags/pix/icon.png create mode 100644 template/flags/pix/icon.svg create mode 100644 template/flags/template.xml create mode 100644 template/flags/version.php create mode 100644 template/oneofeachenable/classes/privacy/provider.php create mode 100644 template/oneofeachenable/classes/template.php create mode 100644 template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php create mode 100644 template/oneofeachenable/pix/icon.png create mode 100644 template/oneofeachenable/pix/icon.svg create mode 100644 template/oneofeachenable/template.xml create mode 100644 template/oneofeachenable/version.php delete mode 100644 tests/fixtures/demo_course-20160108.mbz create mode 100644 tests/fixtures/demo_course-20240410.mbz rename tests/fixtures/usertemplate/{MMM_2023103100.xml => MMM_2024032800.xml} (95%) rename tests/fixtures/usertemplate/{item_action_test.xml => item_action.xml} (92%) rename tests/fixtures/usertemplate/{parent-child_2023103100.xml => parent-child_2024032800.xml} (91%) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 8cf028e1900..baea34564d1 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -29,12 +29,12 @@ jobs: matrix: include: - php: 8.1 - moodle-branch: MOODLE_403_STABLE + moodle-branch: MOODLE_404_STABLE database: mariadb suite: classic profile: default - - php: 8.1 - moodle-branch: MOODLE_403_STABLE + - php: 8.2 + moodle-branch: MOODLE_404_STABLE database: pgsql suite: default profile: chrome diff --git a/TODO.txt b/TODO.txt index 4958bd16a16..6cee0ee6f43 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,7 @@ -> does it make sense the research per long text? --> "Manage relation" page has lots of features, but the consequence is that the page is "cluttered" with too many settings. +-> "Manage relation" page has lots of features, but the consequence is that the page is "cluttered" with too many settings. Obviously a Show/Hide advanced button is needed. (thanks to JR) --> The Autofill question message "Content will be added at submit time" should not be displayed to the Student when taking the Survey, +-> The Autofill question message "Content will be added at submit time" should not be displayed to the Student taking the Survey, as it does not mean anything to him. That is a message for Teacher, not Student. (thanks to JR) -> grades? -> surveypro_get_view_actions()? @@ -9,10 +9,10 @@ as it does not mean anything to him. That is a message for Teacher, not Student. -> surveypro_scale_used($surveyproid, $scaleid)? -> surveypro_scale_used_anywhere($scaleid)? -> unit test (they are a must) --> *** Crucial known issue that is not fixable in my opinion. I apply a master template. -I make a surveypro with it. Tomorrow I update the master template with a newer version. -This new version has one more item in the middle. -Surveys built with the old release of the plugin will stop working fine as they will find in the right position string of a different template. +-> *** Crucial known issue that is not fixable in my opinion. I apply a master template. +I make a surveypro with it. Tomorrow I update the master template with a newer version. +This new version has one more item in the middle. +Surveys built with the old plugins will stop working fine as they will find in the right position string of a different template. -> possible better solution: use the first 32 chars of the question escaped -> is the autofill field saved to userdata even if it is not shown? -> allow upperbound date/datetime == to now @@ -21,7 +21,7 @@ Surveys built with the old release of the plugin will stop working fine as they -> mform elements in MMM have different sizes probably because of /theme/yui_combo.php? 3.13.0/cssreset/cssreset.css&3.13.0/cssfonts/cssfonts.css&3.13.0/cssgrids/cssgrids.css&3.13.0/cssbase/cssbase.css -1) Still it seems to be something strange when handling fileareas. +1) Still it seems to be something strange when handling fileareas. I just grepped by get_area_files and found a bunch of them new/strange for me. ELOY has to review this! > Please let me know better what do you mean. I can not understand it. @@ -31,15 +31,15 @@ I just grepped by get_area_files and found a bunch of them new/strange for me. E > literals is ok. > more yet, if there are groups... then everything (listing, reports, graphs) > must be by group. -things like the "phantom tabs" (sorry for the expression, lol, just joking) or the way "attempts" are performed... +things like the "phantom tabs" (sorry for the expression, lol, just joking) or the way "attempts" are performed... are substandard (to name it in some way). 2.a) A read me about what's missing (migration from old, usability review and discussion) -2.b) A commit (decided by you) where you want me to cut history. +2.b) A commit (decided by you) where you want me to cut history. Can be current commit of anything else if you want to preserve your latest commits for any reason. -2.c) A BIG WARNING saying that it must not be used in production sites with existing old surveypros +2.c) A BIG WARNING saying that it must not be used in production sites with existing old surveypros because they will be erased completely (beacuse of 1). README.md (so it will display nicely in github) ? diff --git a/backup/moodle2/backup_surveypro_stepslib.php b/backup/moodle2/backup_surveypro_stepslib.php index e20c560e95a..d7ccd30b667 100644 --- a/backup/moodle2/backup_surveypro_stepslib.php +++ b/backup/moodle2/backup_surveypro_stepslib.php @@ -44,18 +44,22 @@ protected function define_structure() { // Define each element separated. // Root element describing surveypro instance. $surveypro = new backup_nested_element('surveypro', ['id'], [ - 'name', 'intro', 'introformat', 'newpageforchild', 'neverstartedemail', - 'pauseresume', 'keepinprogress', 'captcha', 'history', 'anonymous', - 'timeopen', 'timeclose', 'startyear', 'stopyear', - 'maxentries', 'mailroles', 'mailextraaddresses', 'mailcontent', 'mailcontentformat', - 'thankspage', 'thankspageformat', 'riskyeditdeadline', 'template', 'completionsubmit', - 'timecreated', 'timemodified', ]); + 'name', 'intro', 'introformat', 'newpageforchild', 'neverstartedemail', + 'pauseresume', 'keepinprogress', 'captcha', 'history', 'anonymous', + 'timeopen', 'timeclose', 'startyear', 'stopyear', + 'maxentries', 'mailroles', 'mailextraaddresses', 'mailcontent', 'mailcontentformat', + 'thankspage', 'thankspageformat', 'riskyeditdeadline', 'template', 'completionsubmit', + 'timecreated', 'timemodified', + ]); $items = new backup_nested_element('items'); $item = new backup_nested_element('item', ['id', 'type', 'plugin'], [ - 'hidden', 'insearchform', 'reserved', 'sortindex', 'formpage', - 'parentid', 'parentvalue', 'timecreated', 'timemodified', ]); + 'content', 'contentformat', + 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', + 'hidden', 'insearchform', 'reserved', 'sortindex', 'formpage', + 'parentid', 'parentvalue', 'timecreated', 'timemodified', + ]); $submissions = new backup_nested_element('submissions'); diff --git a/classes/event/submission_created.php b/classes/event/submission_created.php index 88e7a55587c..10801fe9786 100644 --- a/classes/event/submission_created.php +++ b/classes/event/submission_created.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/event/submission_modified.php b/classes/event/submission_modified.php index 77ed7296dda..59812ed5bd9 100644 --- a/classes/event/submission_modified.php +++ b/classes/event/submission_modified.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/event/submission_viewed.php b/classes/event/submission_viewed.php index 865cac33337..7a9637831c1 100644 --- a/classes/event/submission_viewed.php +++ b/classes/event/submission_viewed.php @@ -70,7 +70,7 @@ public function get_url() { $paramurl['id'] = $this->contextinstanceid; $paramurl['submissionid'] = $this->objectid; $paramurl['mode'] = $this->other['mode']; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; return new \moodle_url('/mod/surveypro/view.php', $paramurl); } diff --git a/classes/formbase.php b/classes/formbase.php index 000fb9f8170..e3177d1a0ed 100644 --- a/classes/formbase.php +++ b/classes/formbase.php @@ -123,8 +123,9 @@ public function set_user_boundary_formpages() { FROM {surveypro_item} WHERE surveyproid = :surveyproid AND reserved = :reserved + AND hidden = :hidden AND plugin <> :plugin'; - $whereparams = ['surveyproid' => $this->surveypro->id, 'reserved' => 0, 'plugin' => 'pagebreak']; + $whereparams = ['surveyproid' => $this->surveypro->id, 'reserved' => 0, 'hidden' => 0, 'plugin' => 'pagebreak']; $boundaries = $DB->get_record_sql($sql, $whereparams); $userfirstpage = isset($boundaries->userfirstpage) ? $boundaries->userfirstpage : 1; @@ -232,7 +233,7 @@ private function page_has_items($formpage) { } foreach ($itemseeds as $itemseed) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); if ($parentitem->userform_is_child_allowed_static($this->get_submissionid(), $itemseed)) { // If at least one parent allows its child, I finished. The page is going to display items. return true; @@ -296,7 +297,7 @@ public function get_prefill_data() { [$where, $params] = surveypro_fetch_items_seeds($id, true, $canaccessreserveditems, null, SURVEYPRO_TYPEFIELD, $page); if ($itemseeds = $DB->get_recordset_select('surveypro_item', $where, $params, 'sortindex', 'id, type, plugin')) { foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $where = ['submissionid' => $this->submissionid, 'itemid' => $item->get_itemid()]; $olduserdata = $DB->get_record('surveypro_answer', $where); diff --git a/classes/itembase.php b/classes/itembase.php index c538e5eeac5..e905b4f99ab 100644 --- a/classes/itembase.php +++ b/classes/itembase.php @@ -38,7 +38,9 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class itembase { +abstract class itembase { + + // Itembase properties. /** * @var object Course module object @@ -55,6 +57,11 @@ class itembase { */ public $surveypro; + /** + * @var int pluginid: the id of the item in the child surveypro(field|format)_plugin table + */ + protected $pluginid; + /** * @var int Unique itemid of the surveyproitem in surveypro_item table */ @@ -71,9 +78,49 @@ class itembase { protected $plugin; /** - * @var string Basename of the field as it is in the out form + * @var string The content of the question of the item */ - protected $itemname; + public $content; + + /** + * @var string The contentformat of the question of the item + */ + public $contentformat; + + /** + * @var int Is the item required? + */ + protected $required; + + /** + * @var int Indent of the item in the form page + */ + protected $indent; + + /** + * @var int The position of the item content in the frame of the user form + */ + protected $position; + + /** + * @var string The custom number of the item + */ + protected $customnumber; + + /** + * @var int Are the filling instruction going to explain the item in the user form? + */ + protected $hideinstructions; + + /** + * @var string The name of the item in the exported report + */ + protected $variable; + + /** + * @var string The content of custom extranote + */ + protected $extranote; /** * @var bool Visibility of this item in the out form @@ -110,6 +157,23 @@ class itembase { */ protected $parentvalue; + /** + * @var int timecreated + */ + protected $timecreated; + + /** + * @var int timemodified + */ + protected $timemodified; + + // Service variables + + /** + * @var string Basename of the field as it is in the out form + */ + protected $itemname; + /** * @var string The user friendly answer that the parent item has to have in order to show this item as child */ @@ -120,11 +184,6 @@ class itembase { */ protected $itemeditingfeedback; - /** - * @var array - */ - protected $fieldsusingformat = ['content' => SURVEYPRO_ITEMCONTENTFILEAREA]; - /** * List of fields properties the surveypro creator will manage in the item definition form * By default each item property is present in the form @@ -132,16 +191,17 @@ class itembase { * * @var array */ - protected $insetupform = [ + public $insetupform = [ 'common_fs' => true, 'content' => true, - 'customnumber' => true, + 'contentformat' => true, + 'required' => true, + 'indent' => true, 'position' => true, + 'variable' => true, 'extranote' => true, + 'customnumber' => true, 'hideinstructions' => true, - 'required' => true, - 'variable' => true, - 'indent' => true, 'hidden' => true, 'insearchform' => true, 'reserved' => true, @@ -149,7 +209,7 @@ class itembase { ]; /** - * Class constructor. + * Class constructor * * @param object $cm * @param object $surveypro @@ -159,12 +219,13 @@ class itembase { public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->cm = $cm; $this->surveypro = $surveypro; + $this->context = \context_module::instance($cm->id); } /** * Item load. * - * If itemid is provided, load the object (item + base + plugin) from database + * If itemid is provided, load the object (item = base + plugin) from database * If evaluateparentcontent is true, load the parentitem parentcontent property too * * @param integer $itemid @@ -179,10 +240,8 @@ protected function item_load($itemid, $getparentcontent) { debugging($message, DEBUG_DEVELOPER); } - $context = \context_module::instance($this->cm->id); - - // Some item, like pagebreak or fieldsetend, may be free of the plugin table. - if ($this->uses_db_table()) { + // Some item, like pagebreak or fieldsetend, may do not use the plugin table. + if ($this->get_usesplugintable()) { $tablename = 'surveypro'.$this->type.'_'.$this->plugin; $sql = 'SELECT *, i.id as itemid, p.id as pluginid FROM {surveypro_item} i @@ -194,28 +253,30 @@ protected function item_load($itemid, $getparentcontent) { WHERE i.id = :itemid'; } + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin']; if ($record = $DB->get_record_sql($sql, ['itemid' => $itemid])) { - foreach ($record as $option => $value) { - $this->{$option} = $value; + foreach ($record as $field => $value) { + if (in_array($field, $unrelevantfields)) { + continue; + } + $method = 'set_'.$field; + $this->{$method}($value); } - // Plugins not using contentformat (only Fieldset, at the moment) are satisfied. + // Plugins not using contentformat (only Fieldset and pagebreak, at the moment) are satisfied. // Pagebreak and fieldsetend are missing content too. - // Special care to fields with format. - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - foreach ($fieldsusingformat as $fieldname => $filearea) { - $this->{$fieldname} = file_rewrite_pluginfile_urls( - $this->{$fieldname}, 'pluginfile.php', $context->id, - 'mod_surveypro', $filearea, $itemid - ); - } + if (isset($this->content) && strpos($this->content, '@@PLUGINFILE@@/')) { // Pagebreak don't use $this->content. + // Special care to fields with format. + $this->content = file_rewrite_pluginfile_urls( + $this->content, 'pluginfile.php', $this->context->id, + 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid + ); } - unset($this->id); // I do not care it. I already heave: itemid and pluginid. $this->itemname = SURVEYPRO_ITEMPREFIX.'_'.$this->type.'_'.$this->plugin.'_'.$this->itemid; if ($getparentcontent && $this->parentid) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $this->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $this->parentid); $this->parentcontent = $parentitem->parent_decode_child_parentvalue($this->parentvalue); } } else { @@ -227,7 +288,7 @@ protected function item_load($itemid, $getparentcontent) { /** * Verify the validity of contents of the record. * - * for instance: age not greater than maximum age + * For instance: age not greater than maximum age. * * @param \stdClass $record * @return void @@ -245,6 +306,15 @@ public function item_force_coherence($record) { * √ surveyproid * √ type * √ plugin + * √ content + * √ contentformat + * √ required + * √ indent + * √ position + * √ customnumber + * √ hideinstructions + * √ variable + * √ extranote * √ hidden * √ insearchform * √ reserved @@ -255,14 +325,6 @@ public function item_force_coherence($record) { * √ timecreated * √ timemodified * - * in spite of this, here I also get: - * hideinstructions - * required - * - * in addition, here I also make cleanup of: - * extranote - * parentvalue - * * The following settings will be calculated later: * sortindex * formpage @@ -270,12 +332,7 @@ public function item_force_coherence($record) { * @param \stdClass $record * @return void */ - protected function get_common_settings($record) { - // You are going to change item content (maybe sortindex, maybe the parentitem) - // so, do not forget to reset items per page. - $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); - $utilitylayoutman->reset_pages(); - + protected function add_base_properties_to_record($record) { $timenow = time(); // Surveyproid. @@ -283,8 +340,10 @@ protected function get_common_settings($record) { // Plugin and type are already onboard. - // Checkboxes content. - $checkboxessettings = ['hidden', 'insearchform', 'reserved', 'hideinstructions', 'required']; + // Content and contentformat will be managed later. + + // Checkboxes values. + $checkboxessettings = ['required', 'hidden', 'hideinstructions', 'insearchform', 'reserved']; foreach ($checkboxessettings as $checkboxessetting) { if ($this->insetupform[$checkboxessetting]) { $record->{$checkboxessetting} = isset($record->{$checkboxessetting}) ? 1 : 0; @@ -313,15 +372,16 @@ protected function get_common_settings($record) { // Because of this, even if the user writes, for instance, "bread\nmilk" to parentvalue // I have to encode it to key(bread);key(milk). if (!empty($record->parentid)) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $record->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $record->parentid); $record->parentvalue = $parentitem->parent_encode_child_parentcontent($record->parentcontent); unset($record->parentcontent); // Why do I drop $record->parentcontent? } } /** - * Item save - * Executes surveyproitem_<> global level actions + * Item save. + * + * Executes surveypro(field|format)_<> global level actions * this is the save point of the global part of each plugin * * Here is the explanation of $this->itemeditingfeedback @@ -353,80 +413,66 @@ protected function get_common_settings($record) { * (digit 5) == 1: a chain of children items inherited reserved access because this item (as parent) was changed to reserved * * @param object $record - * @return void + * @return int $record->itemid */ public function item_save($record) { global $DB, $COURSE; - $context = \context_module::instance($this->cm->id); + $this->add_base_properties_to_record($record); $utilitysubmissionman = new utility_submission($this->cm, $this->surveypro); $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); $hassubmission = $utilitylayoutman->has_submissions(false); + // You are going to change item content (maybe sortindex, maybe the parentitem) + // so, do not forget to reset items per page. + $utilitylayoutman->reset_pages(); + $tablename = 'surveypro'.$this->type.'_'.$this->plugin; $this->itemeditingfeedback = SURVEYPRO_NOFEEDBACK; - // Does this record need to be saved as new record or as un update of a preexisting record? - if (empty($record->itemid)) { - // Item is new. + // Is this a new item or does it already exist? + if (empty($record->itemid)) { // Item is new. // Sortindex. $sql = 'SELECT COUNT(\'x\') FROM {surveypro_item} WHERE surveyproid = :surveyproid - AND sortindex > 0'; - $whereparams = ['surveyproid' => $this->cm->instance]; + AND sortindex > :sortindex'; + $whereparams = ['surveyproid' => $this->cm->instance, 'sortindex' => 0]; $record->sortindex = 1 + $DB->count_records_sql($sql, $whereparams); // Itemid. try { $transaction = $DB->start_delegated_transaction(); + // Before saving validate the variable name. + $this->item_validate_variablename($record); if ($itemid = $DB->insert_record('surveypro_item', $record)) { // First surveypro_item save. - // Now think to $tablename. - if ($this->uses_db_table()) { - // Before saving to the the plugin table, validate the variable name. - $this->item_validate_variablename($record, $itemid); - - $record->itemid = $itemid; - if ($pluginid = $DB->insert_record($tablename, $record)) { // First save of $tablename. - $this->itemeditingfeedback += 1; // 0*2^1+1*2^0. - } - } else { - $record->itemid = $itemid; - } - } - - // Special care to "editors". Remember that content and contentformat are in plugin table. - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { + if ($this->insetupform['contentformat']) { + // Special care to the field content equipped with an editor. + $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $this->context]; + $record->id = $itemid; $record = file_postupdate_standard_editor( - $record, $fieldname, $editoroptions, - $context, 'mod_surveypro', $filearea, $record->itemid + $record, 'content', $editoroptions, + $this->context, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $record->id ); + $DB->update_record('surveypro_item', $record); } - if ($this->uses_db_table()) { - // Tablename. - $record->id = $pluginid; - - if (!$DB->update_record($tablename, $record)) { // Update of $tablename. - $this->itemeditingfeedback -= ($this->itemeditingfeedback % 2); // Whatever it was, now it is a fail. - // Otherwise... - // Leave the previous $this->itemeditingfeedback. - // If it was a success, leave it as now you got one more success. - // If it was a fail, leave it as you can not cover the previous fail. + // Now think to $tablename. + $record->itemid = $itemid; // Always give a value to $record->itemid as it is returned by the method. + if ($this->get_usesplugintable()) { + if ($pluginid = $DB->insert_record($tablename, $record)) { // First save of $tablename. + $this->itemeditingfeedback += 1; // 0*2^1+1*2^0. } - // Record->content follows standard flow and has already been saved at first save time. } } $transaction->allow_commit(); // Event: item_created. - $eventdata = ['context' => $context, 'objectid' => $itemid]; + $eventdata = ['context' => $this->context, 'objectid' => $itemid]; $eventdata['other'] = ['type' => $record->type, 'plugin' => $record->plugin, 'view' => SURVEYPRO_NEWITEM]; $event = \mod_surveypro\event\item_created::create($eventdata); $event->trigger(); @@ -443,17 +489,6 @@ public function item_save($record) { } else { // Item already exists. - // Special care to "editors". - if ($fieldsusingformat = $this->get_fieldsusingformat()) { - $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { - $record = file_postupdate_standard_editor( - $record, $fieldname, $editoroptions, - $context, 'mod_surveypro', $filearea, $record->itemid - ); - } - } - // Begin of: Hide/unhide part 1. $oldhidden = $this->get_hidden(); // Used later. // End of: hide/unhide 1. @@ -465,19 +500,27 @@ public function item_save($record) { // Sortindex. // Doesn't change at item editing time. - // Surveypro_item. + // Mandatory id. $record->id = $record->itemid; try { $transaction = $DB->start_delegated_transaction(); - if ($DB->update_record('surveypro_item', $record)) { - if ($this->uses_db_table()) { - // Before saving to the plugin table, validate the variable name. - $this->item_validate_variablename($record, $record->itemid); + if ($this->insetupform['contentformat']) { + // Special care to "editors". + $editoroptions = ['trusttext' => true, 'subdirs' => false, 'maxfiles' => -1, 'context' => $this->context]; + $record = file_postupdate_standard_editor( + $record, 'content', $editoroptions, + $this->context, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $record->id + ); + } - $record->id = $record->pluginid; + // Variable. + $this->item_validate_variablename($record); + if ($DB->update_record('surveypro_item', $record)) { + if ($this->get_usesplugintable()) { + $record->id = $record->pluginid; if ($DB->update_record($tablename, $record)) { $this->itemeditingfeedback += 3; // 1*2^1+1*2^0 alias: editing + success. } else { @@ -495,7 +538,7 @@ public function item_save($record) { $this->item_manage_chains($record->itemid, $oldhidden, $record->hidden, $oldreserved, $record->reserved); // Event: item_modified. - $eventdata = ['context' => $context, 'objectid' => $record->itemid]; + $eventdata = ['context' => $this->context, 'objectid' => $record->itemid]; $eventdata['other'] = ['type' => $record->type, 'plugin' => $record->plugin, 'view' => SURVEYPRO_NEWITEM]; $event = \mod_surveypro\event\item_modified::create($eventdata); $event->trigger(); @@ -541,11 +584,10 @@ public function item_save($record) { /** * Validate the name of the variable to make sure it is unique. * - * @param stdobject $record - * @param integer $itemid + * @param object $record * @return void */ - public function item_validate_variablename($record, $itemid) { + public function item_validate_variablename($record) { global $DB; // If variable does not exist. @@ -553,41 +595,33 @@ public function item_validate_variablename($record, $itemid) { return; } - // Verify variable was set. If not, set $userchoosedname and $basename starting from the plugin name. + // Define $testname and $basename. if (!isset($record->variable) || empty($record->variable)) { - $userchoosedname = $this->plugin.'_001'; + $testname = $this->plugin.'_001'; $basename = $this->plugin; } else { - $userchoosedname = clean_param($record->variable, PARAM_TEXT); - if (preg_match('~^(.*)_[0-9]{3}$~', $userchoosedname, $matches)) { + $testname = clean_param($record->variable, PARAM_TEXT); + if (preg_match('~^(.*)_[0-9]{3}$~', $testname, $matches)) { $basename = $matches[1]; } else { - $basename = $userchoosedname; + $basename = $testname; } } - $testname = $userchoosedname; - - // Bloody Editing Teachers can create a boolean element, for instance, naming it 'age_001' - // having an age element named 'age_001' already onboard! - // Because of this I need to make as much queries as the number of used plugins in my surveypro! - // Get the list of used plugin. - $utilitysubmissionman = new utility_submission($this->cm, $this->surveypro); - $pluginlist = $utilitysubmissionman->get_used_plugin_list(SURVEYPRO_TYPEFIELD); - - $usednames = []; - foreach ($pluginlist as $plugin) { - $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; - $sql = 'SELECT p.itemid, p.variable + // Get all the other variables used in this surveypro. (eventually exluding the current one) + if (!isset($record->itemid) || empty($record->itemid)) { + $whereparams = ['surveyproid' => (int)$record->surveyproid]; + $usednames = $DB->get_records_menu('surveypro_item', $whereparams, 'id', 'id, variable'); + } else { + $whereparams = ['surveyproid' => (int)$record->surveyproid, 'itemid' => $record->itemid]; + $sql = 'SELECT i.id, i.variable FROM {surveypro_item} i - JOIN {'.$tablename.'} p ON p.itemid = i.id - WHERE ((i.surveyproid = :surveyproid) - AND (p.itemid <> :itemid))'; - $whereparams = ['surveyproid' => (int)$record->surveyproid, 'itemid' => $itemid]; - $usednames += $DB->get_records_sql_menu($sql, $whereparams); + WHERE ( (i.surveyproid = :surveyproid) + AND (i.id <> :itemid) )'; + $usednames = $DB->get_records_sql_menu($sql, $whereparams); } - // Verify the $userchoosedname name is unique. If not, change it. + // Verify the $testname name is unique. If not, change it. $i = 0; // If the name is a duplicate, concatenate a suffix starting from 1. while (in_array($testname, $usednames)) { $i++; @@ -598,8 +632,8 @@ public function item_validate_variablename($record, $itemid) { } /** - * Show/Hide chains of descendant/ancestors on the basis of the settings provided in the current editing process - * Make reserved/standard chains of descendant/ancestors on the basis of the settings provided in the current editing process + * Show/Hide chains of descendant/ancestors on the basis of the settings provided in the current editing process. + * Make reserved/standard chains of descendant/ancestors on the basis of the settings provided in the current editing process. * * @param integer $itemid * @param boolean $oldhidden @@ -609,7 +643,6 @@ public function item_validate_variablename($record, $itemid) { * @return void */ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserved, $newreserved) { - $context = \context_module::instance($this->cm->id); // Now hide or unhide (whether needed) chain of ancestors or descendents. if ($this->itemeditingfeedback & 1) { // Bitwise logic, alias: if the item was successfully saved. @@ -618,23 +651,23 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve if ($oldhidden != $newhidden) { $action = ($oldhidden) ? SURVEYPRO_SHOWITEM : SURVEYPRO_HIDEITEM; - $itemsetupman = new layout_itemsetup($this->cm, $context, $this->surveypro); - $itemsetupman->setup(); - $itemsetupman->set_type($this->type); - $itemsetupman->set_plugin($this->plugin); - $itemsetupman->set_itemid($itemid); - $itemsetupman->set_action($action); - $itemsetupman->set_view(SURVEYPRO_NOMODE); - $itemsetupman->set_confirm(SURVEYPRO_CONFIRMED_YES); + $itemlistman = new layout_itemlist($this->cm, $this->context, $this->surveypro); + $itemlistman->setup(); + $itemlistman->set_type($this->type); + $itemlistman->set_plugin($this->plugin); + $itemlistman->set_itemid($itemid); + $itemlistman->set_action($action); + // $itemlistman->set_view(SURVEYPRO_NOMODE); // <-- Where is it coming from? + $itemlistman->set_confirm(SURVEYPRO_CONFIRMED_YES); // Begin of: Hide/unhide part 2. if ( ($oldhidden == 1) && ($newhidden == 0) ) { - $itemsetupman->item_show_execute(); + $itemlistman->item_show_execute(); // A chain of parent items was shown. $this->itemeditingfeedback += 4; // 1*2^2. } if ( ($oldhidden == 0) && ($newhidden == 1) ) { - $itemsetupman->item_hide_execute(); + $itemlistman->item_hide_execute(); // Chain of children items was hided. $this->itemeditingfeedback += 8; // 1*2^3. } @@ -645,24 +678,24 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve if ($oldreserved != $newreserved) { $action = ($oldreserved) ? SURVEYPRO_MAKEAVAILABLE : SURVEYPRO_MAKERESERVED; - $itemsetupman = new layout_itemsetup($this->cm, $context, $this->surveypro); - $itemsetupman->setup(); - $itemsetupman->set_type($this->type); - $itemsetupman->set_plugin($this->plugin); - $itemsetupman->set_itemid($itemid); - $itemsetupman->set_action($action); - $itemsetupman->set_view(SURVEYPRO_NOMODE); - $itemsetupman->set_confirm(SURVEYPRO_CONFIRMED_YES); + $itemlistman = new layout_itemlist($this->cm, $this->context, $this->surveypro); + $itemlistman->setup(); + $itemlistman->set_type($this->type); + $itemlistman->set_plugin($this->plugin); + $itemlistman->set_itemid($itemid); + $itemlistman->set_action($action); + // $itemlistman->set_view(SURVEYPRO_NOMODE); + $itemlistman->set_confirm(SURVEYPRO_CONFIRMED_YES); // Begin of: Make reserved/free part 2. if ( ($oldreserved == 1) && ($newreserved == 0) ) { - if ($itemsetupman->item_makeavailable_execute()) { + if ($itemlistman->item_makeavailable_execute()) { // A chain of parents items inherited free access. $this->itemeditingfeedback += 16; // 1*2^4. } } if ( ($oldreserved == 0) && ($newreserved == 1) ) { - if ($itemsetupman->item_makereserved_execute()) { + if ($itemlistman->item_makereserved_execute()) { // A chain of children items inherited reserved access. $this->itemeditingfeedback += 32; // 1*2^5. } @@ -673,21 +706,20 @@ private function item_manage_chains($itemid, $oldhidden, $newhidden, $oldreserve } /** - * redefine the parentvalue of children items according to the new parameters of the just saved parent item. + * Redefine the parentvalue of children items according to the new parameters of the just saved parent item. * - * for instance: if I removed an item from the parent item - * while some children were using that item as condition to appear, - * I drop that item from the parentvalue of that children + * For instance: if I removed an item from the parent item + * while some children were using that item as parent, + * I drop that item from the parentvalue of that children. * * @return void */ public function item_update_childrenparentvalue() { global $DB, $CFG; - $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; - if ($classname::get_canbeparent()) { - // Take care: you can not use $this->get_content_array(SURVEYPRO_VALUES, 'options') to evaluate values - // because $item was loaded before last save, so $this->get_content_array(SURVEYPRO_VALUES, 'options') + if ($this->get_canbeparent()) { + // Take care: you can not use $this->get_textarea_content(SURVEYPRO_VALUES, 'options') to evaluate values + // because $item was loaded before last save, so $this->get_textarea_content(SURVEYPRO_VALUES, 'options') // will still return the previous values. $childrenitems = $DB->get_records('surveypro_item', ['parentid' => $this->itemid], 'id', 'id, parentvalue'); @@ -720,30 +752,73 @@ protected function item_builtin_string_load_support() { return; } + // If this routine fails it is difficult to delete each field from the surveypro using graphic user interface + // because the mdl_surveypro.template is not empty. + // To make it simple to escape trouble in case of error I delete mdl_surveypro.template now + // with the promise to set it again at the end of this method. + $DB->set_field('surveypro', 'template', null, ['id' => $surveyproid]); + // Take care: I verify the existence of the english folder even if, maybe, I will ask for strings in a different language. if (!file_exists($CFG->dirroot.'/mod/surveypro/template/'.$template.'/lang/en/surveyprotemplate_'.$template.'.php')) { // This template does not support multilang. return; } - if ($multilangfields = $this->get_multilang_fields()) { // Pagebreak and fieldsetend have no multilang_fields. - foreach ($multilangfields as $plugin) { - foreach ($plugin as $fieldname) { - // Backward compatibility. - // In the frame of https://github.com/kordan/moodle-mod_surveypro/pull/447 few multilang fields were added. - // This was really a mandatory addition but, - // opening surveypros created (from mastertemplates) before this addition, - // I may find that they don't have new added fields filled in the database - // so the corresponding property $this->{$fieldname} does not exist. - if (isset($this->{$fieldname})) { - $stringkey = $this->{$fieldname}; - $this->{$fieldname} = get_string($stringkey, 'surveyprotemplate_'.$template); - } else { - $this->{$fieldname} = ''; + if ($multilangfields = $this->get_multilang_fields(false)) { // Pagebreak and fieldsetend have no multilang_fields. + foreach ($multilangfields as $table => $mlfields) { + foreach ($mlfields as $mlfield) { + // I am using a surveypro built on a mastertemplate. + // In the template.xml I may have had, for instance, boolean_extranote_02 + // I saved (during parent::item_load) the content of template.xml in the properies of this item. + // (alias: $this->extranote = "boolean_extranote_02") + // Now, cycling over each multilang field, + // I find the key of the corresponding lang string in the properies of this item. + + // Each property was set because of the query executed in item_load but + // it may be that, for instance, I had mdl_surveypro_ite.extranote = null. + // In this case I have $this->extranote empty and this is why I need: if (!empty($this->{$mlfield})) {. + + if (!empty($this->{$mlfield})) { + // At the beginning $this->{$mlfield} may be "boolean_content_02". + $stringkey = $this->{$mlfield}; + $this->{$mlfield} = get_string($stringkey, 'surveyprotemplate_'.$template); + // Now $this->{$mlfield} is "content contains, now, '@@PLUGINFILE@@/' that did not contain before. + if (strpos($this->content, '@@PLUGINFILE@@/')) { + // Am I sure the file is already into SURVEYPRO_ITEMCONTENTFILEAREA + $fs = get_file_storage(); + $templateman = new templatebase($this->cm, $this->context, $this->surveypro); + + $regex = '~src="@@PLUGINFILE@@\/([^"]*)"~'; + if (preg_match_all($regex, $this->content, $matches)) { + foreach ($matches[1] as $filename) { + if (!$fs->get_file($this->context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $this->itemid, '/', $filename)) { + // I am using a surveypro built on a mastertemplate. + // Let's suppose an admin added a new lang file describing new pictures. + // Am I sure each new picture of the current lang file was loaded in the filearea? + // Take in mind that ONLY the files of the lang file in the language in use + // at mastertemplate apply time were loaded to filearea. + $templateman->load_new_files_from_lang($template, $this->itemid); + // Once you loaded each new file, don't check anymore. + break; + } } } + + // Special care to fields with format. + $this->content = file_rewrite_pluginfile_urls( + $this->content, 'pluginfile.php', $this->context->id, + 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $this->itemid + ); } } + + // As promised at the beginning of this method: + $DB->set_field('surveypro', 'template', $template, ['id' => $surveyproid]); } /** @@ -760,21 +835,22 @@ protected function item_builtin_string_load_support() { * [minutes] => 00 * ) * - * @param integer $time - * @return void + * @param integer $unixtime + * @return array $dateout */ - protected function item_split_unix_time($time) { - $datestring = date('Y_m_d_H_i', $time); + protected function item_split_unix_time($unixtime) { + $datestring = gmdate('Y_m_d_H_i', $unixtime); // 2012_07_11_16_03. - $getdate = []; - [$getdate['year'], $getdate['mon'], $getdate['mday'], $getdate['hours'], $getdate['minutes']] = explode('_', $datestring); + $dateout = []; + [$dateout['year'], $dateout['mon'], $dateout['mday'], $dateout['hours'], $dateout['minutes']] = explode('_', $datestring); + $dateout = array_map('intval', $dateout); - return $getdate; + return $dateout; } /** - * Does this item live into a form page?. + * Does this item live into a form page? * * Each item lives into a form page but not the pagebreak * @@ -785,7 +861,7 @@ public function item_uses_form_page() { } /** - * Does this item allow the question in left position?. + * Does this item allow the question in left position? * * Each item allows the question in left position but not the rate * @@ -796,7 +872,7 @@ public function item_left_position_allowed() { } /** - * clean the content of the field $record->{$field} (remove blank lines, trailing \r). + * Clean the content of the field $record->{$field} (remove blank lines, trailing \r). * * @param object $record Item record * @param array $fieldlist List of fields to clean @@ -816,21 +892,21 @@ protected function item_clean_textarea_fields($record, $fieldlist) { } /** - * This method defines if an item can be switched to mandatory or not. + * This method defines if an item can be set to mandatory or not. * - * Used by layout_itemsetup->display_items_table() to define the icon to show + * Used by layout_itemsetup->display_items_table() to define the icon to show. * * There are two types of fields. * 1) those for which (like the boolean) * defaultoption discriminates on the desired type of default: "Custom", "Invite", "No response" - * and, if defaultoption == "Custom", defaultvalue intervenes and declares which custom default is chosen. + * and, if defaultoption == "Custom", defaultvalue defines which custom default is choosen. * * 2) those for which (like multiselect). * noanswerdefault = 1 means "No response". * * @return boolean */ - public function item_canbemandatory() { + public function item_canbesettomandatory() { $return = true; if (isset($this->defaultoption)) { if ($this->defaultoption == SURVEYPRO_NOANSWERDEFAULT) { @@ -850,16 +926,27 @@ public function item_canbemandatory() { } /** - * Add to the item record that is going to be saved, items that can not be omitted with default value - * They, maybe, will be overwritten + * Add to the item record that is going to be saved, items that can not be omitted with default value. + * They, maybe, will be overwritten. * * @param \stdClass $record * @return void */ - public function item_add_mandatory_base_fields(&$record) { + public function item_add_fields_default_to_parent_table(&$record) { + $record->content = ''; + $record->contentformat = 1; + $record->required = 0; + $record->indent = 0; + $record->position = 0; + $record->customnumber = ''; + $record->hideinstructions = 0; + $record->variable = ''; + $record->extranote = ''; $record->hidden = 0; $record->insearchform = 0; $record->reserved = 0; + // $record->parentid = 0; + // $record->parentvalue = 0; $record->formpage = 0; $record->timecreated = time(); } @@ -879,36 +966,18 @@ public function item_add_color_unifier($mform) { } /** - * Get if the plugin uses a table into the db. - * - * @return if the plugin uses a personal table in the db. - */ - public function uses_db_table() { - return true; - } - - /** - * Uses mandatory database field? + * Uses mandatory attribute? * * Each item uses teh "mandatory" database field but not the autofill * * @return whether the item uses the "mandatory" database field */ - public static function item_uses_mandatory_dbfield() { + public static function has_mandatoryattribute() { return true; } /** - * Returns if the field plugin needs contentformat - * - * @return bool - */ - public static function response_uses_format() { - return false; - } - - /** - * Returns if the item has children + * Returns if the item has children. * * @return bool */ @@ -922,7 +991,7 @@ public function item_has_children() { } /** - * Returns if the item is a child + * Returns if the item is a child. * * @return bool */ @@ -937,10 +1006,35 @@ public function item_is_child() { return $return; } + /** + * List the fields that this plugin is expected to save as NULL in the database. + * + * @return array + */ + public function item_expected_null_fields() { + $expectednull = []; + foreach ($this->insetupform as $field => $value) { + if (!$value) { + $expectednull[] = $field; + } + } + + return $expectednull; + } + // MARK response. /** - * Report how the sql query does fit for this plugin + * Returns if the field plugin needs contentformat. + * + * @return bool + */ + public static function response_uses_format() { + return false; + } + + /** + * Report how the sql query does fit for this plugin. * * @param int $itemid * @param string $searchrestriction @@ -956,233 +1050,540 @@ public static function response_get_whereclause($itemid, $searchrestriction) { // MARK set. /** - * Defines presets for the editor field of surveyproitem in itembaseform.php. - * - * (copied from moodle20/cohort/edit.php) - * - * Some examples: - * Each SURVEYPRO_ITEMFIELD has: $this->insetupform['content'] == true and $fieldsusingformat == ['content'] - * Fieldset plugin has: $this->insetupform['content'] == true and $fieldsusingformat == null - * Pagebreak plugin has: $this->insetupform['content'] == false and $fieldsusingformat == null + * Set itemid. * + * @param int $itemid * @return void */ - public function set_editor() { - if (!$fieldsusingformat = $this->get_fieldsusingformat()) { - return; - } - - $context = \context_module::instance($this->cm->id); - // I have to set 'trusttext' => false because 'noclean' is ignored if trusttext is enabled! - $editoroptions = ['noclean' => true, 'subdirs' => true, 'maxfiles' => -1, 'context' => $context]; - foreach ($fieldsusingformat as $fieldname => $filearea) { - file_prepare_standard_editor($this, $fieldname, $editoroptions, $context, 'mod_surveypro', $filearea, $this->itemid); - } + public function set_itemid($itemid) { + $this->itemid = $itemid; } - // MARK get. - /** - * Get course module. + * Set pluginid. * - * @return the content of $cm property + * @param int $pluginid + * @return void */ - public function get_cm() { - return $this->cm; + public function set_pluginid($pluginid) { + $this->pluginid = $pluginid; } /** - * Get surveyproid. + * Set type. * - * @return the content of $surveyproid property + * @param string $type + * @return void */ - public function get_surveyproid() { - return $this->cm->instance; + public function set_type($type) { + $this->type = $type; } /** - * Get the list of fields using format. + * Set plugin. * - * @return the content of $fieldsusingformat property + * @param string $plugin + * @return void */ - public function get_fieldsusingformat() { - return $this->fieldsusingformat; + public function set_plugin($plugin) { + $this->plugin = $plugin; } /** - * Get if the plugin uses the position of options to save user answers. + * Set content. * - * @return bool The plugin uses the position of options to save user answers. + * @param string $content + * @return void */ - public function get_uses_positional_answer() { - return false; + public function set_content($content) { + $this->content = $content; } /** - * Get the preset for the item setup form. + * Set contentformat. * - * @return array $data + * @param string $contentformat + * @return void */ - public function get_itemform_preset() { - if (!empty($this->itemid)) { - $data = get_object_vars($this); - - // Just to save few nanoseconds. - unset($data['cm']); - unset($data['surveypro']); - unset($data['insetupform']); - } else { - $data = []; - $data['type'] = $this->type; - $data['plugin'] = $this->plugin; - } - - return $data; + public function set_contentformat($contentformat) { + $this->contentformat = $contentformat; } /** - * Get if the mform element corresponding to the propery $itemformelement has to be shown in the form. + * Set indent. * - * @param string $itemformelement - * @return true if the corresponding element has to be shown in the form; false otherwise + * @param int $indent of the item in the user form + * @return void */ - public function get_insetupform($itemformelement) { - return $this->insetupform[$itemformelement]; + public function set_indent($indent) { + $this->indent = $indent; } /** - * Get item id. + * Set position. * - * @return the content of $itemid property + * @param int $position of the content in the item in the form + * @return void */ - public function get_itemid() { - if (isset($this->itemid)) { - return $this->itemid; - } else { - return 0; - } + public function set_position($position) { + $this->position = $position; } /** - * Get type. + * Set customnumber. * - * @return the content of $type property + * @param string $customnumber of the item + * @return void */ - public function get_type() { - return $this->type; + public function set_customnumber($customnumber) { + $this->customnumber = $customnumber; } /** - * Get plugin. + * Set hideinstructions. * - * @return the content of $plugin property + * @param int $hideinstructions + * @return void */ - public function get_plugin() { - return $this->plugin; + public function set_hideinstructions($hideinstructions) { + $this->hideinstructions = (isset($hideinstructions) && !empty($hideinstructions)) ? 1 : 0; } /** - * Get content. + * Set extranote. * - * @return the content of $content property + * @param string $extranote for the item + * @return void */ - public function get_content() { - $options = ['overflowdiv' => false, 'allowid' => true, 'para' => false]; - return format_text($this->content, $this->contentformat, $options); + public function set_extranote($extranote) { + $this->extranote = $extranote; } /** - * Get content format. + * Set hidden. * - * @return the content of $contentformat property + * @param int $hidden + * @return void */ - public function get_contentformat() { - return $this->contentformat; + public function set_hidden($hidden) { + $this->hidden = (isset($hidden) && !empty($hidden)) ? 1 : 0; } /** - * Get plugin id. + * Set insearchform. * - * @return the content of $pluginid property + * @param int $insearchform + * @return void */ - public function get_pluginid() { - if (isset($this->pluginid)) { - return $this->pluginid; - } else { - return 0; - } + public function set_insearchform($insearchform) { + $this->insearchform = (isset($insearchform) && !empty($insearchform)) ? 1 : 0; } /** - * Get item name. + * Set reserved. * - * @return the content of $itemname property + * @param int $reserved + * @return void */ - public function get_itemname() { - return $this->itemname; + public function set_reserved($reserved) { + $this->reserved = (isset($reserved) && !empty($reserved)) ? 1 : 0; } /** - * Get hidden. + * Set sortindex. * - * @return the content of $hidden property + * @param int $sortindex + * @return void */ - public function get_hidden() { - return $this->hidden; + public function set_sortindex($sortindex) { + $this->sortindex = $sortindex; } /** - * Get in search form. + * Set formpage. * - * @return the content of $insearchform property + * @param int $formpage + * @return void */ - public function get_insearchform() { - return $this->insearchform; + public function set_formpage($formpage) { + $this->formpage = $formpage; } /** - * Get reserved. + * Set parentid. * - * @return the content of $reserved property + * @param int $parentid + * @return void */ - public function get_reserved() { - return $this->reserved; + public function set_parentid($parentid) { + $this->parentid = $parentid; } /** - * Get sortindex. + * Set parentvalue. * - * @return the content of $sortindex property + * @param int $parentvalue + * @return void */ - public function get_sortindex() { - return $this->sortindex; + public function set_parentvalue($parentvalue) { + $this->parentvalue = $parentvalue; } /** - * Get form page. + * Set timemodified. * - * @return the content of $formpage property + * @param int $timemodified + * @return void */ - public function get_formpage() { - return $this->formpage; + public function set_timemodified($timemodified) { + $this->timemodified = $timemodified; } /** - * Parse $this->labelother in $value and $label. + * Set timecreated. * - * @return $value - * @return $label + * @param int $timecreated + * @return void */ - protected function get_other() { - if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { - $label = trim($match[1]); - $value = trim($match[2]); - } else { - $label = trim($this->labelother); - $value = ''; - } - - return [$value, $label]; + public function set_timecreated($timecreated) { + $this->timecreated = $timecreated; + } + + /** + * Defines presets for the editor field of surveyproitem in itembaseform.php. + * + * (copied from moodle20/cohort/edit.php) + * + * Some examples: + * Each SURVEYPRO_ITEMFIELD: + * $this->insetupform['content'] == true + * $this->insetupform['contentformat'] = true + * + * Fieldset plugin: + * $this->insetupform['content'] == true + * $this->insetupform['contentformat'] = false + * + * Pagebreak plugin: + * $this->insetupform['content'] == false + * $this->insetupform['contentformat'] = false + * + * @return void + */ + public function set_editor() { + $data = new \stdClass(); + $data->content = $this->get_content(); + + if ($this->insetupform['contentformat']) { + // I have to set 'trusttext' => false because 'noclean' is ignored if trusttext is enabled! + $editoroptions = ['noclean' => true, 'subdirs' => true, 'maxfiles' => -1, 'context' => $this->context]; + $filearea = SURVEYPRO_ITEMCONTENTFILEAREA; + + $data->content = $this->get_content(); + $data->contentformat = $this->get_contentformat(); + $data = file_prepare_standard_editor( + $data, 'content', $editoroptions, $this->context, 'mod_surveypro', $filearea, $this->itemid + ); + } + + return $data; + } + + /** + * Set variable. + * + * @param string $variable + * @return void + */ + public function set_variable($variable) { + $variable = format_string($variable); + $this->variable = $variable; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $condition = false; + $condition = $condition || ($defaultoption == SURVEYPRO_CUSTOMDEFAULT); + $condition = $condition || ($defaultoption == SURVEYPRO_INVITEDEFAULT); + $condition = $condition || ($defaultoption == SURVEYPRO_NOANSWERDEFAULT); + if (!$condition) { + $message = 'Passed defaultoption is not allowed.'; + debugging($message, DEBUG_DEVELOPER); + } + + $this->defaultoption = $defaultoption; + } + + /** + * Set required. + * + * Introduced as needed by unit test. + * + * @param string $required + * @return void + */ + public function set_required($required) { + $this->required = (isset($required) && !empty($required)) ? 1 : 0; + } + + /** + * Set options. + * + * Introduced as needed by unit test. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + // MARK get. + + /** + * Make the list of the fields using multilang. + * This is the "default" list that is supposed to be empty because Pagebreak and fieldset inherit from it + * + * @param boolean $includemetafields + * @return array of fields + */ + abstract public function get_multilang_fields($includemetafields=true); + + /** + * Get course module. + * + * @return the content of $cm property + */ + public function get_cm() { + return $this->cm; + } + + /** + * Get surveyproid. + * + * @return the content of $surveyproid property + */ + public function get_surveyproid() { + return $this->cm->instance; + } + + /** + * Get type. + * + * @return the content of $type property + */ + public function get_type() { + return $this->type; + } + + /** + * Get plugin. + * + * @return the content of $plugin property + */ + public function get_plugin() { + return $this->plugin; + } + + /** + * Get content. + * + * @return the content of $content property + */ + public function get_content() { + $options = ['overflowdiv' => false, 'allowid' => true, 'para' => false]; + return format_text($this->content, $this->contentformat, $options); + } + + /** + * Get content format. + * + * @return the content of $contentformat property + */ + public function get_contentformat() { + return $this->contentformat; + } + + /** + * Get content_editor. + * + * @return the content of $contentformat property + */ + public function get_content_editor() { + return $this->content_editor; + } + + /** + * Get itemid. + * + * @return the content of $itemid property + */ + public function get_itemid() { + if (isset($this->itemid)) { + $return = $this->itemid; + } else { + $return = 0; + } + + return $return; + } + + /** + * Get plugin id. + * + * @return the content of $pluginid property + */ + public function get_pluginid() { + if (isset($this->pluginid)) { + $return = $this->pluginid; + } else { + $return = 0; + } + + return $return; + } + + /** + * Get item name. + * + * @return the content of $itemname property + */ + public function get_itemname() { + return $this->itemname; + } + + /** + * This method returns the list of the field used by the plugin. + * + * AT THE MOMENT, this method is never used. + * + * @param string $plugin + * @param string $type + * @return array + */ + public function get_plugin_fields($plugin, $type) { + global $CFG; + + if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { + $message = '$type and $plugin must be provided both or none.'; + debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); + } + + $installxmls = ['surveypro_item', 'db/install.xml']; + if (!empty($type) && !empty($plugin)) { + $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; + // Some plugins are missing the install.xml because they don't have specific attributes. + if (file_exists($installxml)) { + $installxmls['surveypro'.$type.'_'.$plugin] = $type.'/'.$plugin.'/db/install.xml'; + } + } + + foreach ($installxmls as $targettable => $installxml) { + $currentfile = $CFG->dirroot.'/mod/surveypro/'.$installxml; + $xmlall = simplexml_load_file($installxml); + foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. + foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. + $attributes = $xmltable->attributes(); + $tablename = $attributes['NAME']; + if ($tablename != $targettable) { + continue; + } + foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. + $curenttablefields = []; + foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. + $attributes = $xmlfield->attributes(); + $fieldname = $attributes['NAME']; + $curenttablefields[] = (string)$attributes['NAME']; + } + $fieldlist[$tablename] = $curenttablefields; + break; + } + // If the correct table has been found, don't go searching for one more table. Stop! + break; + } + // If the correct table has been found, don't go searching for one more table. Stop! + break; + } + } + + return $fieldlist; + } + + /** + * Get if the plugin uses the position of options to save user answers. + * + * @return bool The plugin uses the position of options to save user answers. + */ + public function get_uses_positional_answer() { + return false; + } + + /** + * Get if the mform element corresponding to the propery $itemformelement has to be shown in the form. + * + * @param string $itemformelement + * @return true if the corresponding element has to be shown in the form; false otherwise + */ + public function get_insetupform($itemformelement) { + return $this->insetupform[$itemformelement]; + } + + /** + * Get hidden. + * + * @return the content of $hidden property + */ + public function get_hidden() { + // This property is common to EACH item plugin + $return = ((empty($this->hidden)) || ($this->hidden == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get insearchform. + * + * @return the content of $insearchform property + */ + public function get_insearchform() { + // This property is common to EACH item plugin + $return = ((empty($this->insearchform)) || ($this->insearchform == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get reserved. + * + * @return the content of $reserved property + */ + public function get_reserved() { + // This property is common to EACH item plugin + $return = ((empty($this->reserved)) || ($this->reserved == 0)) ? 0 : 1; + + return $return; + } + + /** + * Get sortindex. + * + * @return the content of $sortindex property + */ + public function get_sortindex() { + return $this->sortindex; + } + + /** + * Get formpage. + * + * @return the content of $formpage property + */ + public function get_formpage() { + return $this->formpage; } /** @@ -1192,15 +1593,17 @@ protected function get_other() { */ public function get_usesoptionother() { if (property_exists($this, 'labelother')) { - return !empty($this->labelother); + $return = !empty($this->labelother); } else { - return false; + $return = false; } + + return $return; } /** - * Get the content of textareas. Get the first or the second part of each row based on $content - * Each row is written with the format: + * Get the content of textareas. Get the first or the second part of each row based on $content. + * Each row is supposed to be written with the format: * value::label * or * label @@ -1209,9 +1612,9 @@ public function get_usesoptionother() { * @param string $field Name of the text area field, source of the multiline text * @return array $values */ - public function get_content_array($content, $field) { + public function get_textarea_content($content, $field) { if (($content != SURVEYPRO_VALUES) && ($content != SURVEYPRO_LABELS)) { - throw new Exception('Bad parameter passed to get_content_array'); + throw new Exception('Bad parameter passed to get_textarea_content'); } $index = ($content == SURVEYPRO_VALUES) ? 1 : 2; @@ -1231,16 +1634,19 @@ public function get_content_array($content, $field) { } /** - * Make the list of the fields using multilang - * This is the "default" list that is supposed to be empty because Pagebreak and fieldset inherit from it + * Provide the list of the fields of surveypro_item using multilang. * - * @return array of felds + * @param boolean $includemetafields true if you need filename and filecontent too. + * @return array the list of the fields of surveypro_item using multilang */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = []; + public function get_base_multilang_fields($includemetafields) { + if ($includemetafields) { + $return = ['content', 'filename', 'filecontent', 'extranote']; + } else { + $return = ['content', 'extranote']; + } - return $fieldlist; + return $return; } /** @@ -1282,14 +1688,17 @@ public function get_parentvalue() { * Get the requested property. * * @param string $field - * @return the content of the field whether defined + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { if (isset($this->{$field})) { - return $this->{$field}; + $method = 'get_'.$field; + $return = $this->{$method}(); } else { - return false; + $return = false; } + + return $return; } /** @@ -1308,29 +1717,29 @@ public function get_variable() { */ public function get_customnumber() { if (isset($this->customnumber)) { - return $this->customnumber; + $return = $this->customnumber; } else { - return false; + $return = false; } + + return $return; } /** * Get required. * - * @return bool false if the property is not set for the class (like, for instance, for autofill or label) - * int 0|1 acording to the property + * @return int 0|1 acording to the property + * bool false if the property is not set (like, for instance, for autofill or label) */ public function get_required() { // It may be not set as in page_break, autofill or some more. - if (!isset($this->required)) { - return false; + if (isset($this->required)) { + $return = empty($this->required) ? 0 : 1; } else { - if (empty($this->required)) { - return 0; - } else { - return 1; - } + $return = false; } + + return $return; } /** @@ -1352,11 +1761,14 @@ public function get_indent() { * @return the content of $hideinstructions property whether defined */ public function get_hideinstructions() { + // It may be not set in some plugin item if (isset($this->hideinstructions)) { - return $this->hideinstructions; + $return = empty($this->hideinstructions) ? 0 : 1; } else { - return false; + $return = false; } + + return $return; } /** @@ -1385,6 +1797,49 @@ public function get_extranote() { } } + /** + * Returns the list of common item properties. + * + * @return array $data + */ + public function get_base_properties() { + $baseproperties = [ + 'surveyproid', 'type', 'plugin', 'content', 'contentformat', 'required', 'indent', 'position', + 'customnumber', 'hideinstructions', 'variable', 'extranote', 'hidden', 'insearchform', 'reserved', + 'parentid', 'parentvalue', 'parentcontent', + ]; + + return $baseproperties; + } + + /** + * Prepare presets for itemsetuprform. + * + * @param array $pluginproperties + * @return array $data + */ + public function get_base_presets($pluginproperties) { + if (!empty($this->itemid)) { + $baseproperties = $this->get_base_properties(); + $properties = array_merge($baseproperties, $pluginproperties); + + $data = $this->set_editor(); // Now $data is a new \stdClass(). + $data->itemid = $this->get_itemid(); // Mandatory! + $data->pluginid = $this->get_pluginid(); // Mandatory! + foreach ($properties as $property) { + $method = 'get_'.$property; + $data->{$property} = $this->{$method}(); + } + // Parentcontent does not come from db. + } else { + $data = new \stdClass(); + $data->type = $this->type; + $data->plugin = $this->plugin; + } + + return $data; + } + /** * Get downloadformat. * @@ -1528,6 +1983,28 @@ public function get_itemeditingfeedback() { return $this->itemeditingfeedback; } + /** + * Does this item use a specific table? + * + * @return the content of the static property "usesplugintable" + */ + public function get_usesplugintable() { + $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; + + return $classname::$usesplugintable; + } + + /** + * Can this item be parent? + * + * @return the content of the static property "canbeparent" + */ + public function get_canbeparent() { + $classname = 'surveypro'.$this->type.'_'.$this->plugin.'\item'; + + return $classname::$canbeparent; + } + /** * Return the xml schema for surveypro_<> table. * @@ -1541,9 +2018,26 @@ public static function get_itembase_schema() { - - - + + + + + + + + + + + + + + + + + + + + @@ -1561,86 +2055,6 @@ public static function get_itembase_schema() { return $schema; } - // MARK set. - - /** - * Set contentformat. - * - * @param string $contentformat - * @return void - */ - public function set_contentformat($contentformat) { - $this->contentformat = $contentformat; - } - - /** - * Set variable. - * - * @param string $variable - * @return void - */ - public function set_variable($variable) { - $variable = format_string($variable); - $this->variable = $variable; - } - - /** - * Set defaultoption. - * - * Introduced as needed by unit test. - * - * @param string $defaultoption - * @return void - */ - public function set_defaultoption($defaultoption) { - $condition = false; - $condition = $condition || ($defaultoption == SURVEYPRO_CUSTOMDEFAULT); - $condition = $condition || ($defaultoption == SURVEYPRO_INVITEDEFAULT); - $condition = $condition || ($defaultoption == SURVEYPRO_NOANSWERDEFAULT); - if (!$condition) { - $message = 'Passed defaultoption is not allowed.'; - debugging($message, DEBUG_DEVELOPER); - } - - $this->defaultoption = $defaultoption; - } - - /** - * Set labelother. - * - * Introduced as needed by unit test. - * - * @param string $labelother - * @return void - */ - public function set_labelother($labelother) { - $this->labelother = (string)$labelother; - } - - /** - * Set required. - * - * Introduced as needed by unit test. - * - * @param string $required - * @return void - */ - public function set_required($required) { - $this->labelother = $required; - } - - /** - * Set options. - * - * Introduced as needed by unit test. - * - * @param string $options - * @return void - */ - public function set_options($options) { - $this->options = $options; - } - // MARK parent. /** @@ -1693,16 +2107,20 @@ public function userform_get_full_info($searchform) { } } } + + $return = ''; if (isset($fillinginstruction) && $fillinginstruction && isset($extranote) && $extranote) { - return $fillinginstruction.'
'.$extranote; + $return = $fillinginstruction.'
'.$extranote; } else { if (isset($fillinginstruction) && $fillinginstruction) { - return $fillinginstruction; + $return = $fillinginstruction; } if (isset($extranote) && $extranote) { - return $extranote; + $return = $extranote; } } + + return $return; } /** @@ -1753,8 +2171,8 @@ public function userform_is_child_allowed_static($submissionid, $childitemrecord } /** - * This function is used ONLY if $surveypro->newpageforchild == false - * it adds as much as needed $mform->disabledIf to disable items when parent condition does not match + * This function is used ONLY if $surveypro->newpageforchild == false. + * It adds as much as needed $mform->disabledIf to disable items when parent condition does not match * This method is used by the child item * In the frame of this method the parent item is loaded and is requested to provide the disabledif conditions for its child * @@ -1802,7 +2220,7 @@ public function userform_add_disabledif($mform) { $displaydebuginfo = false; foreach ($parentrestrictions as $parentid => $childparentvalue) { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $parentid); $disabilitationinfo = $parentitem->userform_get_parent_disabilitation_info($childparentvalue); if ($displaydebuginfo) { diff --git a/classes/layout_branchingvalidation.php b/classes/layout_branchingvalidation.php index 86268db63cc..f4ad8e661db 100644 --- a/classes/layout_branchingvalidation.php +++ b/classes/layout_branchingvalidation.php @@ -161,12 +161,12 @@ public function display_relations_table() { echo $OUTPUT->notification($message, 'notifymessage'); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemishidden = $item->get_hidden(); if ($item->get_parentid()) { // Here I do not know type and plugin. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $item->get_parentid()); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $item->get_parentid()); } $tablerow = []; @@ -265,7 +265,6 @@ public function display_relations_table() { $itemseeds->close(); $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } } diff --git a/classes/layout_itemlist.php b/classes/layout_itemlist.php index 9f75cb6b51b..e8a2dc37221 100644 --- a/classes/layout_itemlist.php +++ b/classes/layout_itemlist.php @@ -127,7 +127,7 @@ class layout_itemlist { protected $itemeditingfeedback; /** - * @var StdClass object with the feedback for the user + * @var stdClass object with the feedback for the user */ protected $actionfeedback; @@ -256,7 +256,8 @@ public function display_items_table() { $righticn = new \pix_icon('t/right', $indentstr, 'moodle', $iconparams); $moveherestr = get_string('movehere'); - $movehereicn = new \pix_icon('movehere', $moveherestr, 'moodle', ['title' => $moveherestr, 'class' => 'placeholder']); + $iconparams = ['title' => $moveherestr]; + $movehereicn = new \pix_icon('movehere', $moveherestr, 'moodle', $iconparams); $availablestr = get_string('available_title', 'mod_surveypro'); $iconparams = ['title' => $availablestr]; @@ -316,7 +317,7 @@ public function display_items_table() { } foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemid = $itemseed->itemid; $itemishidden = $item->get_hidden(); $sortindex = $item->get_sortindex(); @@ -529,12 +530,15 @@ public function display_items_table() { } // SURVEYPRO_REQUIRED ON/OFF. - $currentrequired = $item->get_required(); - if ($currentrequired !== false) { // It may be "not set" as in page_break, autofill or some more. + $plugin = $item->get_plugin(); + $type = $item->get_type(); + $classname = 'surveypro'.$type.'_'.$plugin.'\item'; + $usesmandatoryattribute = $classname::has_mandatoryattribute(); + if ($usesmandatoryattribute) { // It may be not used as in page_break, autofill or some more. $paramurl = $paramurlbase; $paramurl['sesskey'] = sesskey(); - if ($item->item_canbemandatory()) { + if ($item->item_canbesettomandatory()) { $required = $item->get_required(); $tmpl = new layout_required($itemid, $required, $sortindex); $tmpl->set_type_toggle(); @@ -623,7 +627,6 @@ public function display_items_table() { } $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } @@ -727,12 +730,12 @@ public function display_relations_table() { echo $OUTPUT->notification($message, 'notifymessage'); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->itemid, $itemseed->type, $itemseed->plugin, true); $itemishidden = $item->get_hidden(); if ($item->get_parentid()) { // Here I do not know type and plugin. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $item->get_parentid()); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $item->get_parentid()); } $tablerow = []; @@ -831,7 +834,6 @@ public function display_relations_table() { $itemseeds->close(); $table->set_attribute('align', 'center'); - $table->summary = get_string('itemlist', 'mod_surveypro'); $table->print_html(); } @@ -998,8 +1000,8 @@ public function actions_execution() { redirect($returnurl); break; case SURVEYPRO_CHANGEINDENT: - $where = ['itemid' => $this->rootitemid]; - $DB->set_field('surveypro'.$this->type.'_'.$this->plugin, 'indent', $this->nextindent, $where); + $where = ['id' => $this->rootitemid]; + $DB->set_field('surveypro_item', 'indent', $this->nextindent, $where); break; case SURVEYPRO_MAKERESERVED: $this->item_makereserved_execute(); @@ -1173,7 +1175,7 @@ public function item_hide_feedback() { if ($this->confirm == SURVEYPRO_UNCONFIRMED) { if ($itemstoprocess > 1) { // Ask for confirmation. $dependencies = []; - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->itemcontent = $item->get_content(); @@ -1263,7 +1265,7 @@ public function item_show_feedback() { $itemstoprocess = count($toshowlist); // This is the list of ancestors. if ($this->confirm == SURVEYPRO_UNCONFIRMED) { if ($itemstoprocess > 1) { // Ask for confirmation. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->lastitem = $item->get_content(); @@ -1388,7 +1390,7 @@ public function item_makereserved_feedback() { if ($itemstoprocess > 1) { // Ask for confirmation. // If the clicked element has not parents. $a = new \stdClass(); - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a->itemcontent = $item->get_content(); foreach ($itemstoreserve as $itemtoreserve) { $dependencies[] = $itemtoreserve->sortindex; @@ -1402,7 +1404,7 @@ public function item_makereserved_feedback() { if ($baseitemid != $this->rootitemid) { $firstparentitem = reset($itemstoreserve); - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $firstparentitem->id); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $firstparentitem->id); $a->parentcontent = $parentitem->get_content(); $message = get_string('confirm_reservechainitems_newparent', 'mod_surveypro', $a); } else { @@ -1515,7 +1517,7 @@ public function item_makeavailable_feedback() { if ($itemstoprocess > 1) { // Ask for confirmation. // If the clicked element has not parents. $a = new \stdClass(); - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a->itemcontent = $item->get_content(); foreach ($itemstoavailable as $itemtoavailable) { $dependencies[] = $itemtoavailable->sortindex; @@ -1529,7 +1531,7 @@ public function item_makeavailable_feedback() { if ($baseitemid != $this->rootitemid) { $firstparentitem = reset($itemstoavailable); - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $firstparentitem->id); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $firstparentitem->id); $a->parentcontent = $parentitem->get_content(); $message = get_string('confirm_freechainitems_newparent', 'mod_surveypro', $a); } else { @@ -1600,7 +1602,7 @@ public function item_delete_execute() { } // Get the content of the item for the feedback message. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $killedsortindex = $item->get_sortindex(); $whereparams = ['id' => $this->rootitemid]; @@ -1630,7 +1632,7 @@ public function item_delete_feedback() { if ($this->confirm == SURVEYPRO_UNCONFIRMED) { // Ask for confirmation. // In the frame of the confirmation I need to declare whether some child will break the link. - $item = surveypro_get_item($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $this->rootitemid, $this->type, $this->plugin); $a = new \stdClass(); $a->content = $item->get_content(); @@ -2047,34 +2049,48 @@ public function drop_multilang_execute() { global $DB; if ($this->confirm == SURVEYPRO_CONFIRMED_YES) { + // Overwrite keys from the database and replace it with the actual strings. $template = $this->surveypro->template; + $where = ['surveyproid' => $this->surveypro->id]; $itemseeds = $DB->get_records('surveypro_item', $where, 'sortindex', 'id, type, plugin'); foreach ($itemseeds as $itemseed) { $id = $itemseed->id; $type = $itemseed->type; $plugin = $itemseed->plugin; - $item = surveypro_get_item($this->cm, $this->surveypro, $id, $type, $plugin); - $itemsmlfields = $item->get_multilang_fields(); // Pagebreak and fieldsetend have no multilang_fields. - if ($itemsmlfields[$plugin]) { - // Note: ml means multi language. - foreach ($itemsmlfields as $itemmlfield) { // Note: $itemmlfield is an array of fields. + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $id, $type, $plugin); + + $itemsmlfields = $item->get_multilang_fields(false); + if ($itemsmlfields) { // Pagebreak and fieldsetend have no multilang_fields. + // SELECT content,extranote,options,labelother,defaultvalue FROM {surveyprofield_radiobutton} WHERE id = 8. + foreach ($itemsmlfields as $table => $fields) { // Note: $itemmlfield is an array of arrays of fields. + if (!count($fields)) { + continue; + } $record = new \stdClass(); - $record->id = $item->get_pluginid(); - - $where = ['id' => $record->id]; - $fieldlist = implode(',', $itemmlfield); - // SELECT content,extranote,options,labelother,defaultvalue FROM {surveyprofield_radiobutton} WHERE id = 8. - $reference = $DB->get_record('surveypro'.$type.'_'.$plugin, $where, $fieldlist, MUST_EXIST); - foreach ($itemmlfield as $mlfieldname) { - $stringkey = $reference->{$mlfieldname}; + + $fieldlist = implode(',', $fields); + if ($table == 'surveypro_item') { + $where = ['id' => $id]; + $savedrecord = $DB->get_record($table, $where, $fieldlist, MUST_EXIST); + $record->id = $id; + } else { + $where = ['itemid' => $id]; + $savedrecord = $DB->get_record($table, $where, 'id,'.$fieldlist, MUST_EXIST); + $record->id = $savedrecord->id; + } + + foreach ($fields as $mlfieldname) { + $stringkey = $savedrecord->{$mlfieldname}; + if (core_text::strlen($stringkey)) { $record->{$mlfieldname} = get_string($stringkey, 'surveyprotemplate_'.$template); } else { $record->{$mlfieldname} = null; } } - $DB->update_record('surveypro'.$type.'_'.$plugin, $record); + + $DB->update_record($table, $record); } } } @@ -2115,14 +2131,14 @@ public function drop_multilang_feedback() { // Ask for confirmation. $message = get_string('confirm_dropmultilang', 'mod_surveypro'); - $optionbase = ['s' => $this->cm->instance, 'act' => SURVEYPRO_DROPMULTILANG, 'section' => 'itemslist']; + $optionbase = ['s' => $this->cm->instance]; - $optionsyes = $optionbase; + $optionsyes = $optionbase + ['section' => 'itemslist', 'act' => SURVEYPRO_DROPMULTILANG]; $optionsyes['cnf'] = SURVEYPRO_CONFIRMED_YES; $urlyes = new \moodle_url('/mod/surveypro/layout.php', $optionsyes); $buttonyes = new \single_button($urlyes, get_string('yes')); - $optionsno = $optionbase; + $optionsno = $optionbase + ['section' => 'preview']; $optionsno['cnf'] = SURVEYPRO_CONFIRMED_NO; $urlno = new \moodle_url('/mod/surveypro/layout.php', $optionsno); $buttonno = new \single_button($urlno, get_string('no')); diff --git a/classes/layout_itemsetup.php b/classes/layout_itemsetup.php index 362fb7beb1b..f3de30730b7 100644 --- a/classes/layout_itemsetup.php +++ b/classes/layout_itemsetup.php @@ -287,10 +287,10 @@ public function prevent_direct_user_input() { * * @return void */ - public function item_identitycard() { + public function display_iteminfo() { global $OUTPUT; - $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '.. + $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $friendlyname = get_string('userfriendlypluginname', 'surveypro'.$this->type.'_'.$this->plugin); $iconparams = ['title' => $friendlyname, 'class' => 'icon']; diff --git a/classes/local/form/item_chooser.php b/classes/local/form/item_chooser.php index d8d6d110cbb..a7b3a473d9a 100644 --- a/classes/local/form/item_chooser.php +++ b/classes/local/form/item_chooser.php @@ -54,13 +54,13 @@ public function definition() { // Take care! Here the plugin holds type and plugin both. $fieldplugins = surveypro_get_plugin_list(SURVEYPRO_TYPEFIELD, true); foreach ($fieldplugins as $k => $v) { - $fieldplugins[$k] = get_string('userfriendlypluginname', 'surveyprofield_'.$v); + $fieldplugins[$k] = get_string('userfriendlypluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$v); } asort($fieldplugins); $formatplugins = surveypro_get_plugin_list(SURVEYPRO_TYPEFORMAT, true); foreach ($formatplugins as $k => $v) { - $formatplugins[$k] = get_string('userfriendlypluginname', 'surveyproformat_'.$v); + $formatplugins[$k] = get_string('userfriendlypluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$v); } asort($formatplugins); @@ -70,7 +70,7 @@ public function definition() { $elementgroup = []; $elementgroup[] = $mform->createElement('selectgroups', $fieldname, '', $pluginlist); $elementgroup[] = $mform->createElement('submit', $fieldname.'_button', get_string('add')); - $mform->addGroup($elementgroup, $fieldname.'_group', get_string($fieldname, 'mod_surveypro'), [' '], false); + $mform->addGroup($elementgroup, $fieldname.'_group', get_string('item', 'mod_surveypro'), [' '], false); $mform->addHelpButton($fieldname.'_group', $fieldname, 'surveypro'); } } diff --git a/classes/local/form/item_setupbaseform.php b/classes/local/form/item_setupbaseform.php index 68ecf9a2d37..d2b84948494 100644 --- a/classes/local/form/item_setupbaseform.php +++ b/classes/local/form/item_setupbaseform.php @@ -52,6 +52,7 @@ public function definition() { // Get _customdata. $item = $this->_customdata['item']; + // $fortheeditor = $item->get_fortheeditor(); $surveypro = $item->surveypro; $cm = $item->get_cm(); @@ -84,8 +85,7 @@ public function definition() { // Itembase: content & contentformat. if ($item->get_insetupform('content')) { - $fieldsusingformat = $item->get_fieldsusingformat(); - if (array_key_exists('content', $fieldsusingformat)) { + if ($item->insetupform['contentformat']) { $fieldname = 'content_editor'; $editoroptions = ['trusttext' => true, 'subdirs' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES]; $mform->addElement('editor', $fieldname, get_string($fieldname, 'mod_surveypro'), null, $editoroptions); @@ -212,13 +212,13 @@ public function definition() { // $classname::get_canbeparent() == true; // I also should include the clause "reserved = my one" but I omit this validation // because the surveypro creator can, at every time, change the availability of the current item. - // So I move the validation of the holding form at the form validation time. + // So I move the validation of the holding form at form validation time. - // Build the list only for searchable plugins. + // Build the list only for items that can be parent. $pluginlist = surveypro_get_plugin_list(SURVEYPRO_TYPEFIELD); foreach ($pluginlist as $plugin) { - $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - if (!$classname::get_canbeparent()) { + $dummyitem = surveypro_get_itemclass($cm, $surveypro, 0, SURVEYPRO_TYPEFIELD, $plugin); + if (!$dummyitem->get_canbeparent()) { unset($pluginlist[$plugin]); } } @@ -239,13 +239,13 @@ public function definition() { $select = $quickform->createElement('select', $fieldname, get_string($fieldname, 'mod_surveypro')); $select->addOption(get_string('choosedots'), 0); foreach ($parentsseeds as $parentsseed) { - $parentitem = surveypro_get_item($cm, $surveypro, $parentsseed->id, $parentsseed->type, $parentsseed->plugin); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $parentsseed->id, $parentsseed->type, $parentsseed->plugin); $star = ($parentitem->get_reserved()) ? '(*) ' : ''; // I do not need to take care of contents of items of master templates // because if I am here, $parent is a standard item and not a multilang one. $content = $star; - $content .= get_string('pluginname', 'surveyprofield_'.$parentitem->get_plugin()); + $content .= get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$parentitem->get_plugin()); $content .= ' ['.$parentitem->get_sortindex().']: '.strip_tags($parentitem->get_content()); $content = surveypro_cutdownstring($content); @@ -277,11 +277,11 @@ public function definition() { $rowparity = 1 - $rowparity; $a->examples .= \html_writer::start_tag('tr', ['class' => 'r' . $rowparity]); $a->examples .= \html_writer::start_tag('td', ['class' => 'pluginname']); - $a->examples .= get_string('pluginname', 'surveyprofield_'.$plugin); + $a->examples .= get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin); $a->examples .= \html_writer::end_tag('td'); $a->examples .= \html_writer::start_tag('td', ['class' => 'inputformat']); - $a->examples .= get_string('parentformat', 'surveyprofield_'.$plugin); + $a->examples .= get_string('parentformat', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin); $a->examples .= \html_writer::end_tag('td'); $a->examples .= \html_writer::end_tag('tr'); } @@ -293,7 +293,7 @@ public function definition() { if ($item->get_type() == SURVEYPRO_TYPEFIELD) { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyprofield_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); } } diff --git a/classes/local/form/mtemplate_applyform.php b/classes/local/form/mtemplate_applyform.php index dc96c33c6d6..7c6ec297383 100644 --- a/classes/local/form/mtemplate_applyform.php +++ b/classes/local/form/mtemplate_applyform.php @@ -99,8 +99,10 @@ public function validation($data, $files) { $templatename = $data['mastertemplate']; $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$templatename.'/template.xml'; $xml = file_get_contents($templatepath); - $errormessage = $applyman->validate_xml($xml); - if ($errormessage !== false) { + + $applyman->validate_xml($xml); + $errormessage = $applyman->get_xmlvalidationoutcome(); + if (!empty($errormessage->key)) { $addendum = get_string('mastertemplateaddendum', 'mod_surveypro'); if (isset($errormessage->a)) { $errors['mastertemplate'] = get_string($errormessage->key, 'mod_surveypro', $errormessage->a).$addendum; diff --git a/classes/local/form/mtemplate_createform.php b/classes/local/form/mtemplate_createform.php index 2da180fac1f..9c97af9b4a9 100644 --- a/classes/local/form/mtemplate_createform.php +++ b/classes/local/form/mtemplate_createform.php @@ -45,6 +45,9 @@ class mtemplate_createform extends \moodleform { public function definition() { $mform = $this->_form; + // Get _customdata. + $defaultname = $this->_customdata->defaultname; + // Mtemplatecreate: surveyproid. $fieldname = 'surveyproid'; $mform->addElement('hidden', $fieldname, 0); @@ -56,6 +59,7 @@ public function definition() { $mform->addHelpButton($fieldname, $fieldname, 'surveypro'); $mform->addRule($fieldname, get_string('required'), 'required', null, 'client'); $mform->setType($fieldname, PARAM_FILE); // This word is going to be a file name. + $mform->setDefault($fieldname, $defaultname); $this->add_action_buttons(false, get_string('save', 'mod_surveypro')); } diff --git a/classes/local/form/usersearch.php b/classes/local/form/response_searchform.php similarity index 89% rename from classes/local/form/usersearch.php rename to classes/local/form/response_searchform.php index 1417e692f5b..23e1fac68d3 100644 --- a/classes/local/form/usersearch.php +++ b/classes/local/form/response_searchform.php @@ -37,7 +37,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class usersearch extends \moodleform { +class response_searchform extends \moodleform { /** * Definition. @@ -63,7 +63,7 @@ public function definition() { // so they and are not selected by the css3 selector: fieldset div.fitem:nth-of-type(even) {. $mform->addElement('static', 'beginning_extrarow', '', ''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); // Position. $position = $item->get_position(); @@ -71,8 +71,9 @@ public function definition() { if ($position == SURVEYPRO_POSITIONTOP) { $itemname = $item->get_itemname().'_extrarow'; $content = $item->get_content(); - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, $elementnumber, $content, $option); + + $elementgroup[] = $mform->createElement('static', $itemname, $elementnumber, $content); + $mform->addGroup($elementgroup, $this->itemname.'_group', '', '', false, $class); $item->item_add_color_unifier($mform); } @@ -107,8 +108,11 @@ public function definition() { $item->item_add_color_unifier($mform); $itemname = $item->get_itemname().'_info'; - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, get_string('note', 'mod_surveypro'), $fullinfo, $option); + + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, get_string('note', 'mod_surveypro'), $fullinfo); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); + } } $itemseeds->close(); @@ -151,7 +155,7 @@ public function validation($data, $files) { $olditemid = $itemid; - $item = surveypro_get_item($cm, $surveypro, $itemid, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $type, $plugin); $item->userform_mform_validation($data, $errors, true); } } diff --git a/classes/local/form/userform.php b/classes/local/form/response_submitform.php similarity index 81% rename from classes/local/form/userform.php rename to classes/local/form/response_submitform.php index 1a1e0aa06d0..2b65782ede3 100644 --- a/classes/local/form/userform.php +++ b/classes/local/form/response_submitform.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The class representing the out form + * The class representing the surveypro form for the student * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -37,7 +37,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class userform extends \moodleform { +class response_submitform extends \moodleform { /** * Definition. @@ -67,20 +67,20 @@ public function definition() { $notestr = get_string('note', 'mod_surveypro'); - // Userform: s. + // Response_submitform: s. $mform->addElement('hidden', 's', $surveypro->id); $mform->setType('s', PARAM_INT); - // Userform: submissionid. + // Response_submitform: submissionid. // I usually set 0 into mform elements and then I replace them with preset. // Here I can not follow this habit because... - // if the userform has autofill items (that may use labels), in order to display them + // if the Response_submitform has autofill items (that may use labels), in order to display them // I need to ask to $mform the value of $submissionid. $mform->addElement('hidden', 'submissionid', $submissionid); $mform->setType('submissionid', PARAM_INT); - // Userform: formpage. - // Value is provided by $userform->set_data($prefill); in view.php ['section' => 'submissionform']. + // Response_submitform: formpage. + // Value is provided by $response_submitform->set_data($prefill); in view.php ['section' => 'responsesubmit']. $mform->addElement('hidden', 'formpage', 0); $mform->setType('formpage', PARAM_INT); @@ -99,6 +99,10 @@ public function definition() { $mform->addElement('static', 'nomoreitems', $notestr, get_string('nomoreitems', 'mod_surveypro', $a)); } + if ($mode == SURVEYPRO_PREVIEWMODE) { + $this->add_buttons($surveypro, $formpage, $userfirstpage, $userlastpage, $mode); + } + foreach ($itemseeds as $itemseed) { if ($mode == SURVEYPRO_PREVIEWMODE) { $itemaschildisallowed = true; @@ -106,7 +110,7 @@ public function definition() { // Is the current item allowed in this page? if ($itemseed->parentid) { // Get it now AND NEVER MORE. - $parentitem = surveypro_get_item($cm, $surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $itemseed->parentid); // If parentitem is in a previous page, have a check // otherwise @@ -124,7 +128,7 @@ public function definition() { } if ($itemaschildisallowed) { - $item = surveypro_get_item($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); // Position. $position = $item->get_position(); @@ -132,8 +136,10 @@ public function definition() { if ($position == SURVEYPRO_POSITIONTOP) { $itemname = $item->get_itemname().'_extrarow'; $content = $item->get_contentwithnumber(); - $option = ['class' => 'indent-'.$item->get_indent()]; - $mform->addElement('mod_surveypro_label', $itemname, $elementnumber, $content, $option); + $class = ['class' => 'indent-'.$item->get_indent()]; + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, $elementnumber, $content); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); $item->item_add_color_unifier($mform); } @@ -158,8 +164,10 @@ public function definition() { $item->item_add_color_unifier($mform); $itemname = $item->get_itemname().'_note'; - $attributes = ['class' => 'indent-'.$item->get_indent().' label_static']; - $mform->addElement('mod_surveypro_label', $itemname, '', $fullinfo, $attributes); + $class = ['class' => 'indent-'.$item->get_indent()]; + $elementgroup = []; + $elementgroup[] = $mform->createElement('static', $itemname, '', $fullinfo); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); } if (!$surveypro->newpageforchild) { @@ -181,57 +189,7 @@ public function definition() { return; } - // Buttons. - $buttonlist = []; - if ($formpage > $userfirstpage) { - $buttonlist['prevbutton'] = get_string('previousformpage', 'mod_surveypro'); - } - if ($mode != SURVEYPRO_PREVIEWMODE) { - $pasuseresumesurvey = ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMENOEMAIL); - $pasuseresumesurvey = $pasuseresumesurvey || ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMEEMAIL); - if ($pasuseresumesurvey) { - $buttonlist['pausebutton'] = get_string('pause', 'mod_surveypro'); - } - if ($formpage == $userlastpage) { - if ($surveypro->history) { - $where = ['id' => $submissionid]; - $submissionstatus = $DB->get_field('surveypro_submission', 'status', $where, IGNORE_MISSING); - if ($submissionstatus === false) { // Submissions still does not exist. - $usesimplesavebutton = true; - } else { - $usesimplesavebutton = ($submissionstatus == SURVEYPRO_STATUSINPROGRESS); - } - } else { - $usesimplesavebutton = true; - } - if ($usesimplesavebutton) { - $buttonlist['savebutton'] = get_string('submit'); - } else { - $buttonlist['saveasnewbutton'] = get_string('saveasnew', 'mod_surveypro'); - } - } - } - if ($formpage < $userlastpage) { - $buttonlist['nextbutton'] = get_string('nextformpage', 'mod_surveypro'); - } - - if (count($buttonlist) == 1) { - $name = array_key_first($buttonlist); - $label = $buttonlist[$name]; - - $mform->closeHeaderBefore($name); - $mform->addElement('submit', $name, $label); - } - - if (count($buttonlist) > 1) { - $buttonarray = []; - foreach ($buttonlist as $name => $label) { - $buttonarray[] = $mform->createElement('submit', $name, $label); - } - $mform->addGroup($buttonarray, 'buttonsrow', '', ' ', false); - $mform->setType('buttonsrow', PARAM_RAW); - $mform->closeHeaderBefore('buttonsrow'); - } + $this->add_buttons($surveypro, $formpage, $userfirstpage, $userlastpage, $mode); } /** @@ -284,7 +242,7 @@ public function validation($data, $files) { $olditemid = $itemid; - $item = surveypro_get_item($cm, $surveypro, $itemid, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $type, $plugin); if ($surveypro->newpageforchild) { $itemisenabled = true; // Since it is displayed, it is enabled. $parentitem = null; @@ -295,7 +253,7 @@ public function validation($data, $files) { $parentitem = null; } else { // Call its parent. - $parentitem = surveypro_get_item($cm, $surveypro, $parentitemid); + $parentitem = surveypro_get_itemclass($cm, $surveypro, $parentitemid); // Tell parent that his child has parentvalue = 1;3. if ($parentitem->get_formpage() == $item->get_formpage()) { $itemisenabled = $parentitem->userform_is_child_allowed_dynamic($item->get_parentvalue(), $data); @@ -307,25 +265,95 @@ public function validation($data, $files) { } if ($itemisenabled) { - $propertyexists = property_exists('surveypro'.$type.'_'.$plugin.'\item', 'trimonsave'); - if ($propertyexists && $item->get_trimonsave()) { - if (trim($content) != $content) { - $warnings[$elementname] = get_string('uerr_willbetrimmed', 'mod_surveypro'); - } - } $item->userform_mform_validation($data, $errors, false); } + // Otherwise... // Code: echo 'parent item doesn\'t allow the validation of the child item '.$item->itemid;. // Code: echo ', plugin = '.$item->plugin.'('.$item->content.')
';. } } - if ($errors) { - // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. - $errors += $warnings; + return $errors; + } + + + /** + * Add buttons at the end of the submitform. + * + * @return void + */ + public function add_buttons() { + global $DB; + + $mform = $this->_form; + + $surveypro = $this->_customdata->surveypro; + $submissionid = $this->_customdata->submissionid; + $formpage = $this->_customdata->formpage; + $userfirstpage = $this->_customdata->userfirstpage; + $userlastpage = $this->_customdata->userlastpage; + $mode = $this->_customdata->mode; + + // Buttons. + $buttonlist = []; + if ($formpage > $userfirstpage) { + $buttonlist['prevbutton'] = get_string('previousformpage', 'mod_surveypro'); + } + if ($mode != SURVEYPRO_PREVIEWMODE) { + $pasuseresumesurvey = ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMENOEMAIL); + $pasuseresumesurvey = $pasuseresumesurvey || ($surveypro->pauseresume == SURVEYPRO_PAUSERESUMEEMAIL); + if ($pasuseresumesurvey) { + $buttonlist['pausebutton'] = get_string('pause', 'mod_surveypro'); + } + if ($formpage == $userlastpage) { + if ($surveypro->history) { + $where = ['id' => $submissionid]; + $submissionstatus = $DB->get_field('surveypro_submission', 'status', $where, IGNORE_MISSING); + if ($submissionstatus === false) { // Submissions still does not exist. + $usesimplesavebutton = true; + } else { + $usesimplesavebutton = ($submissionstatus == SURVEYPRO_STATUSINPROGRESS); + } + } else { + $usesimplesavebutton = true; + } + if ($usesimplesavebutton) { + $buttonlist['savebutton'] = get_string('submit'); + } else { + $buttonlist['saveasnewbutton'] = get_string('saveasnew', 'mod_surveypro'); + } + } + $buttonlist['cancelbutton'] = get_string('cancel'); + } + if ($formpage < $userlastpage) { + $buttonlist['nextbutton'] = get_string('nextformpage', 'mod_surveypro'); } - return $errors; + if (count($buttonlist) == 1) { + $name = array_key_first($buttonlist); + $label = $buttonlist[$name]; + + $mform->closeHeaderBefore($name); + if ($name == 'cancelbutton') { + $mform->addElement('cancel'); + } else { + $mform->addElement('submit', $name, $label); + } + } + + if (count($buttonlist) > 1) { + $buttonarray = []; + foreach ($buttonlist as $name => $label) { + if ($name == 'cancelbutton') { + $buttonarray[] = $mform->createElement('cancel'); + } else { + $buttonarray[] = $mform->createElement('submit', $name, $label); + } + } + $mform->addGroup($buttonarray, 'buttonsrow', '', ' ', false); + $mform->setType('buttonsrow', PARAM_RAW); + $mform->closeHeaderBefore('buttonsrow'); + } } } diff --git a/classes/local/form/utemplate_importform.php b/classes/local/form/utemplate_importform.php index 6fc4a83425d..22f47a21b6c 100644 --- a/classes/local/form/utemplate_importform.php +++ b/classes/local/form/utemplate_importform.php @@ -109,8 +109,9 @@ public function validation($data, $files) { $xmlfileid = $file->get_id(); $xml = $importman->get_utemplate_content($xmlfileid); - $errormessage = $importman->validate_xml($xml); - if ($errormessage !== false) { + $importman->validate_xml($xml); + $errormessage = $importman->get_xmlvalidationoutcome(); + if (!empty($errormessage->key)) { if (isset($errormessage->a)) { $errors['importfile_filemanager'] = get_string($errormessage->key, 'mod_surveypro', $errormessage->a); } else { diff --git a/classes/local/ipe/layout_customnumber.php b/classes/local/ipe/layout_customnumber.php index a40f11f0399..4b8ea5a9cb6 100644 --- a/classes/local/ipe/layout_customnumber.php +++ b/classes/local/ipe/layout_customnumber.php @@ -55,15 +55,14 @@ public function __construct($itemid, $customnumber) { public static function update($itemid, $newcnumber) { global $DB; - $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], 'id, surveyproid, type, plugin', MUST_EXIST); + $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], 'id, surveyproid', MUST_EXIST); $surveypro = $DB->get_record('surveypro', ['id' => $itemrecord->surveyproid], '*', MUST_EXIST); $cm = get_coursemodule_from_instance('surveypro', $surveypro->id, $surveypro->course, false, MUST_EXIST); $context = \context_module::instance($cm->id); external_api::validate_context($context); - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; $newcnumber = clean_param($newcnumber, PARAM_TEXT); - $DB->set_field($tablename, 'customnumber', $newcnumber, ['itemid' => $itemid]); + $DB->set_field('surveypro_item', 'customnumber', $newcnumber, ['id' => $itemid]); return new static($itemid, $newcnumber); } diff --git a/classes/local/ipe/layout_required.php b/classes/local/ipe/layout_required.php index c9348eab4d9..117c18af1eb 100644 --- a/classes/local/ipe/layout_required.php +++ b/classes/local/ipe/layout_required.php @@ -90,16 +90,15 @@ public function export_for_template(\renderer_base $output) { public static function update($itemid, $newrequired) { global $DB; - $fields = 'id, surveyproid, type, plugin, sortindex'; + $fields = 'id, surveyproid, sortindex'; $itemrecord = $DB->get_record('surveypro_item', ['id' => $itemid], $fields, MUST_EXIST); $surveypro = $DB->get_record('surveypro', ['id' => $itemrecord->surveyproid], 'id, course', MUST_EXIST); $cm = get_coursemodule_from_instance('surveypro', $surveypro->id, $surveypro->course, false, MUST_EXIST); $context = \context_module::instance($cm->id); external_api::validate_context($context); - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; $newrequired = clean_param($newrequired, PARAM_INT); - $DB->set_field($tablename, 'required', $newrequired, ['itemid' => $itemid]); + $DB->set_field('surveypro_item', 'required', $newrequired, ['id' => $itemid]); if (!empty($newrequired)) { // This item that WAS NOT mandatory IS NOW mandatory. diff --git a/classes/local/ipe/layout_variable.php b/classes/local/ipe/layout_variable.php index ccd22610bea..68d3d9caf5d 100644 --- a/classes/local/ipe/layout_variable.php +++ b/classes/local/ipe/layout_variable.php @@ -61,20 +61,18 @@ public static function update($itemid, $newvarname) { $context = \context_module::instance($cm->id); external_api::validate_context($context); - // Why was I required to move surveypro_get_item from locallib.php to lib.php? - $item = surveypro_get_item($cm, $surveypro, $itemid, $itemrecord->type, $itemrecord->plugin); + // Why was I required to move surveypro_get_itemclass from locallib.php to lib.php? + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $itemrecord->type, $itemrecord->plugin); // Before saving to the the plugin table, validate the variable name. $record = new \stdClass(); + $record->itemid = $itemid; $record->surveyproid = $surveypro->id; $record->variable = $newvarname; $record->plugin = $itemrecord->plugin; - $item->item_validate_variablename($record, $itemid); - - $tablename = 'surveypro'.$itemrecord->type.'_'.$itemrecord->plugin; - $newvarname = $record->variable; - $DB->set_field($tablename, 'variable', $newvarname, ['itemid' => $itemid]); + $item->item_validate_variablename($record); + $DB->set_field('surveypro_item', 'variable', $record->variable, ['id' => $itemid]); return new static($itemid, $newvarname); } diff --git a/classes/mtemplate_apply.php b/classes/mtemplate_apply.php index 1036174b0b6..a73a54c6ea3 100644 --- a/classes/mtemplate_apply.php +++ b/classes/mtemplate_apply.php @@ -41,6 +41,23 @@ class mtemplate_apply extends mtemplate_base { */ protected $langtree = []; + /** + * @var array + */ + protected $mastertemplate; + + // MARK set. + + /** + * Set mastertemplate. + * + * @param string $mastertemplate + * @return void + */ + public function set_mastertemplate($mastertemplate) { + $this->mastertemplate = $mastertemplate; + } + // MARK get. /** @@ -64,6 +81,20 @@ public function get_mtemplates() { // MARK other. + /** + * Execute last minute check before applying master templates. + * + * @return void + */ + public function lastminute_template_check() { + global $CFG; + + $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$this->mastertemplate.'/template.xml'; + $xml = file_get_contents($templatepath); + + $this->validate_xml($xml); + } + /** * Actually add items coming from template to the db. * @@ -92,10 +123,9 @@ public function add_items_from_template() { $naturalsortindex = 0; foreach ($simplexml->children() as $xmlitem) { - // Read the attributes of the item node. foreach ($xmlitem->attributes() as $attribute => $value) { - // The $xmlitem looks like: . + // The $xmlitem looks like: . if ($attribute == 'type') { $currenttype = (string)$value; } @@ -104,61 +134,75 @@ public function add_items_from_template() { } } - // Take care to details. // Load the item class in order to call its methods to validate $record before saving it. - $item = surveypro_get_item($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); foreach ($xmlitem->children() as $xmltable) { // Surveypro_item and surveypro_<>. $tablename = $xmltable->getName(); - if ($tablename == 'surveypro_item') { - $currenttablestructure = $this->get_table_structure(); - } else { - $currenttablestructure = $this->get_table_structure($currenttype, $currentplugin); - } $record = new \stdClass(); - - // Add to $record mandatory fields that will be overwritten, hopefully, with the content of the usertemplate. - $record->surveyproid = (int)$this->surveypro->id; - $record->type = $currenttype; - $record->plugin = $currentplugin; if ($tablename == 'surveypro_item') { - $item->item_add_mandatory_base_fields($record); + $itemid = 0; // This is the proof the surveypro_item record has not yet been saved. + + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure(); + + $record->surveyproid = (int)$this->surveypro->id; + $record->type = $currenttype; + $record->plugin = $currentplugin; + $item->item_add_fields_default_to_parent_table($record); } else { - $item->item_add_mandatory_plugin_fields($record); + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure($currenttype, $currentplugin); + + $record->itemid = $itemid; // It has been defined when surveypro_item record was saved. + $item->item_add_fields_default_to_child_table($record); } foreach ($xmltable->children() as $xmlfield) { - $fieldname = $xmlfield->getName(); + $xmltag = $xmlfield->getName(); // Generally $xmltag is the name of the field. // Tag always belong to surveypro_item table. - if ($fieldname == 'parent') { - foreach ($xmlfield->children() as $xmlparentattribute) { - $fieldname = $xmlparentattribute->getName(); - $fieldexists = in_array($fieldname, $currenttablestructure); + if ($xmltag == 'parent') { + // Debug: $label = 'Count of attributes of the field '.$xmltag;. + // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. + foreach ($xmlfield->children() as $xmlchildattribute) { + $xmltag = $xmlchildattribute->getName(); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlparentattribute; + $record->{$xmltag} = (string)$xmlchildattribute; } } continue; } - // Tag always belong to surveypro(field|format)_<> table. - // So: ($fieldname == 'embedded') only when surveypro_item has already been saved. - // So: $itemid is known. - if ($fieldname == 'embedded') { - // Debug: $label = 'Count of attributes of the field '.$fieldname; + // Tag always belong to surveypro_item table. + if ($xmltag == 'embedded') { + // Urgently create a record because its id is needed here. + // Please do not create a new record twice. + // If 2 embedded pictures are part of the content, be sure to create only one record. + // If you already created the record for the first embedded picture, do not create one more record now. + if (empty($itemid)) { + $itemid = $DB->insert_record('surveypro_item', $record); + } + + // Debug: $label = 'Count of attributes of the field '.$xmltag; // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. foreach ($xmlfield->children() as $xmlfileattribute) { $fileattributename = $xmlfileattribute->getName(); if ($fileattributename == 'filename') { - $filename = $xmlfileattribute; + $attributecontent = (string)$xmlfileattribute; + $filename = get_string($attributecontent, 'surveyprotemplate_'.$this->templatename); } if ($fileattributename == 'filecontent') { - $filecontent = base64_decode($xmlfileattribute); + $attributecontent = (string)$xmlfileattribute; + $encodedcontent = get_string($attributecontent, 'surveyprotemplate_'.$this->templatename); + $filecontent = base64_decode($encodedcontent); } } + // Debug: echo 'I need to add: "'.$filename.'" to the filearea
';. + // Add the file described by $filename and $filecontent to filearea. // Alias, add pictures found in the utemplate to filearea. $filerecord = new \stdClass(); @@ -172,14 +216,19 @@ public function add_items_from_template() { continue; } - $fieldexists = in_array($fieldname, $currenttablestructure); + // The method xml_validation checks only the formal schema validity. + // It does not know whether the xml is old and holds no longer needed fields + // or does not hold fields that are now mandatory. + // Because of this, I can not SIMPLY add $xmltag to $record but I need to make some more investigation. + // I neglect unneeded used fields, here. + // I will add mandatory (but missing because the usertemplate may be old) fields, + // before saving in the frame of the $item->item_force_coherence. + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlfield; + $record->{$xmltag} = (string)$xmlfield; } } - unset($record->id); - // Apply master template settings. [$tablename, $record] = $mastertemplate->apply_template_settings($tablename, $record, $config); @@ -192,16 +241,23 @@ public function add_items_from_template() { $record->parentid = $DB->get_field('surveypro_item', 'id', $whereparams, MUST_EXIST); } - $itemid = $DB->insert_record($tablename, $record); + $item->item_validate_variablename($record); + if (empty($itemid)) { // If the record in surveypro_item has NOT already been added. + $itemid = $DB->insert_record('surveypro_item', $record); + } else { + // I had to urgently create a record to get its id in order to give it to $fs->create_file_from_string. + // Now I can not create a different record because I passed the id of the existing one. + // So I update the found record. + $record->id = $itemid; + $DB->update_record('surveypro_item', $record); + } } else { // Take care to details. $item->item_force_coherence($record); - $item->item_validate_variablename($record, $itemid); - $record->itemid = $itemid; $DB->insert_record($tablename, $record, false); } - } + } // Closes foreach ($xmlitem->children() as $xmltable) alias: Surveypro_item and surveypro_<>. } } @@ -220,8 +276,8 @@ public function apply_template() { // End of: delete all existing items. $this->templatename = $this->formdata->mastertemplate; - $record = new \stdClass(); + $record = new \stdClass(); $record->id = $this->surveypro->id; $record->template = $this->templatename; $DB->update_record('surveypro', $record); @@ -288,6 +344,4 @@ public function welcome_apply_message() { $message = get_string('welcome_mtemplateapply', 'mod_surveypro'); echo $OUTPUT->notification($message, 'notifymessage'); } - - } diff --git a/classes/mtemplate_save.php b/classes/mtemplate_save.php index 843e9db1913..80009a32337 100644 --- a/classes/mtemplate_save.php +++ b/classes/mtemplate_save.php @@ -43,6 +43,30 @@ class mtemplate_save extends mtemplate_base { // MARK get. + /** + * Get translated strings. + * + * @param string $userlang + * @return void + */ + public function get_translated_strings($userlang) { + $stringsastext = []; + $a = new \stdClass(); + $a->userlang = $userlang; + foreach ($this->langtree as $langbranch) { + foreach ($langbranch as $k => $originalstring) { + if (empty($originalstring)) { + $stringsastext[] = '$string[\''.$k.'\'] = \'\';'; + } else { + $a->stringkey = $k; + $stringsastext[] = get_string('translatedstring', 'mod_surveypro', $a); + } + } + } + + return "\n".implode("\n", $stringsastext)."\n"; + } + /** * Generate the array of strings for the lang file of the mastertemplate plugin. * @@ -58,7 +82,7 @@ public function get_lang_file_content() { } } - return "\n".implode("\n", $stringsastext); + return "\n".implode("\n", $stringsastext)."\n"; } /** @@ -107,17 +131,33 @@ public function get_plugin_name() { * @return void */ public function build_langtree($multilangfields, $item) { - foreach ($multilangfields as $plugin => $fieldnames) { - foreach ($fieldnames as $fieldname) { - $component = $plugin.'_'.$fieldname; - if (isset($this->langtree[$component])) { - $index = count($this->langtree[$component]); + global $DB; + + $itemid = $item->get_itemid(); + $plugin = $item->get_plugin(); + foreach ($multilangfields as $table => $multilanfields) { + foreach ($multilanfields as $multilanfield) { + // Filename and filecontent are multilang fields BUT I they may not be set. + if ( ($multilanfield == 'filename') || ($multilanfield == 'filecontent') ) { + continue; + } + + // Key. + $key = $plugin.'_'.$multilanfield; + if (isset($this->langtree[$key])) { + $index = count($this->langtree[$key]); } else { $index = 0; } $stringindex = sprintf('%02d', 1 + $index); - $content = str_replace("\r", '', $item->get_generic_property($fieldname)); - $this->langtree[$component][$component.'_'.$stringindex] = $content; + + // Value. + if ($multilanfield == 'content') { + $value = $DB->get_field('surveypro_item', 'content', ['id' => $itemid], MUST_EXIST); + } else { + $value = str_replace("\r", '', $item->get_generic_property($multilanfield)); + } + $this->langtree[$key][$key.'_'.$stringindex] = $value; } } } @@ -371,6 +411,31 @@ public function replace_package($filecontent, $pluginname) { return $filecontent; } + /** + * Add to langtree as many elements as the number of files found among content fields. + * + * If in the frame of the content of an item I find 5 embedded images, I add 5 extra elements to langtree. + * I can not use the standard procedure written in build_langtree because I don't know what I will find. + * + * @param string $plugin + * @param string $field + * @param string $content + * @return string $stringindex + */ + public function add_entry_in_langtree($plugin, $field, $content) { + $key = $plugin.'_'.$field; + if (isset($this->langtree[$key])) { + $index = count($this->langtree[$key]); + } else { + $index = 0; + } + $stringindex = sprintf('%02d', 1 + $index); + $val = $key.'_'.$stringindex; + $this->langtree[$key][$val] = $content; + + return $val; + } + /** * Write master template content. * @@ -393,7 +458,7 @@ public function write_template_content($visiblesonly=true) { $xmltemplate = new \SimpleXMLElement(''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $xmlitem = $xmltemplate->addChild('item'); $xmlitem->addAttribute('type', $itemseed->type); @@ -402,14 +467,65 @@ public function write_template_content($visiblesonly=true) { $xmlitem->addAttribute('version', $pluginversion[$index]); // Surveypro_item. + $structure = $this->get_table_structure(); + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; + $unrelevantfields = array_merge($unrelevantfields, $item->item_expected_null_fields()); $xmltable = $xmlitem->addChild('surveypro_item'); if ($multilangfields = $item->get_multilang_fields()) { // Pagebreak and fieldsetend have no multilang_fields. $this->build_langtree($multilangfields, $item); } - - $structure = $this->get_table_structure(); foreach ($structure as $field) { + if (in_array($field, $unrelevantfields)) { + continue; + } + + if ($field == 'content') { + // If $field == 'content' I can not use the property of the object $item because + // in case of pictures, for instance, $item->content looks like: + // 'MMM' + // and not like: + // '...get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + // $val = $DB->get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + // if (core_text::strlen($val)) { + // $xmlfield = $xmltable->addChild('content', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // } + + $val = $this->xml_get_field_content($item, $field, $multilangfields); + if (\core_text::strlen($val)) { + $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + } // Otherwise: It is empty, do not evaluate: jump. + + if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemseed->id)) { + foreach ($files as $file) { + $filename = $file->get_filename(); + if ($filename == '.') { + continue; + } + $xmlembedded = $xmltable->addChild('embedded'); + + // Add an entry in langtree for filename. + $val = $this->add_entry_in_langtree($itemseed->plugin, 'filename', $filename); + // End of: add corresponding string in langtree. + + // $val = $this->xml_get_field_content($item, 'filename', $multilangfields); + $xmlembedded->addChild('filename', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // $xmlembedded->addChild('filename', $filename); + + // Add corresponding string in langtree. + $content = base64_encode($file->get_content()); + $val = $this->add_entry_in_langtree($itemseed->plugin, 'filecontent', $content); + // End of: add corresponding string in langtree. + + // $val = $this->xml_get_field_content($item, 'filecontent', $multilangfields); + $xmlembedded->addChild('filecontent', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + // $xmlembedded->addChild('filecontent', $content); + } + } + continue; + } + if ($field == 'parentid') { $parentid = $item->get_parentid(); if ($parentid) { @@ -424,61 +540,44 @@ public function write_template_content($visiblesonly=true) { } // Otherwise: It is empty, do not evaluate: jump. continue; } + if ($field == 'parentvalue') { continue; } - $val = $this->xml_get_field_content($item, 'item', $field, $multilangfields); - + $val = $this->xml_get_field_content($item, $field, $multilangfields); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (\core_text::strlen($val)) { $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. } // Child table. + $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; $structure = $this->get_table_structure($itemseed->type, $itemseed->plugin); + // Take care: some items plugin may be free of their own specific table. if (!count($structure)) { continue; } - $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; + $unrelevantfields = ['id', 'itemid']; $xmltable = $xmlitem->addChild($tablename); foreach ($structure as $field) { - // If $field == 'content' I can not use the property of the object $item because - // in case of pictures, for instance, $item->content has to look like: - // 'MMM' - // and not like: - // 'img1xml_get_field_content($item, $itemseed->plugin, $field, $multilangfields); - } else { - $val = $DB->get_field($tablename, 'content', ['itemid' => $itemseed->id], MUST_EXIST); - } - if (\core_text::strlen($val)) { - $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); - // Otherwise: It is empty, do not evaluate: jump. + if (in_array($field, $unrelevantfields)) { + continue; } - if ($field == 'content') { - $itemid = $item->get_itemid(); - if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid)) { - foreach ($files as $file) { - $filename = $file->get_filename(); - if ($filename == '.') { - continue; - } - $xmlembedded = $xmltable->addChild('embedded'); - $xmlembedded->addChild('filename', $filename); - $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); - } - } - } + $val = $this->xml_get_field_content($item, $field, $multilangfields); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); + if (\core_text::strlen($val)) { + $xmlfield = $xmltable->addChild($field, $val); + } // Otherwise: It is empty, do not evaluate: jump. } } - // The case: $option == false if 100% waste of time + // In the coming code, "$option == false;" if 100% waste of time and should be changed to "$option == true;" // BUT BUT BUT... // the output in the file is well written. // I prefer a more readable xml file instead of few nanoseconds saved. @@ -497,29 +596,45 @@ public function write_template_content($visiblesonly=true) { /** * Get the content of a field for the XML file. + * This tree is needed to build the lang files of the master template. + * The idea is: + * if the field am I dialing with is a multilang field { + * return the key of the lang file + * } + * if the field am I dialing with is NOT a multilang field { + * return the content of the field + * } * - * @param object $item - * @param string $plugin + * Once this function returns its output the XML describing the surveypro of this master template will be: + * boolean_content_01 + * or + * 0 + * + * @param object $itemclass The class needed to call $itemclass->get_generic_property($field); * @param string $field * @param array $multilangfields - * @return void + * @return string the key for the lang file of the direct content of the file */ - public function xml_get_field_content($item, $plugin, $field, $multilangfields) { - // 1a: Has the plugin $plugin multilang fields?. - if (isset($multilangfields[$plugin])) { - // 1b: If the field that is going to be assigned belongs to your multilang fields. - if (in_array($field, $multilangfields[$plugin])) { - $component = $plugin.'_'.$field; - - if (isset($this->langtree[$component])) { - end($this->langtree[$component]); - $val = key($this->langtree[$component]); - return $val; + public function xml_get_field_content($itemclass, $field, $multilangfields) { + // 1a: Has the current plugin multilang fields?. + if (!empty($multilangfields)) { // Pagebrak and fieldsetend don't have $multilangfields. + $plugin = $itemclass->get_plugin(); + foreach ($multilangfields as $table => $multilangfield) { + // 1b: Is the field that is going to be assigned belongs to the multilang fields of this plugin? + if (in_array($field, $multilangfield)) { + $key = $plugin.'_'.$field; // For instance: boolean_content + + if (isset($this->langtree[$key])) { // Langtree has already been defined. + $index = count($this->langtree[$key]); + $stringindex = sprintf('%02d', $index); + $val = $key.'_'.$stringindex; + return $val; + } } } } - $content = $item->get_generic_property($field); + $content = $itemclass->get_generic_property($field); if (\core_text::strlen($content)) { $val = $content; } else { diff --git a/classes/output/action_bar.php b/classes/output/action_bar.php index cee01898cc2..29da25d2dde 100644 --- a/classes/output/action_bar.php +++ b/classes/output/action_bar.php @@ -103,9 +103,9 @@ public function draw_view_action_bar(): string { $menu[$linktosubmissions->out(false)] = get_string('surveypro_responses', 'mod_surveypro'); } - // View -> searchsubmissions. + // View -> responsesearch. if ($cansearch && $utilitylayoutman->has_search_items()) { - $paramurl['section'] = 'searchsubmissions'; + $paramurl['section'] = 'responsesearch'; $linktosearch = new moodle_url('/mod/surveypro/view.php', $paramurl); $menu[$linktosearch->out(false)] = get_string('surveypro_view_search', 'mod_surveypro'); } @@ -132,8 +132,8 @@ public function draw_view_action_bar(): string { } } - // If section = 'submissionform', set $activeurl according to the way the form is going to be used. - if (strpos($this->currenturl->out(false), 'submissionform')) { + // If section = 'responsesubmit', set $activeurl according to the way the form is going to be used. + if (strpos($this->currenturl->out(false), 'responsesubmit')) { if (isset($gosthlink)) { $activeurl = $gosthlink; } else { diff --git a/classes/plugininfo/surveyprofield.php b/classes/plugininfo/surveyprofield.php index 3392b0fec6d..32b0caf928d 100644 --- a/classes/plugininfo/surveyprofield.php +++ b/classes/plugininfo/surveyprofield.php @@ -26,6 +26,10 @@ use core_text, core\plugininfo\base, core_plugin_manager, moodle_url; +defined('MOODLE_INTERNAL') || die(); + +require_once(dirname(__FILE__).'/../../lib.php'); + /** * The mod_surveypro field plugin class. * @@ -49,7 +53,7 @@ public static function get_enabled_plugins() { } $installed = []; foreach ($plugins as $plugin => $version) { - $installed[] = 'surveyprofield_'.$plugin; + $installed[] = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; } [$installed, $params] = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); diff --git a/classes/plugininfo/surveyproformat.php b/classes/plugininfo/surveyproformat.php index f3de8ddee5f..7b0c7630176 100644 --- a/classes/plugininfo/surveyproformat.php +++ b/classes/plugininfo/surveyproformat.php @@ -26,6 +26,10 @@ use core_text, core\plugininfo\base, core_plugin_manager, moodle_url; +defined('MOODLE_INTERNAL') || die(); + +require_once(dirname(__FILE__).'/../../lib.php'); + /** * The mod_surveypro format plugin class. * @@ -49,7 +53,7 @@ public static function get_enabled_plugins() { } $installed = []; foreach ($plugins as $plugin => $version) { - $installed[] = 'surveyproformat_'.$plugin; + $installed[] = 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$plugin; } [$installed, $params] = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 7dd683e44f3..231bbbfc888 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -237,7 +237,7 @@ protected static function store_current_data(&$surveyprodata, $surveyproanswer, protected static function export_get_itemcontent($surveyproanswer) { global $DB; - $tablename = 'surveyprofield_'.$surveyproanswer->plugin; + $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$surveyproanswer->plugin; $itemid = $surveyproanswer->itemid; $params = ['itemid' => $itemid]; $plugin = $DB->get_record($tablename, $params); diff --git a/classes/templatebase.php b/classes/templatebase.php index 3f308eaf1ea..1a526b328ea 100644 --- a/classes/templatebase.php +++ b/classes/templatebase.php @@ -63,6 +63,11 @@ class templatebase { */ protected $langtree = []; + /** + * @var string Outcome of the last minute check before applying templates. + */ + protected $xmlvalidationoutcome; + /** * Class constructor. * @@ -76,17 +81,135 @@ public function __construct($cm, $context, $surveypro) { $this->surveypro = $surveypro; } + // MARK set. + + /** + * Set xmlvalidationoutcome. + * + * @param stdClass $xmlvalidationoutcome + * @return void + */ + public function set_xmlvalidationoutcome($xmlvalidationoutcome=null) { + if (is_null($xmlvalidationoutcome)) { + $xmlvalidationoutcome = new \stdClass(); + } + $this->xmlvalidationoutcome = $xmlvalidationoutcome; + } + + // MARK get. + + /** + * Returns the ordered list of fields for the itembase (or the plugin) table. + * + * @param string $type (optional) + * @param string $plugin (optional) + * @return void + */ + public function get_table_structure($type=null, $plugin=null) { + global $CFG; + + if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { + $message = '$type and $plugin must be provided both or none.'; + debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); + } + + $fieldlist = []; + if (empty($type) && empty($plugin)) { + $installxml = $CFG->dirroot.'/mod/surveypro/db/install.xml'; + $targettable = 'surveypro_item'; + } else { + $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; + $targettable = 'surveypro'.$type.'_'.$plugin; + + // Some plugins are missing the install.xml because they don't have attributes. + if (!file_exists($installxml)) { + return $fieldlist; + } + } + + $xmlall = simplexml_load_file($installxml); + foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. + foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. + $attributes = $xmltable->attributes(); + $tablename = $attributes['NAME']; + if ($tablename != $targettable) { + continue; + } + foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. + foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. + $attributes = $xmlfield->attributes(); + $fieldname = $attributes['NAME']; + $fieldlist[] = (string)$attributes['NAME']; + } + break; + } + break; + } + break; + } + + return $fieldlist; + } + + /** + * Get plugin versions. + * + * @return versions of each field and format plugin + */ + public static function get_subplugin_versions() { + $versions = []; + $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; + + foreach ($types as $type) { + $plugins = surveypro_get_plugin_list($type, true); + foreach ($plugins as $plugin => $unused) { + $versions[$plugin] = get_config('surveypro'.$plugin, 'version'); + } + } + + return $versions; + } + + /** + * Get xml validation outcome + * + * @return xmlvalidationoutcome + */ + public function get_xmlvalidationoutcome() { + return $this->xmlvalidationoutcome; + } + + /** + * Get user template content. + * + * @param int $utemplateid + * @return void + */ + public function get_utemplate_content($utemplateid=0) { + $fs = get_file_storage(); + if (empty($utemplateid)) { + $utemplateid = $this->utemplateid; + } + $xmlfile = $fs->get_file_by_id($utemplateid); + + return $xmlfile->get_content(); + } + + // MARK other. + /** * Validate the uploaded xml file. * * @param object $xml File to validate - * @return object|boolean error describing the message to show, false if no error is found + * @return object|false error describing the message to show, false if no error is found */ public function validate_xml($xml) { global $CFG; $debug = false; // Set $debug = true if you want to stop anyway to debug the xml template. + $this->set_xmlvalidationoutcome(); + $pluginversion = self::get_subplugin_versions(); if ($debug) { $simplexml = new \SimpleXMLElement($xml); @@ -95,7 +218,7 @@ public function validate_xml($xml) { } foreach ($simplexml->children() as $xmlitem) { foreach ($xmlitem->attributes() as $attribute => $value) { - // Example: . + // Example: . // Debug: echo 'Found: '.$attribute.' = '.$value.'
';. if ($attribute == 'type') { $currenttype = (string)$value; @@ -111,19 +234,22 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'missingitemtype'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } if (!isset($currentplugin)) { $error = new \stdClass(); $error->key = 'missingitemplugin'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } if (!isset($currentversion)) { $error = new \stdClass(); $error->key = 'missingitemversion'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } // Ok, $currenttype and $currentplugin are onboard. @@ -132,11 +258,12 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'invalidtypeorplugin'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } $index = $currenttype.'_'.$currentplugin; - if ($pluginversion[$index] < $currentversion) { + if ($pluginversion[$index] > $currentversion) { $a = new \stdClass(); $a->type = $currenttype; $a->plugin = $currentplugin; @@ -147,7 +274,8 @@ public function validate_xml($xml) { $error->a = $a; $error->key = 'versionmismatch'; - return $error; + $this->set_xmlvalidationoutcome($error); + break; } foreach ($xmlitem->children() as $xmltable) { @@ -167,7 +295,8 @@ public function validate_xml($xml) { $error->key = 'badtablenamefound'; $error->a = $tablename; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } $xsd = $classname::get_plugin_schema(); // Plugin schema. } @@ -176,7 +305,8 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'xsdnotfound'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } $mdom = new \DOMDocument(); @@ -217,7 +347,8 @@ public function validate_xml($xml) { $error->a = $a; $error->key = 'reportederror'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } if (!$status) { @@ -230,89 +361,100 @@ public function validate_xml($xml) { $error = new \stdClass(); $error->key = 'schemavalidationfailed'; - return $error; + $this->set_xmlvalidationoutcome($error); + break 2; // Exit the first foreach and the second too. } } } - - return false; } - // MARK get. + /** + * Tell the user that the usertemplate is obsolete. + * + * @return void + */ + public function lastminute_stop() { + global $OUTPUT; + + $errormessage = $this->get_xmlvalidationoutcome(); + if (isset($errormessage->key)) { + if (isset($errormessage->a)) { + $message = get_string($errormessage->key, 'mod_surveypro', $errormessage->a); + } else { + $message = get_string($errormessage->key, 'mod_surveypro'); + } + $message .= get_string('utemplate_nolongervalid', 'mod_surveypro'); + + echo $OUTPUT->notification($message, 'notifyproblem'); + $paramurl = ['s' => $this->surveypro->id, 'area' => 'layout', 'section' => 'itemslist']; + $url = new \moodle_url('/mod/surveypro/layout.php', $paramurl); + echo $OUTPUT->continue_button($url); + + echo $OUTPUT->footer(); + die(); + } + } /** - * Get the ordered list of fields for the itembase (or the plugin) table. + * Tell the user that the usertemplate is obsolete. * - * @param string $type (optional) - * @param string $plugin (optional) + * @param string $mtemplate + * @param int $itemid * @return void */ - public function get_table_structure($type=null, $plugin=null) { + public function load_new_files_from_lang($mtemplate, $itemid) { global $CFG; - if ((empty($type) && !empty($plugin)) || (!empty($type) && empty($plugin))) { - $message = '$type and $plugin must be provided both or none.'; - debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); - } + // I need to push to SURVEYPRO_ITEMCONTENTFILEAREA new files described in current lang file that may be new. - $fieldlist = []; - if (empty($type) && empty($plugin)) { - $installxml = $CFG->dirroot.'/mod/surveypro/db/install.xml'; - $targettable = 'surveypro_item'; - $uselessfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; - } else { - $installxml = $CFG->dirroot.'/mod/surveypro/'.$type.'/'.$plugin.'/db/install.xml'; - $targettable = 'surveypro'.$type.'_'.$plugin; - $uselessfields = ['id', 'itemid']; + $context = \context_module::instance($this->cm->id); - // Some plugins are missing the install.xml because they havn't attributes. - if (!file_exists($installxml)) { - return $fieldlist; - } + $templatepath = $CFG->dirroot.'/mod/surveypro/template/'.$mtemplate.'/template.xml'; + if (!file_exists($templatepath)) { + return; } - $xmlall = simplexml_load_file($installxml); - foreach ($xmlall->children() as $xmltables) { // TABLES opening tag. - foreach ($xmltables->children() as $xmltable) { // TABLE opening tag. - $attributes = $xmltable->attributes(); - $tablename = $attributes['NAME']; - if ($tablename != $targettable) { + $fs = get_file_storage(); + + $templatecontent = file_get_contents($templatepath); + $simplexml = new \SimpleXMLElement($templatecontent); + foreach ($simplexml->children() as $xmlitem) { + foreach ($xmlitem->children() as $xmltable) { // Surveypro_item and surveypro_<>. + $tablename = $xmltable->getName(); + if ($tablename != 'surveypro_item') { continue; } - foreach ($xmltable->children() as $xmlfields) { // FIELDS opening tag. - foreach ($xmlfields->children() as $xmlfield) { // FIELD opening tag. - $attributes = $xmlfield->attributes(); - $fieldname = $attributes['NAME']; - if (in_array($fieldname, $uselessfields) === false) { - $fieldlist[] = (string)$attributes['NAME']; + foreach ($xmltable->children() as $xmlfield) { + $fieldname = $xmlfield->getName(); + if ($fieldname != 'embedded') { + continue; + } + foreach ($xmlfield->children() as $xmlfileattribute) { + $fileattributename = $xmlfileattribute->getName(); + if ($fileattributename == 'filename') { + $attributecontent = (string)$xmlfileattribute; + $filename = get_string($attributecontent, 'surveyprotemplate_'.$mtemplate); + } + if ($fileattributename == 'filecontent') { + $attributecontent = (string)$xmlfileattribute; + $encodedcontent = get_string($attributecontent, 'surveyprotemplate_'.$mtemplate); + $filecontent = base64_decode($encodedcontent); } } - break; + if (!$fs->file_exists($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid, '/', $filename)) { + // Add the new found file to filearea. + $filerecord = new \stdClass(); + $filerecord->contextid = $context->id; + $filerecord->component = 'mod_surveypro'; + $filerecord->filearea = SURVEYPRO_ITEMCONTENTFILEAREA; + $filerecord->itemid = $itemid; + $filerecord->filepath = '/'; + $filerecord->filename = $filename; + + $fileinfo = $fs->create_file_from_string($filerecord, $filecontent); + } } - break; - } - break; - } - - return $fieldlist; - } - - /** - * Get plugin versions. - * - * @return versions of each field and format plugin - */ - public static function get_subplugin_versions() { - $versions = []; - $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; - - foreach ($types as $type) { - $plugins = surveypro_get_plugin_list($type, true); - foreach ($plugins as $plugin => $unused) { - $versions[$plugin] = get_config('surveypro'.$plugin, 'version'); } } - - return $versions; } } diff --git a/classes/tools_export.php b/classes/tools_export.php index 461e7927f5a..4bfd6a28bc4 100644 --- a/classes/tools_export.php +++ b/classes/tools_export.php @@ -266,9 +266,8 @@ public function export_get_output_headers() { $itemseedskeys = []; foreach ($itemseeds as $itemseed) { - $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemseed->plugin; - $where = ['itemid' => $itemseed->id]; - $currentheader = $DB->get_field($tablename, 'variable', $where); + $where = ['id' => $itemseed->id]; + $currentheader = $DB->get_field('surveypro_item', 'variable', $where); $headerlabels[] = $currentheader; $itemseedskeys[] = $itemseed->id; if ($this->formdata->outputstyle == SURVEYPRO_RAW) { @@ -567,7 +566,7 @@ public function decode_content($richsubmission) { } else { $itemid = $richsubmission->itemid; $plugin = $richsubmission->plugin; - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $plugin); $return = $item->userform_db_to_export($richsubmission); } diff --git a/classes/tools_import.php b/classes/tools_import.php index fd36f9473ef..d2b8456a8d9 100644 --- a/classes/tools_import.php +++ b/classes/tools_import.php @@ -512,10 +512,10 @@ public function get_survey_infos() { $whereparams = ['surveyproid' => $this->surveypro->id]; foreach ($pluginlist as $plugin) { $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - $canbemandatory = $classname::item_uses_mandatory_dbfield(); + $usesmandatoryattribute = $classname::has_mandatoryattribute(); $tablename = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin; - $fieldname = ($canbemandatory) ? ', p.required' : ''; + $fieldname = ($usesmandatoryattribute) ? ', p.required' : ''; $sql = 'SELECT p.itemid, p.variable'.$fieldname.' FROM {surveypro_item} i JOIN {'.$tablename.'} p ON p.itemid = i.id @@ -528,7 +528,7 @@ public function get_survey_infos() { if ($classname::response_uses_format()) { $surveyheaders[$itemvar->itemid.SURVEYPRO_IMPFORMATSUFFIX] = $itemvar->variable.SURVEYPRO_IMPFORMATSUFFIX; } - if ($canbemandatory) { + if ($usesmandatoryattribute) { if ($itemvar->required > 0) { $requireditems[] = $itemvar->itemid; } @@ -645,7 +645,7 @@ public function buil_item_helpers() { continue; } } - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid); // Itemhelperinfo. $itemhelper = new \stdClass(); @@ -663,7 +663,7 @@ public function buil_item_helpers() { if ($itemhelper->usespositionalanswer) { // The count of the options is enough. - $optionscountpercol[$col] = count($item->get_content_array(SURVEYPRO_LABELS, 'options')); + $optionscountpercol[$col] = count($item->get_textarea_content(SURVEYPRO_LABELS, 'options')); } } diff --git a/classes/utemplate_apply.php b/classes/utemplate_apply.php index 7f4f186d819..8e77a31c655 100644 --- a/classes/utemplate_apply.php +++ b/classes/utemplate_apply.php @@ -38,6 +38,11 @@ */ class utemplate_apply extends utemplate_base { + /** + * @var int User confirmation to actions + */ + protected $action; + /** * @var int User confirmation to actions */ @@ -91,22 +96,6 @@ private function set_confirm($confirm) { // MARK get. - /** - * Get user template content. - * - * @param int $utemplateid - * @return void - */ - public function get_utemplate_content($utemplateid=0) { - $fs = get_file_storage(); - if (empty($utemplateid)) { - $utemplateid = $this->utemplateid; - } - $xmlfile = $fs->get_file_by_id($utemplateid); - - return $xmlfile->get_content(); - } - /** * Get the content of the user template drop down menu. * @@ -153,9 +142,8 @@ public function add_items_from_template() { $naturalsortindex = 0; foreach ($simplexml->children() as $xmlitem) { - // Read the attributes of the item node: - // The xmlitem looks like: . + // The xmlitem looks like: . foreach ($xmlitem->attributes() as $attribute => $value) { if ($attribute == 'type') { $currenttype = (string)$value; @@ -165,52 +153,62 @@ public function add_items_from_template() { } } - // Take care to details. // Load the item class in order to call its methods to validate $record before saving it. - $item = surveypro_get_item($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, 0, $currenttype, $currentplugin); - foreach ($xmlitem->children() as $xmltable) { // Tables are: surveypro_item and surveypro(field|format)_<>. + foreach ($xmlitem->children() as $xmltable) { // Tables are: surveypro_item and surveypro(field|format)_(plugin). $tablename = $xmltable->getName(); - if ($tablename == 'surveypro_item') { - $currenttablestructure = $this->get_table_structure(); - } else { - $currenttablestructure = $this->get_table_structure($currenttype, $currentplugin); - } + // Begin of: Create a new record and fill it with basic infor and defaults. $record = new \stdClass(); - - // Add to $record mandatory fields that will be overwritten, hopefully, with the content of the usertemplate. - $record->surveyproid = (int)$this->surveypro->id; - $record->type = $currenttype; - $record->plugin = $currentplugin; if ($tablename == 'surveypro_item') { - $item->item_add_mandatory_base_fields($record); + $itemid = 0; // This is the proof the surveypro_item record has not yet been saved. + + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure(); + + $record->surveyproid = (int)$this->surveypro->id; + $record->type = $currenttype; + $record->plugin = $currentplugin; + $item->item_add_fields_default_to_parent_table($record); } else { - $item->item_add_mandatory_plugin_fields($record); + // $tablestructure limits the fields that are going to be saved in the database. + $tablestructure = $this->get_table_structure($currenttype, $currentplugin); + + $record->itemid = $itemid; // It has been defined when surveypro_item record was saved. + $item->item_add_fields_default_to_child_table($record); } + // End of: Create a new record and fill it with basic infor and defaults. - foreach ($xmltable->children() as $xmlfield) { - $fieldname = $xmlfield->getName(); + // Begin of: Overwrite defaults with utemplate data. + foreach ($xmltable->children() as $xmlfield) { // Run over fields listed in the xml. + $xmltag = $xmlfield->getName(); // Generally $xmltag is the name of the field. // Tag always belong to surveypro_item table. - if ($fieldname == 'parent') { - // Debug: $label = 'Count of attributes of the field '.$fieldname;. + if ($xmltag == 'parent') { + // Debug: $label = 'Count of attributes of the field '.$xmltag;. // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. - foreach ($xmlfield->children() as $xmlparentattribute) { - $fieldname = $xmlparentattribute->getName(); - $fieldexists = in_array($fieldname, $currenttablestructure); + foreach ($xmlfield->children() as $xmlchildattribute) { + $xmltag = $xmlchildattribute->getName(); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlparentattribute; + $record->{$xmltag} = (string)$xmlchildattribute; } } continue; } - // Tag always belong to surveypro(field|format)_<> table - // so: ($fieldname == 'embedded') only when surveypro_item has already been saved... - // so: $itemid is known. - if ($fieldname == 'embedded') { - // Debug: $label = 'Count of attributes of the field '.$fieldname;. + // Tag always belong to surveypro_item table. + if ($xmltag == 'embedded') { + // Urgently create a record because its id is needed here. + // Please do not create a new record twice. + // If 2 embedded pictures are part of the content, take care to create only one record. + // If you already created the record for the first embedded picture, do not create one more record now. + if (empty($itemid)) { + $itemid = $DB->insert_record('surveypro_item', $record); + } + + // Debug: $label = 'Count of attributes of the field '.$xmltag; // Debug: echo '
'.$label.': '.count($xmlfield->children()).'
';. foreach ($xmlfield->children() as $xmlfileattribute) { $fileattributename = $xmlfileattribute->getName(); @@ -224,8 +222,8 @@ public function add_items_from_template() { // Debug: echo 'I need to add: "'.$filename.'" to the filearea
';. - // Add the file described by $filename and $filecontent to filearea, - // alias, add pictures found in the utemplate to filearea. + // Add the file described by $filename and $filecontent to filearea. + // Alias, add pictures found in the utemplate to filearea. $filerecord = new \stdClass(); $filerecord->contextid = $this->context->id; $filerecord->component = 'mod_surveypro'; @@ -241,38 +239,96 @@ public function add_items_from_template() { // It does not know whether the xml is old and holds no longer needed fields // or does not hold fields that are now mandatory. // Because of this, I can not SIMPLY add $fieldname to $record but I need to make some more investigation. - // I neglect no longer used fields, here. + // I neglect unneeded used fields, here. // I will add mandatory (but missing because the usertemplate may be old) fields, // before saving in the frame of the $item->item_force_coherence. - $fieldexists = in_array($fieldname, $currenttablestructure); + $fieldexists = in_array($xmltag, $tablestructure); if ($fieldexists) { - $record->{$fieldname} = (string)$xmlfield; + $record->{$xmltag} = (string)$xmlfield; } } + // End of: Overwrite defaults with utemplate data. - unset($record->id); - + // Begin of: Overwrite defaults with utemplate data. if ($tablename == 'surveypro_item') { $naturalsortindex++; $record->sortindex = $naturalsortindex + $sortindexoffset; - if (!empty($record->parentid)) { + if (!empty($record->parentid)) { // If I have a parent, its record was already saved. $whereparams = ['surveyproid' => $this->surveypro->id]; $whereparams['sortindex'] = $record->parentid + $sortindexoffset; $record->parentid = $DB->get_field('surveypro_item', 'id', $whereparams, MUST_EXIST); } - $itemid = $DB->insert_record($tablename, $record); + $item->item_validate_variablename($record); + if (empty($itemid)) { // If the record in surveypro_item has NOT already been added. + $itemid = $DB->insert_record('surveypro_item', $record); + } else { + // I had to urgently create a record to get its id in order to give it to $fs->create_file_from_string. + // Now I can not create a different record because I passed the id of the existing one. + // So I update the found record. + $record->id = $itemid; + $DB->update_record('surveypro_item', $record); + } } else { // Take care to details. $item->item_force_coherence($record); - $item->item_validate_variablename($record, $itemid); - $record->itemid = $itemid; $DB->insert_record($tablename, $record, false); } + // End of: Overwrite defaults with utemplate data. } } } + /** + * Ask for confirmation when a utemplate is applied directly. + * + * @return void + */ + public function ask_for_confirmation() { + global $OUTPUT; + + if ($this->confirm == SURVEYPRO_UNCONFIRMED) { + $message = get_string('confirm_applyutemplate', 'mod_surveypro'); + + $optionbase = ['s' => $this->cm->instance, 'act' => $this->action, 'sesskey' => sesskey()]; + + $optionsyes = $optionbase; + $optionsyes['cnf'] = SURVEYPRO_CONFIRMED_YES; + $optionsyes['section'] = 'apply'; + $optionsyes['fid'] = $this->utemplateid; + $optionsyes['action'] = SURVEYPRO_APPLYUTEMPLATE; + $urlyes = new \moodle_url('/mod/surveypro/utemplates.php', $optionsyes); + $yeslabel = get_string('yes_applyutemplate', 'mod_surveypro'); + $buttonyes = new \single_button($urlyes, $yeslabel); + + $optionsno = $optionbase; + $optionsno['cnf'] = SURVEYPRO_CONFIRMED_NO; + $optionsyes['section'] = 'manage'; + $urlno = new \moodle_url('/mod/surveypro/utemplates.php', $optionsno); + $buttonno = new \single_button($urlno, get_string('no')); + + echo $OUTPUT->confirm($message, $buttonyes, $buttonno); + echo $OUTPUT->footer(); + die(); + } + } + + /** + * Execute last minute check before applying user templates. + * + * @return void + */ + public function lastminute_template_check() { + if (!empty($this->utemplateid)) { + $utemplateid = $this->utemplateid; + } else { + $parts = explode('_', $this->formdata->usertemplateinfo); + $utemplateid = $parts[1]; + } + + $xml = $this->get_utemplate_content($utemplateid); + $this->validate_xml($xml); + } /** * Apply template. @@ -280,21 +336,25 @@ public function add_items_from_template() { * @return void */ public function apply_template() { - $applyction = $this->formdata->action; - $parts = explode('_', $this->formdata->usertemplateinfo); - $this->utemplateid = $parts[1]; + if (!isset($this->formdata->action)) { + $applyaction = SURVEYPRO_IGNOREITEMS; + } else { + $applyaction = $this->formdata->action; + $parts = explode('_', $this->formdata->usertemplateinfo); + $this->utemplateid = $parts[1]; + } // Before continuing. - if ($applyction != SURVEYPRO_DELETEALLITEMS) { + if ($applyaction != SURVEYPRO_DELETEALLITEMS) { // Dispose assignemnt of pages. $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); $utilitylayoutman->reset_pages(); } - $this->trigger_event('usertemplate_applied', $applyction); + $this->trigger_event('usertemplate_applied', $applyaction); // Begin the process executing preliminary actions. - switch ($applyction) { + switch ($applyaction) { case SURVEYPRO_IGNOREITEMS: break; case SURVEYPRO_HIDEALLITEMS: @@ -325,9 +385,8 @@ public function apply_template() { $utilitylayoutman->items_reindex(); break; - break; default: - $message = 'Unexpected $applyction = '.$applyction; + $message = 'Unexpected $applyaction = '.$applyaction; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } @@ -361,7 +420,7 @@ public function friendly_stop() { if ($this->surveypro->template && (!$riskyediting)) { // This survey comes from a master template so it is multilang. echo $OUTPUT->notification(get_string('applyusertemplatedenied02', 'mod_surveypro'), 'notifyproblem'); - $url = new \moodle_url('/mod/surveypro/view.php', ['s' => $this->surveypro->id, 'section' => 'submissionform']); + $url = new \moodle_url('/mod/surveypro/view.php', ['s' => $this->surveypro->id, 'section' => 'responsesubmit']); echo $OUTPUT->continue_button($url); echo $OUTPUT->footer(); die(); diff --git a/classes/utemplate_import.php b/classes/utemplate_import.php index b1dbd2c0872..3c21eee4dd9 100644 --- a/classes/utemplate_import.php +++ b/classes/utemplate_import.php @@ -77,22 +77,6 @@ public function get_filemanager_options() { return $templateoptions; } - /** - * Get user template content. - * - * @param int $utemplateid - * @return void - */ - public function get_utemplate_content($utemplateid=0) { - $fs = get_file_storage(); - if (empty($utemplateid)) { - $utemplateid = $this->utemplateid; - } - $xmlfile = $fs->get_file_by_id($utemplateid); - - return $xmlfile->get_content(); - } - // MARK other. /** diff --git a/classes/utemplate_manage.php b/classes/utemplate_manage.php index 15c03f86b05..2344509424c 100644 --- a/classes/utemplate_manage.php +++ b/classes/utemplate_manage.php @@ -187,11 +187,13 @@ public function delete_utemplate() { if ($this->confirm == SURVEYPRO_CONFIRMED_YES) { // Put the name in the gobal vaiable, to remember it for the log. + // At log time I haven't availability of the file so I can not ask fot its name. $this->templatename = $this->get_utemplate_name(); $fs = get_file_storage(); $xmlfile = $fs->get_file_by_id($this->utemplateid); $a = $xmlfile->get_filename(); + $xmlfile->delete(); $this->trigger_event('usertemplate_deleted'); @@ -217,6 +219,7 @@ public function display_usertemplates_table() { require_once($CFG->libdir.'/tablelib.php'); + $canapplyutemplates = has_capability('mod/surveypro:applyusertemplates', $this->context); $candownloadutemplates = has_capability('mod/surveypro:downloadusertemplates', $this->context); $candeleteutemplates = has_capability('mod/surveypro:deleteusertemplates', $this->context); @@ -224,13 +227,17 @@ public function display_usertemplates_table() { $paramurlbase = ['s' => $this->cm->instance]; // End of $paramurlbase definition. + $applytitle = get_string('utemplate_apply', 'mod_surveypro'); + $iconparams = ['title' => $applytitle]; + $applyicn = new \pix_icon('stamp', $applytitle, 'surveypro', $iconparams); + $deletetitle = get_string('delete'); $iconparams = ['title' => $deletetitle]; $deleteicn = new \pix_icon('t/delete', $deletetitle, 'moodle', $iconparams); - $importtitle = get_string('exporttemplate', 'mod_surveypro'); - $iconparams = ['title' => $importtitle]; - $importicn = new \pix_icon('t/download', $importtitle, 'moodle', $iconparams); + $exporttitle = get_string('exporttemplate', 'mod_surveypro'); + $iconparams = ['title' => $exporttitle]; + $exporticn = new \pix_icon('t/download', $exporttitle, 'moodle', $iconparams); $table = new \flexible_table('templatelist'); @@ -297,6 +304,18 @@ public function display_usertemplates_table() { $row++; $icons = ''; + + // SURVEYPRO_APPLYUTEMPLATE. + if ($canapplyutemplates) { + $paramurl = $paramurlbase; + $paramurl['act'] = SURVEYPRO_APPLYUTEMPLATE; + $paramurl['section'] = 'apply'; + $paramurl['sesskey'] = sesskey(); + + $link = new \moodle_url('/mod/surveypro/utemplates.php', $paramurl); + $icons .= $OUTPUT->action_icon($link, $applyicn, null, ['title' => $applytitle]); + } + // SURVEYPRO_DELETEUTEMPLATE. if ($candeleteutemplates) { if ($utemplate->userid == $USER->id) { // The user template can be deleted only by its owner. @@ -318,7 +337,7 @@ public function display_usertemplates_table() { $paramurl['sesskey'] = sesskey(); $link = new \moodle_url('/mod/surveypro/utemplates.php', $paramurl); - $icons .= $OUTPUT->action_icon($link, $importicn, null, ['title' => $importtitle]); + $icons .= $OUTPUT->action_icon($link, $exporticn, null, ['title' => $exporttitle]); } $tablerow[] = $icons; @@ -326,7 +345,6 @@ public function display_usertemplates_table() { $table->add_data($tablerow); } $table->set_attribute('align', 'center'); - $table->summary = get_string('templatelist', 'mod_surveypro'); $table->print_html(); } diff --git a/classes/utemplate_save.php b/classes/utemplate_save.php index 882812c7117..b623132e2fe 100644 --- a/classes/utemplate_save.php +++ b/classes/utemplate_save.php @@ -76,15 +76,31 @@ public function welcome_save_message() { } /** - * Write template content. + * Write user template content. + * + * TAKE CARE + * At "usertemplate creation" time, in order to recover the ID of the parent record to be assigned to the child record in a + * possible parent-child relation, I write, in the parentid field of the child record in the XML, the sortindex of the parent + * record and not the ID of the parent record. At "usertemplate apply" time, to get the ID of the parent record, I get the + * sortindex written in the XML and I add to it the sortindexoffset (that is nothing more than the number of preexisting items + * in the accepting surveypro) that I calculate at the beginning of the "usertemplate apply" process. Finally I get the ID of + * the item that has sortindex equal to ("sortindex taken from the usertemplate" + sortindexoffset) with a query "SELECT the ID + * of the item WHERE sortindex = ...". + * + * When the user creates a usertemplate with only visible items, this trick does not work because the parent's sortindex could + * be 100 even if the parent is the first record (and, in my plan, is should have sortindex == 1). + * + * For this reason, at "usertemplate creation" time, I AM FORCED to use a "hot" calculated sortindex instead of using the one + * taken from the db. * * @param boolean $visiblesonly * @return void */ - public function write_template_content($visiblesonly=true) { + public function write_template_content($visiblesonly) { global $DB; $pluginversion = self::get_subplugin_versions(); + $where = ['surveyproid' => $this->surveypro->id]; if ($visiblesonly) { $where['hidden'] = '0'; @@ -96,7 +112,7 @@ public function write_template_content($visiblesonly=true) { $xmltemplate = new \SimpleXMLElement(''); foreach ($itemseeds as $itemseed) { - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $xmlitem = $xmltemplate->addChild('item'); $xmlitem->addAttribute('type', $itemseed->type); @@ -105,72 +121,102 @@ public function write_template_content($visiblesonly=true) { $xmlitem->addAttribute('version', $pluginversion[$index]); // Surveypro_item. - $xmltable = $xmlitem->addChild('surveypro_item'); $structure = $this->get_table_structure(); + $unrelevantfields = ['id', 'surveyproid', 'type', 'plugin', 'sortindex', 'formpage', 'timecreated', 'timemodified']; + $unrelevantfields = array_merge($unrelevantfields, $item->item_expected_null_fields()); + $xmltable = $xmlitem->addChild('surveypro_item'); foreach ($structure as $field) { + if (in_array($field, $unrelevantfields)) { + continue; + } + + if ($field == 'content') { + // If $field == 'content' I can not use the property of the object $item because + // in case of pictures, for instance, $item->content has to look like: + // 'MMM' + // and not like: + // 'img1get_field('surveypro_item', 'content', ['id' => $itemseed->id], MUST_EXIST); + if (core_text::strlen($val)) { + $xmlfield = $xmltable->addChild('content', htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + } + if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemseed->id)) { + foreach ($files as $file) { + $filename = $file->get_filename(); + if ($filename == '.') { + continue; + } + $xmlembedded = $xmltable->addChild('embedded'); + $xmlembedded->addChild('filename', $filename); + $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); + } + } + + continue; + } + if ($field == 'parentid') { $parentid = $item->get_parentid(); if ($parentid) { // Store the sortindex of the parent instead of its id, because at restore time parentid will change. + // Get $parentsortindex. $whereparams = ['id' => $parentid]; - $sortindex = $DB->get_field('surveypro_item', 'sortindex', $whereparams, MUST_EXIST); - $val = $item->get_parentvalue(); + $parentsortindex = $DB->get_field('surveypro_item', 'sortindex', $whereparams, MUST_EXIST); + + if ($visiblesonly) { + $sql = 'SELECT COUNT(\'x\') + FROM {surveypro_item} + WHERE surveyproid = :surveyproid + AND hidden = :hidden + AND sortindex < :sortindex'; + $whereparams = ['surveyproid' => $this->surveypro->id, 'hidden' => 1, 'sortindex' => $parentsortindex]; + $hidedsortindex = $DB->count_records_sql($sql, $whereparams); + $parentsortindex -= $hidedsortindex; + } + + // Get $parentsortindex. + $parentvalue = $item->get_parentvalue(); $xmlparent = $xmltable->addChild('parent'); - $xmlfield = $xmlparent->addChild('parentid', $sortindex); - $xmlfield = $xmlparent->addChild('parentvalue', $val); + $xmlfield = $xmlparent->addChild('parentid', $parentsortindex); + $xmlfield = $xmlparent->addChild('parentvalue', $parentvalue); } // Otherwise: It is empty, do not evaluate: jump. continue; } + if ($field == 'parentvalue') { continue; } $val = $item->get_generic_property($field); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (core_text::strlen($val)) { $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. } // Child table. + $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; $structure = $this->get_table_structure($itemseed->type, $itemseed->plugin); + // Take care: some items plugin may be free of their own specific table. if (!count($structure)) { continue; } - $tablename = 'surveypro'.$itemseed->type.'_'.$itemseed->plugin; + $unrelevantfields = ['id', 'itemid']; $xmltable = $xmlitem->addChild($tablename); foreach ($structure as $field) { - // If $field == 'content' I can not use the property of the object $item because - // in case of pictures, for instance, $item->content has to look like: - // 'MMM' - // and not like: - // 'img1get_generic_property($field); - } else { - $val = $DB->get_field($tablename, 'content', ['itemid' => $itemseed->id], MUST_EXIST); + + if (in_array($field, $unrelevantfields)) { + continue; } + $val = $item->get_generic_property($field); + $val = htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE); if (core_text::strlen($val)) { - $xmlfield = $xmltable->addChild($field, htmlspecialchars($val, ENT_QUOTES | ENT_SUBSTITUTE)); + $xmlfield = $xmltable->addChild($field, $val); } // Otherwise: It is empty, do not evaluate: jump. - - if ($field == 'content') { - $itemid = $item->get_itemid(); - if ($files = $fs->get_area_files($context->id, 'mod_surveypro', SURVEYPRO_ITEMCONTENTFILEAREA, $itemid)) { - foreach ($files as $file) { - $filename = $file->get_filename(); - if ($filename == '.') { - continue; - } - $xmlembedded = $xmltable->addChild('embedded'); - $xmlembedded->addChild('filename', $filename); - $xmlembedded->addChild('filecontent', base64_encode($file->get_content())); - } - } - } } } diff --git a/classes/utility_layout.php b/classes/utility_layout.php index d63500361ee..499b068c5ac 100644 --- a/classes/utility_layout.php +++ b/classes/utility_layout.php @@ -379,7 +379,7 @@ public function delete_answers($whereparams, $item=null) { debugging('Error at line '.__LINE__.' of file '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $validanswerparams = ['id', 'submissionid', 'itemid', 'content']; + $validanswerparams = ['id', 'submissionid', 'itemid', 'content', 'verified']; $startingparams = array_keys($whereparams); foreach ($startingparams as $startingparam) { if (!in_array($startingparam, $validanswerparams)) { @@ -610,7 +610,7 @@ public function get_answers_idlist_from_answers($whereparams) { global $DB; // Verify input params integrity. - $validanswerparams = ['id', 'submissionid', 'itemid', 'content']; + $validanswerparams = ['id', 'submissionid', 'itemid', 'content', 'verified']; $startingparams = array_keys($whereparams); foreach ($startingparams as $startingparam) { if (!in_array($startingparam, $validanswerparams)) { diff --git a/classes/utility_mform.php b/classes/utility_mform.php deleted file mode 100644 index 21a2198a4c4..00000000000 --- a/classes/utility_mform.php +++ /dev/null @@ -1,66 +0,0 @@ -. - -/** - * The utility_mform class - * - * @package mod_surveypro - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_surveypro; - -/** - * The class managing mform classes - * - * @package mod_surveypro - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class utility_mform { - - /** - * Register classes extending mform classes - * - * @return void - */ - public static function register_form_elements() { - global $CFG; - - $basepath = $CFG->dirroot.'/mod/surveypro'; - $types = [SURVEYPRO_TYPEFIELD, SURVEYPRO_TYPEFORMAT]; - - foreach ($types as $type) { - $plugins = surveypro_get_plugin_list($type); - foreach ($plugins as $plugin) { - $filepath = $basepath.'/'.$type.'/'.$plugin.'/mform'; - if (file_exists($filepath) && is_dir($filepath)) { - $classfiles = scandir($filepath); - foreach ($classfiles as $classfile) { - if ($classfile[0] == '.') { // Hidden files, '.' and '..'. - continue; - } - $basename = basename($classfile, '.php'); - $extendingclass = 'mod_surveypro_'.$basename; - $parentpath = $filepath.'/'.$classfile; - \MoodleQuickForm::registerElementType($extendingclass, $parentpath, 'surveypromform_'.$basename); - } - } - } - } - } -} diff --git a/classes/view_cover.php b/classes/view_cover.php index 9b496f1eae5..78e2296e828 100644 --- a/classes/view_cover.php +++ b/classes/view_cover.php @@ -157,7 +157,7 @@ public function display_cover() { $paramurl['s'] = $this->cm->instance; $paramurl['mode'] = SURVEYPRO_NEWRESPONSEMODE; $paramurl['area'] = 'surveypro'; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; $paramurl['begin'] = 1; $url = new \moodle_url('/mod/surveypro/view.php', $paramurl); $message = get_string('addnewsubmission', 'mod_surveypro'); diff --git a/classes/view_submissionlist.php b/classes/view_responselist.php similarity index 97% rename from classes/view_submissionlist.php rename to classes/view_responselist.php index 9ae5dc6892e..454ae31371a 100644 --- a/classes/view_submissionlist.php +++ b/classes/view_responselist.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionlist class + * The view_responselist class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -35,7 +35,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionlist { +class view_responselist { /** * @var object Course module object @@ -662,6 +662,7 @@ public function display_submissions_table() { $caneditownsubmissions = has_capability('mod/surveypro:editownsubmissions', $this->context); $caneditotherssubmissions = has_capability('mod/surveypro:editotherssubmissions', $this->context); $canduplicateownsubmissions = has_capability('mod/surveypro:duplicateownsubmissions', $this->context); + $canduplicateotherssubmissions = has_capability('mod/surveypro:duplicateotherssubmissions', $this->context); $candeleteownsubmissions = has_capability('mod/surveypro:deleteownsubmissions', $this->context); $candeleteotherssubmissions = has_capability('mod/surveypro:deleteotherssubmissions', $this->context); $cansavetopdfownsubmissions = has_capability('mod/surveypro:savetopdfownsubmissions', $this->context); @@ -837,9 +838,29 @@ public function display_submissions_table() { } // Actions. + $icons = ''; $paramurl = $paramurlbase; $paramurl['submissionid'] = $submission->submissionid; + // View. + $displayviewicon = false; + if ($ismine) { // Owner is me. + $displayviewicon = ($submission->status != SURVEYPRO_STATUSINPROGRESS); + } else { + if ($mysamegroup) { // Owner is from a group of mine. + $displayviewicon = ($submission->status == SURVEYPRO_STATUSINPROGRESS) ? false : $canseeotherssubmissions; + } + } + if ($displayviewicon) { + $paramurl['mode'] = SURVEYPRO_READONLYMODE; + $paramurl['begin'] = 1; + $paramurl['section'] = 'responsesubmit'; + + $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); + $paramlink = ['id' => 'view_submission_'.$submissionsuffix, 'title' => $readonlyaccessstr]; + $icons .= $OUTPUT->action_icon($link, $readonlyicn, null, $paramlink); + } + // Edit. $displayediticon = false; if ($ismine) { // Owner is me. @@ -863,27 +884,19 @@ public function display_submissions_table() { if ($displayediticon) { $paramurl['mode'] = SURVEYPRO_EDITMODE; $paramurl['begin'] = 1; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; if ($submission->status == SURVEYPRO_STATUSINPROGRESS) { // Here title and alt are ALWAYS $nonhistoryeditstr. $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); $paramlink = ['id' => 'edit_submission_'.$submissionsuffix, 'title' => $nonhistoryeditstr]; - $icons = $OUTPUT->action_icon($link, $nonhistoryediticn, null, $paramlink); + $icons .= $OUTPUT->action_icon($link, $nonhistoryediticn, null, $paramlink); } else { // Here title and alt depend from $this->surveypro->history. $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); $paramlink = ['id' => $linkidprefix.$submissionsuffix, 'title' => $attributestr]; - $icons = $OUTPUT->action_icon($link, $attributeicn, null, $paramlink); + $icons .= $OUTPUT->action_icon($link, $attributeicn, null, $paramlink); } - } else { - $paramurl['mode'] = SURVEYPRO_READONLYMODE; - $paramurl['begin'] = 1; - $paramurl['section'] = 'submissionform'; - - $link = new \moodle_url('/mod/surveypro/view.php', $paramurl); - $paramlink = ['id' => 'view_submission_'.$submissionsuffix, 'title' => $readonlyaccessstr]; - $icons = $OUTPUT->action_icon($link, $readonlyicn, null, $paramlink); } // Duplicate. @@ -893,7 +906,7 @@ public function display_submissions_table() { } else { if ($mysamegroup) { // Owner is from a group of mine. // I should be here only if $canseeotherssubmissions = true. - $displayduplicateicon = $caneditotherssubmissions; + $displayduplicateicon = $canduplicateotherssubmissions; } } if ($displayduplicateicon) { // I am the owner or a groupmate. @@ -967,7 +980,6 @@ public function display_submissions_table() { } $submissions->close(); - $table->summary = get_string('submissionslist', 'mod_surveypro'); $table->print_html(); // If this is the output of a search and nothing has been found add a way to show all submissions. @@ -993,6 +1005,7 @@ public function show_action_buttons($tifirst, $tilast) { $candeleteownsubmissions = has_capability('mod/surveypro:deleteownsubmissions', $this->context); $candeleteotherssubmissions = has_capability('mod/surveypro:deleteotherssubmissions', $this->context); + $canenjoydeleteallsubmissionsbutton = has_capability('mod/surveypro:enjoydeleteallsubmissionsbutton', $this->context); $canseeotherssubmissions = has_capability('mod/surveypro:seeotherssubmissions', $this->context); $userid = ($canseeotherssubmissions) ? null : $USER->id; @@ -1006,8 +1019,10 @@ public function show_action_buttons($tifirst, $tilast) { // End of: is the button to add one more response going to be the page? // Begin of: is the button to delete all responses going to be the page? - $deleteall = $candeleteownsubmissions; + $deleteall = true; + $deleteall = $deleteall && $candeleteownsubmissions; $deleteall = $deleteall && $candeleteotherssubmissions; + $deleteall = $deleteall && $canenjoydeleteallsubmissionsbutton; $deleteall = $deleteall && empty($this->searchquery); $deleteall = $deleteall && empty($tifirst); // Hide the deleteall button if not all the responses are shown. $deleteall = $deleteall && empty($tilast); // Hide the deleteall button if not all the responses are shown. @@ -1020,7 +1035,7 @@ public function show_action_buttons($tifirst, $tilast) { $paramurl['mode'] = SURVEYPRO_NEWRESPONSEMODE; $paramurl['begin'] = 1; $paramurl['area'] = 'surveypro'; - $paramurl['section'] = 'submissionform'; + $paramurl['section'] = 'responsesubmit'; $addurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); $buttoncount = 1; @@ -1205,7 +1220,7 @@ public function show_thanks_page($responsestatus, $justsubmitted) { $paramurlbase = ['s' => $this->cm->instance]; if ($cansubmitmore) { // If the user is allowed to submit one more response. - $paramurl = $paramurlbase + ['mode' => SURVEYPRO_NEWRESPONSEMODE, 'begin' => 1, 'section' => 'submissionform']; + $paramurl = $paramurlbase + ['mode' => SURVEYPRO_NEWRESPONSEMODE, 'begin' => 1, 'section' => 'responsesubmit']; $buttonurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); $onemore = new \single_button($buttonurl, get_string('addnewsubmission', 'mod_surveypro'), 'post', 'primary'); @@ -1699,7 +1714,7 @@ public function submission_to_pdf() { $answernotprovided = get_string('answernotsubmitted', 'mod_surveypro'); foreach ($itemseeds as $itemseed) { // Pagebreaks are not selected by surveypro_fetch_items_seeds. - $item = surveypro_get_item($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->id, $itemseed->type, $itemseed->plugin); $template = $item::get_pdf_template(); if (!$template) { @@ -1813,8 +1828,8 @@ private function add_pdf_details($pdf, $user, $timecreated, $timemodified) { // Set document information. $pdf->SetCreator(PDF_CREATOR); $pdf->SetAuthor('moodle-mod_surveypro'); - $pdf->SetTitle(get_string('userresponse', 'mod_survyepro')); - $pdf->SetSubject(get_string('pdfsubject', 'mod_survyepro')); + $pdf->SetTitle(get_string('userresponse', 'mod_surveypro')); + $pdf->SetSubject(get_string('pdfsubject', 'mod_surveypro')); $textheader = $this->get_header_text($user, $timecreated, $timemodified); $pdf->SetHeaderData('', 0, $this->surveypro->name, $textheader, [0, 64, 255], [0, 64, 128]); diff --git a/classes/view_submissionsearch.php b/classes/view_responsesearch.php similarity index 96% rename from classes/view_submissionsearch.php rename to classes/view_responsesearch.php index 9b10f780224..b5dcc759609 100644 --- a/classes/view_submissionsearch.php +++ b/classes/view_responsesearch.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionsearch class + * The view_responsesearch class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -33,7 +33,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionsearch { +class view_responsesearch { /** * @var object Course module object @@ -120,7 +120,7 @@ public function get_searchparamurl() { continue; } } - $item = surveypro_get_item($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); $userdata = new \stdClass(); $item->userform_get_user_answer($iteminfo->contentperelement, $userdata, true); diff --git a/classes/view_submissionform.php b/classes/view_responsesubmit.php similarity index 87% rename from classes/view_submissionform.php rename to classes/view_responsesubmit.php index 3df84e05f90..40c03aff0fa 100644 --- a/classes/view_submissionform.php +++ b/classes/view_responsesubmit.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * The view_submissionform class + * The view_responsesubmit class * * @package mod_surveypro * @copyright 2013 onwards kordan @@ -36,7 +36,7 @@ * @copyright 2013 onwards kordan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class view_submissionform extends formbase { +class view_responsesubmit extends formbase { /** * @var int $mode @@ -181,7 +181,7 @@ private function save_surveypro_submission() { $timenow = time(); $savebutton = isset($this->formdata->savebutton); $saveasnewbutton = isset($this->formdata->saveasnewbutton); - // Useless: $nextbutton = isset($this->formdata->nextbutton);. + // Useless: $nextbutton = isset($this->formdata->nextbutton); $pausebutton = isset($this->formdata->pausebutton); // Useless: $prevbutton = isset($this->formdata->prevbutton);. if ($saveasnewbutton) { @@ -192,7 +192,7 @@ private function save_surveypro_submission() { // I don't save the status here because it is useless // the status is defined from the validity of each answer - // and will be saved after each respose in function save_user_data. + // and will be saved after each respose in function save_user_response. if (empty($this->formdata->submissionid)) { // Add a new record to surveypro_submission. @@ -223,7 +223,7 @@ private function save_surveypro_submission() { $submission->timecreated = $timenow; } - // Note: $DB->update_record must be inside curly brackets otherwise + // Note: $DB->update_record must be inside curly brackets (this if statement) otherwise // using "<< previous" or "next >>" to browse the submission // I get the error: // moodle_database::update_record_raw() no fields found. @@ -396,7 +396,7 @@ private function save_surveypro_submission() { * asking to the parent class to manage its own data * passing it $iteminfo->contentperelement. */ - public function save_user_data() { + public function save_user_response() { global $DB, $COURSE; $savebutton = isset($this->formdata->savebutton); @@ -405,14 +405,14 @@ public function save_user_data() { $prevbutton = isset($this->formdata->prevbutton); $nextbutton = isset($this->formdata->nextbutton); - // Drop out undesired answers from the submission. - if (!$this->surveypro->newpageforchild) { - // TAKE CARE: It is not enough to drop out unexpected answers. - // If the response is new, dropping an answer from $this->formdata make you sure the related value will not be saved - // but if the response is not new you may have the answer already in the database - // and you need to actually delete the old datum from DB! Ignoring it is not enough. - $this->drop_undesired_answers(); - } + // There are two types of undesired answers. + // The first: all the answers, of the current submission, coming from disabled item. + // The second: all the answers already saved to database but no longer valid. + // This second type comes from the following scenario: + // User edits an already submitted response. He/she changes the answer to a parent item. (Yes to no or whatever). + // There may be answers already saved in the database FOR THE SAME SUBMISSION that were allowed yesterday + // but that are not allowed now after the current change to the answer to the parent item. I have to delete them. + $this->drop_undesired_answers(); if ($savebutton || $saveasnewbutton) { $this->drop_unverified_data(); @@ -500,7 +500,7 @@ public function save_user_data() { $useranswer->timecreated = time(); $useranswer->verified = ($prevbutton || $pausebutton) ? 0 : 1; - $item = surveypro_get_item($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $iteminfo->itemid, $iteminfo->type, $iteminfo->plugin); // Now I ask to each item the answer for the db starting from what the user provided ($iteminfo->contentperelement). $item->userform_get_user_answer($iteminfo->contentperelement, $useranswer, false); @@ -521,7 +521,7 @@ public function save_user_data() { // 3) User reads the url and understands that the formapge is passed in GET (visible in the url). // 4) At page 3 (the page the user still does not see) of the surveypro there is mandatory field. // 5) Because of 3) user jumps to page 4 and make the final submit. - // This check is needed to verify that EACH mandatory surveypro field was actually saved. + // A check is needed to verify that EACH mandatory surveypro field was actually saved. // SECOND SCENARIO. // Let's suppose the following scenario. @@ -532,7 +532,7 @@ public function save_user_data() { // 5) User return back to page 1 without filling the mandatory field. // 6) Page 2 is saved WITHOUT the mandatory field because when the user moves back, the form VALIDATION is not executed. // 7) Because of 3) user jumps to page 3 and make the final submit. - // This check is needed to verify that EACH surveypro field was actually saved as VERIFIED. + // A check is needed to verify that EACH surveypro field was actually saved as VERIFIED. // I have to ALWAYS check for the validity of all responses // and not ONLY when ($savebutton || $saveasnewbutton) are presssed because... @@ -542,7 +542,7 @@ public function save_user_data() { // 4) I return back to page 1 // 5) Page 2 is saved WITHOUT the mandatory field because when the user moves back, the form VALIDATION is not executed. // 6) I use the breadcrumb to go somewhere else - // 7) the submission HAS TO BE saved as IN PROGRESS and not as CLOSED + // 7) So, the submission HAS TO BE saved as IN PROGRESS and not as CLOSED // even if ($savebutton || $saveasnewbutton) where never pressed. // Be optimistic. Let's start by assuming user was correct. @@ -600,14 +600,14 @@ private function check_mandatories_are_in() { $requireditems = []; foreach ($pluginlist as $plugin) { $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'\item'; - $canbemandatory = $classname::item_uses_mandatory_dbfield(); - if ($canbemandatory) { + $usesmandatoryattribute = $classname::has_mandatoryattribute(); + if ($usesmandatoryattribute) { $sql = 'SELECT i.id, i.parentid, i.parentvalue, i.reserved FROM {surveypro_item} i - JOIN {surveypro'.SURVEYPRO_TYPEFIELD.'_'.$plugin.'} p ON p.itemid = i.id + JOIN {surveyprofield_'.$plugin.'} p ON p.itemid = i.id WHERE i.surveyproid = :surveyproid AND i.hidden = :hidden - AND p.required > :required + AND i.required > :required ORDER BY p.itemid'; $whereparams = ['surveyproid' => $this->surveypro->id, 'hidden' => 0, 'required' => 0]; @@ -636,7 +636,7 @@ private function check_mandatories_are_in() { $this->responsestatus = SURVEYPRO_MISSINGMANDATORY; break; } else { - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $itemseed->parentid); + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); if ($parentitem->userform_is_child_allowed_static($this->get_submissionid(), $itemseed)) { // Parent is here but it allows this item as child in this submission. Answer was jumped. // Take care: this check is valid for chains of parent-child relations too. @@ -666,9 +666,9 @@ private function check_all_was_verified() { /** * Drop old answers saved with 'verified' = 0. - * They comes from data written in pages not validated (because user returned to previous page) - * They were converted to answers with 'verified' = 1 whaen the users arrived to the same page and moved forward - * and if they are still there... they must be deleted now. + * They comes from answers in pages not verified (because user returned to previous page) + * Unverified answers are set to 'verified' when the users arrives to the page where they are NOT DISABLED and moves forward. + * If, at submission time, unverified answers are still somewhere... they must be deleted. * * Example * page 1: What is your gender? @@ -677,18 +677,18 @@ private function check_all_was_verified() { * * User starts. * Page 1: What is your gender? 'M' and 'Next page >>' - * Page 2: Question2: 'I am a male' and '<< Previous page' + * Page 2: 'Question2: Do you confirm you are a male?' 'I am a male' and '<< Previous page' * 'I am a male' is saved as unverified * Page 1: What is your gender? 'F' and 'Next page >>' - * Page 2: Question3: 'I am a female' and '<< Previous page' + * Page 2: 'Question3: Do you confirm you are a female?' 'I am a female' and '<< Previous page' * 'I am a female' is saved as unverified * Page 1: What is your gender? 'M' and 'Next page >>' - * Page 2: Question2: 'I confirm I am a male' and 'Submit' + * Page 2: 'Question2: Do you confirm you are a male?': 'I confirm I am a male' and 'Submit' * * At submit time I have: - * Question1: 'M' saved as verified - * Question2: 'I am a female' saved as unverified - * Question3: 'I confirm I am a male' saved as verified + * Question1: 'M' is saved as verified + * Question2: 'I am a female' is saved as unverified + * Question3: 'I confirm I am a male' is saved as verified * * Submit and 'I am a female' is saved as verified * Now I have to delete the unverified answer @@ -696,11 +696,8 @@ private function check_all_was_verified() { * @return void */ public function drop_unverified_data() { - global $DB; - - $whereparams = ['submissionid' => $this->formdata->submissionid, 'verified' => 0]; - $where = 'submissionid = :submissionid AND verified = :verified'; - $DB->delete_records_select('surveypro_answer', $where, $whereparams); + $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); + $utilitylayoutman->delete_answers(['submissionid' => $this->formdata->submissionid, 'verified' => 0]); } /** @@ -753,7 +750,7 @@ public function notifypeople() { $recipient->mailformat = 1; foreach ($morerecipients as $moreemail) { // Do not create duplicates. - if (in_array($moreemail, $firstlist)) { + if (isset($firstlist) && in_array($moreemail, $firstlist)) { continue; } $recipient->firstname = $moreemail; @@ -824,7 +821,7 @@ public function add_readonly_browsing_buttons() { $params['s'] = $this->surveypro->id; $params['submissionid'] = $this->get_submissionid(); $params['mode'] = SURVEYPRO_READONLYMODE; - $params['section'] = 'submissionform'; + $params['section'] = 'responsesubmit'; $userformpagecount = $this->get_userformpagecount(); if ($userformpagecount > 1) { @@ -865,103 +862,124 @@ public function add_readonly_browsing_buttons() { } /** - * Drop all the answers returned by disabled items. + * The goal of this method is twofold. + * + * The first objective is to drop all the answers returned by disabled items. * * If a child item is disabled by the parent in its same page, * the child answer (whether set) is undesired and must be deleted. * - * Let's suppose parent and child element in the same page. + * First scenario. + * Let's suppose parent and child element share the same page. * I provide the right parent answer so that the child becomes enabled. * Now I enter some input in the child element. * Then I return to parent element and change its answer. * Child is now disabled BUT equipped with an answer. * This is the answer I want to drop out. * + * Second scenario. + * Let's suppose parent and child element share the same page. + * I provide the right parent answer so that the child becomes enabled. + * I save. + * Tomorrow I return to the same response and I change my mind so that the child item is no longer enabled. + * At save time I have to drop the answers provided in the first submission. + * * @return void */ private function drop_undesired_answers() { - // Begin of: delete all the values returned by disabled items (that were NOT supposed to be returned: MDL-34815). + global $DB; + + // Take in mind that, for mysterious motivations, NOT ALWAYS mform returns ONLY enabled element content. + $submittedformpage = $this->formdata->formpage; + + // I must get the list of ALL the items of this page to check if they were already submitted in the past + // even if they were not submitted now. + $canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $this->context); + + // The current submission. $dirtydata = (array)$this->formdata; - $elementnames = array_keys($dirtydata); + + $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); + + $formpage = $this->formdata->formpage; + + [$where, $params] = surveypro_fetch_items_seeds( + $this->surveypro->id, true, $canaccessreserveditems, null, null, $formpage + ); + $fieldlist = 'id, plugin, type, parentid, parentvalue'; + $itemseeds = $DB->get_records_select('surveypro_item', $where, $params, 'sortindex', $fieldlist); $disposelist = []; $olditemid = 0; - foreach ($elementnames as $elementname) { - if ($matches = utility_item::get_item_parts($elementname)) { - // With the introduction of interactive fieldset... - // those format elements are now equipped with open/close triangle... - // and they submit their own state. - // Drop them out. - $condition = false; - $condition = $condition || ($matches['prefix'] == SURVEYPRO_DONTSAVEMEPREFIX); - $condition = $condition || ($matches['type'] == SURVEYPRO_TYPEFORMAT); - if ($condition) { - continue; // To next foreach. - } - } else { - continue; + foreach ($itemseeds as $itemseed) { + // With the introduction of interactive fieldset... + // those format elements are now equipped with open/close triangle... + // and they submit their own state. + // Drop them out. + if ($itemseed->type == SURVEYPRO_TYPEFORMAT) { + continue; // To next foreach. } - $type = $matches['type']; - $plugin = $matches['plugin']; - $itemid = $matches['itemid']; - if ($itemid == $olditemid) { + if (empty($itemseed->parentid)) { continue; } - // Let's start. - $olditemid = $itemid; - - $childitem = surveypro_get_item($this->cm, $this->surveypro, $itemid, $type, $plugin); - - $parentid = $childitem->get_parentid(); - if (empty($parentid)) { - continue; - } + $itemid = $itemseed->id; + $plugin = $itemseed->plugin; + $type = $itemseed->type; // It is, for sure, SURVEYPRO_TYPEFIELD, // If my parent is already in $disposelist, I have to go to $disposelist FOR SURE. - if (in_array($childitem->get_parentid(), $disposelist)) { - $disposelist[] = $childitem->get_itemid(); + if (in_array($itemseed->parentid, $disposelist)) { + $disposelist[] = $itemseed->id; continue; } - // Call parentitem. - $parentitem = surveypro_get_item($this->cm, $this->surveypro, $childitem->get_parentid()); + // Let's start. + // Get parentitem class. + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); $parentpage = $parentitem->get_formpage(); - $childpage = $childitem->get_formpage(); - if ($parentpage == $childpage) { // If parent and child share the same page. - // Pass to parentitem what the child needs to be displayed ($childitem->get_parentvalue()) + if ($parentpage == $submittedformpage) { // If parent and child are both here in the just submitted page. + // Pass to parentitem what the child needs to be enabled ($itemseed->parentvalue) // and compare it with what was answered to parentitem ($dirtydata). - if (!$parentitem->userform_is_child_allowed_dynamic($childitem->get_parentvalue(), $dirtydata)) { + if (!$parentitem->userform_is_child_allowed_dynamic($itemseed->parentvalue, $dirtydata)) { // Parentitem, knowing itself, compares the anwer it received with child needs and provides an answer. - $disposelist[] = $childitem->get_itemid(); + $disposelist[] = $itemseed->id; + } + } else { + // Parent item is somewhere in the previous pages while the child is here, in the just submitted page. + $submissionid = $this->formdata->submissionid; + if (empty($submissionid)) { // The submission is new. + // No answers from previous submission can be found. Carry on. + continue; + } + + // Is there an already saved answer for the item $itemseed->id in the frame of the submission $submissionid? + $sqlparams = ['submissionid' => $submissionid, 'itemid' => $itemseed->id]; + if (!$DB->record_exists('surveypro_answer', $sqlparams)) { + continue; + } + + // Is your parent item still allowing you? + $parentitem = surveypro_get_itemclass($this->cm, $this->surveypro, $itemseed->parentid); + if (!$parentitem->userform_is_child_allowed_static($submissionid, $itemseed)) { + $utilitylayoutman->delete_answers(['submissionid' => $submissionid, 'itemid' => $itemseed->id]); } } } // Check next item. // End of: delete all the values returned by disabled items (that were NOT supposed to be returned: MDL-34815). // If not expected items are here... + $dirtydata = (array)$this->formdata; + $elementnames = array_keys($dirtydata); + if (count($disposelist)) { $utilitylayoutman = new utility_layout($this->cm, $this->surveypro); foreach ($elementnames as $elementname) { if ($matches = utility_item::get_item_parts($elementname)) { - // With the introduction of interactive fieldset... - // those format elements are now equipped with open/close triangle... - // and they submit their own state. - // Drop them out. - $condition = false; - $condition = $condition || ($matches['prefix'] == SURVEYPRO_DONTSAVEMEPREFIX); - $condition = $condition || ($matches['type'] == SURVEYPRO_TYPEFORMAT); - if ($condition) { - continue; // To next foreach. - } $itemid = $matches['itemid']; if (in_array($itemid, $disposelist)) { unset($this->formdata->$elementname); - // If this datum was previously saved (when the item was not disabled) - // now I have to delete from database. - $utilitylayoutman->delete_answers(['submissionid' => $this->formdata->submissionid, 'itemid' => $itemid]); } } } diff --git a/db/access.php b/db/access.php index 24c7d359770..ca41ba676b9 100644 --- a/db/access.php +++ b/db/access.php @@ -63,6 +63,7 @@ * File: view.php, $section = 'submissionslist' * * mod/surveypro:alwaysseeowner + * mod/surveypro:enjoydeleteallsubmissionsbutton * * mod/surveypro:seeownsubmissions <-- It does not actually exist. It is always allowed. * mod/surveypro:seeotherssubmissions @@ -83,11 +84,11 @@ * mod/surveypro:savetopdfownsubmissions * mod/surveypro:savetopdfotherssubmissions * - * File: view.php, $section = 'submissionform' + * File: view.php, $section = 'responsesubmit' * mod/surveypro:submit * mod/surveypro:ignoremaxentries * - * File: view.php, $section = 'searchsubmissions' + * File: view.php, $section = 'responsesearch' * mod/surveypro:searchsubmissions * * ------------------------------------------- @@ -204,6 +205,17 @@ ], ], + 'mod/surveypro:enjoydeleteallsubmissionsbutton' => [ + 'riskbitmask' => RISK_DATALOSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => [ + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + ], + 'mod/surveypro:seeotherssubmissions' => [ 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', @@ -216,7 +228,7 @@ ], 'mod/surveypro:editownsubmissions' => [ - 'riskbitmask' => RISK_CONFIG | RISK_PERSONAL, + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -227,7 +239,7 @@ ], 'mod/surveypro:editotherssubmissions' => [ - 'riskbitmask' => RISK_CONFIG | RISK_PERSONAL, + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -238,7 +250,7 @@ ], 'mod/surveypro:duplicateownsubmissions' => [ - 'riskbitmask' => RISK_CONFIG | RISK_PERSONAL, + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -249,7 +261,7 @@ ], 'mod/surveypro:duplicateotherssubmissions' => [ - 'riskbitmask' => RISK_CONFIG | RISK_PERSONAL, + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -260,7 +272,7 @@ ], 'mod/surveypro:deleteownsubmissions' => [ - 'riskbitmask' => RISK_CONFIG, + 'riskbitmask' => RISK_DATALOSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -271,7 +283,7 @@ ], 'mod/surveypro:deleteotherssubmissions' => [ - 'riskbitmask' => RISK_CONFIG, + 'riskbitmask' => RISK_DATALOSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -383,7 +395,7 @@ ], 'mod/surveypro:importresponses' => [ - 'riskbitmask' => RISK_CONFIG | RISK_PERSONAL, + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -395,7 +407,7 @@ ], 'mod/surveypro:exportresponses' => [ - + 'riskbitmask' => RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -407,7 +419,7 @@ ], 'mod/surveypro:manageusertemplates' => [ - + 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -417,7 +429,7 @@ ], 'mod/surveypro:deleteusertemplates' => [ - 'riskbitmask' => RISK_CONFIG, + 'riskbitmask' => RISK_DATALOSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -437,7 +449,7 @@ ], 'mod/surveypro:saveusertemplates' => [ - 'riskbitmask' => RISK_PERSONAL, + 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => [ @@ -447,7 +459,7 @@ ], 'mod/surveypro:importusertemplates' => [ - + 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -457,7 +469,7 @@ ], 'mod/surveypro:applyusertemplates' => [ - 'riskbitmask' => RISK_CONFIG, + 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ @@ -477,7 +489,7 @@ ], 'mod/surveypro:applymastertemplates' => [ - 'riskbitmask' => RISK_CONFIG, + 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ diff --git a/db/install.xml b/db/install.xml index 4a5e5687079..d6f28db14aa 100644 --- a/db/install.xml +++ b/db/install.xml @@ -46,6 +46,15 @@ + + + + + + + + + diff --git a/db/upgrade.php b/db/upgrade.php index 340face9d36..1e49b517f18 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -369,5 +369,91 @@ function xmldb_surveypro_upgrade($oldversion) { upgrade_mod_savepoint(true, 2023012600, 'surveypro'); } + if ($oldversion < 2024022700) { + + // Define field contentformat to be added to surveypro_item. + $table = new xmldb_table('surveypro_item'); + $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'plugin'); + + // Conditionally launch add field contentformat. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('content', XMLDB_TYPE_TEXT, null, null, null, null, null, 'plugin'); + + // Conditionally launch add field content. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Surveypro savepoint reached. + upgrade_mod_savepoint(true, 2024022700, 'surveypro'); + } + + if ($oldversion < 2024032700) { + + $table = new xmldb_table('surveypro_item'); + + // 7) Define field extranote to be added to surveypro_item. + $field = new xmldb_field('extranote', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'contentformat'); + + // Conditionally launch add field extranote. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 6) Define field variable to be added to surveypro_item. + $field = new xmldb_field('variable', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'contentformat'); + + // Conditionally launch add field variable. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 5) Define field hideinstructions to be added to surveypro_item. + $field = new xmldb_field('hideinstructions', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field hideinstructions. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 4) Define field customnumber to be added to surveypro_item. + $field = new xmldb_field('customnumber', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'contentformat'); + + // Conditionally launch add field customnumber. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 3) Define field position to be added to surveypro_item. + $field = new xmldb_field('position', XMLDB_TYPE_INTEGER, '4', null, null, null, '0', 'contentformat'); + + // Conditionally launch add field position. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 2) Define field indent to be added to surveypro_item. + $field = new xmldb_field('indent', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field indent. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // 1) Define field required to be added to surveypro_item. + $field = new xmldb_field('required', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'contentformat'); + + // Conditionally launch add field required. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Surveypro savepoint reached. + upgrade_mod_savepoint(true, 2024032700, 'surveypro'); + } + return true; } diff --git a/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php b/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php index e5de1b9b531..53200cee157 100644 --- a/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php +++ b/field/age/backup/moodle2/backup_surveyprofield_age_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'age'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginage = new backup_nested_element('surveyprofield_age', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/age/classes/item.php b/field/age/classes/item.php index e1ca457995a..61524d26e97 100644 --- a/field/age/classes/item.php +++ b/field/age/classes/item.php @@ -39,57 +39,29 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; + // Itembase properties. /** - * @var bool O => optional item; 1 => mandatory item; + * @var string Value of the default setting (invite, custom...) */ - protected $required; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var int Lowerbound for the age in unixtime */ - protected $indent; + protected $lowerbound; /** - * @var string Value of the default setting (invite, custom...) + * @var int Upperbound for the age in unixtime */ - protected $defaultoption; + protected $upperbound; - /** - * @var int Defaultvalue for the age in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Year of the defaultvalue for the age @@ -101,11 +73,6 @@ class item extends itembase { */ protected $defaultvaluemonth; - /** - * @var int Lowerbound for the age in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the age in unixtime */ @@ -116,11 +83,6 @@ class item extends itembase { */ protected $lowerboundmonth; - /** - * @var int Upperbound for the age in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the age in unixtime */ @@ -131,6 +93,11 @@ class item extends itembase { */ protected $upperboundmonth; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -164,7 +131,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -196,35 +165,24 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (itembase::item_save($record))). return parent::item_save($record); } /** - * Item add mandatory plugin fields - * Copy mandatory fields to $record + * Set defaults to fields of items * * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Age [yy/mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'age_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue; $record->lowerbound = -2148552000; $record->upperbound = 1193918400; } @@ -249,12 +207,11 @@ public function item_force_coherence($record) { /** * Convert unix time to an age. * - * @param int $time - * @param bool $applyusersettings + * @param int $unixtime * @return void */ - public function item_split_unix_time($time, $applyusersettings=true) { - $getdate = parent::item_split_unix_time($time, $applyusersettings); + public function item_split_unix_time($unixtime) { + $getdate = parent::item_split_unix_time($unixtime); $getdate['year'] -= SURVEYPROFIELD_AGE_YEAROFFSET; if ($getdate['mon'] == 12) { @@ -289,7 +246,7 @@ public function item_age_to_text($agearray) { } /** - * Convert an age to unix time. + * Convert an age to unixtime. * * @param int $year * @param int $month @@ -297,7 +254,8 @@ public function item_age_to_text($agearray) { */ public function item_age_to_unix_time($year, $month) { $year += SURVEYPROFIELD_AGE_YEAROFFSET; - return (mktime(12, 0, 0, $month, 1, $year)); + + return (gmmktime(12, 0, 0, $month, 1, $year)); } /** @@ -326,7 +284,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -349,15 +307,198 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. * - * @return the content of the static property "canbeparent" + * @return $this->upperboundmonth */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_upperboundmonth() { + return $this->upperboundmonth; } /** @@ -369,14 +510,30 @@ public function get_composite_fields() { return ['defaultvalue', 'lowerbound', 'upperbound']; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', 'defaultvalueyear', 'defaultvaluemonth', + 'lowerboundyear', 'lowerboundmonth', 'upperboundyear', 'upperboundmonth', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_age'] = []; return $fieldlist; } @@ -393,29 +550,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -443,7 +581,6 @@ public static function get_plugin_schema() { public function userform_mform_element($mform, $searchform, $readonly) { $stryears = get_string('years'); $strmonths = get_string('months', 'surveyprofield_age'); - $strnoanswer = get_string('noanswer', 'mod_surveypro'); if ($this->position == SURVEYPRO_POSITIONLEFT) { $elementlabel = $this->get_contentwithnumber(); @@ -451,8 +588,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_age_'.$this->sortindex; - // Begin of: element values. $years = []; $months = []; @@ -476,51 +611,69 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - $elementgroup = []; $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_age_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $attributes['class'] = 'indent-'.$this->indent.' age_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($readonly) { $itemname = 'yearlabel_'.$this->itemid; - $attributes['id'] = $idprefix.'_yearseparator'; - $attributes['class'] = 'inline age_static'; - $elementgroup[] = $mform->createElement('mod_surveypro_label', $itemname, '', $stryears, $attributes); + $attributes['id'] = $baseid.'_yearseparator'; + $elementgroup[] = $mform->createElement('static', $itemname, '', $stryears, $attributes); } - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'age_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); if ($readonly) { $itemname = 'monthlabel_'.$this->itemid; - $attributes['id'] = $idprefix.'_monthseparator'; - $attributes['class'] = 'inline age_static'; - $elementgroup[] = $mform->createElement('mod_surveypro_label', $itemname, '', $strmonths, $attributes); + $attributes['id'] = $baseid.'_monthseparator'; + $elementgroup[] = $mform->createElement('static', $itemname, '', $strmonths, $attributes); } if ($this->required) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - if (!$searchform) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; - $mform->_required[] = $starplace; + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + + if (!$searchform) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; + } + } else { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'age_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $strnoanswer, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $attributes['id'] = $baseid.'_noanswer'; + $strnoanswer = get_string('noanswer', 'mod_surveypro'); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $strnoanswer, $attributes); + $separator[] = ' '; + + if (!$searchform) { + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); + } else { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); + } } // End of: mform element. @@ -532,7 +685,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $agearray['mon'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -553,13 +706,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_year', $agearray['year']); - $mform->setDefault($this->itemname.'_month', $agearray['mon']); + $mform->setDefault($basename.'_year', $agearray['year']); + $mform->setDefault($basename.'_month', $agearray['mon']); } else { - $mform->setDefault($this->itemname.'_year', SURVEYPRO_IGNOREMEVALUE); - $mform->setDefault($this->itemname.'_month', SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename.'_year', SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename.'_month', SURVEYPRO_IGNOREMEVALUE); if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -578,7 +731,7 @@ public function userform_mform_validation($data, &$errors, $searchform) { // Because of this, if ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $maximumage = get_config('surveyprofield_age', 'maximumage'); @@ -606,13 +759,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_agenotset', 'surveyprofield_age', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_age_to_unix_time(0, 0)); @@ -632,6 +785,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_age'); } } + + return $errors; } /** @@ -675,7 +830,6 @@ public function userform_get_filling_instructions() { * Starting from the info set by the user in the form * this method calculates what to save in the db * or what to return for the search form. - * I don't set $olduseranswer->contentformat in order to accept the default db value. * * @param array $answer * @param object $olduseranswer @@ -764,8 +918,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/age/db/install.xml b/field/age/db/install.xml index 7d4b8030bb1..5b0776874a9 100644 --- a/field/age/db/install.xml +++ b/field/age/db/install.xml @@ -1,33 +1,17 @@ -
- - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -36,3 +20,4 @@
+ diff --git a/field/age/db/upgrade.php b/field/age/db/upgrade.php index a18b341dca0..70eeca21be2 100644 --- a/field/age/db/upgrade.php +++ b/field/age/db/upgrade.php @@ -54,5 +54,67 @@ function xmldb_surveyprofield_age_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'age'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_age. + $table = new xmldb_table('surveyprofield_age'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_age} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'age'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_age'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_age. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_age} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'age'); + } + return true; } diff --git a/field/age/lang/en/surveyprofield_age.php b/field/age/lang/en/surveyprofield_age.php index 49dec284fed..6e73cd6fb7d 100644 --- a/field/age/lang/en/surveyprofield_age.php +++ b/field/age/lang/en/surveyprofield_age.php @@ -25,28 +25,28 @@ $string['and'] = 'and'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the age the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; +$string['defaultoption_help'] = 'This is the age the remote user will find answered by default. The default for this type of question is mandatory.'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest age the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; -$string['maximumage_desc'] = 'The maximun age this software will allow to ever enter'; +$string['lowerbound_help'] = 'The lowest age the user is allowed to enter'; $string['maximumage'] = 'Maximum age'; +$string['maximumage_desc'] = 'The maximun age this software will allow to ever enter'; $string['months'] = 'months'; $string['pluginname'] = 'Age'; +$string['privacy:metadata'] = 'The "Age" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; -$string['uerr_agenotset'] = 'Please choose a age or select the "{$a}" checkbox'; +$string['uerr_agenotset'] = 'Please choose an age or select the "{$a}" checkbox'; $string['uerr_agenotsetrequired'] = 'Age is not correctly defined'; $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest age the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest age the user is allowed to enter'; $string['userfriendlypluginname'] = 'Age [yy/mm]'; -$string['privacy:metadata'] = 'The "Age" field plugin does not store any personal data.'; diff --git a/field/age/lang/it/surveyprofield_age.php b/field/age/lang/it/surveyprofield_age.php new file mode 100644 index 00000000000..75861a487c1 --- /dev/null +++ b/field/age/lang/it/surveyprofield_age.php @@ -0,0 +1,43 @@ +. + +/** + * Strings for component 'surveyprofield_age', language 'en' + * + * @package surveyprofield_age + * @subpackage age + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['and'] = 'e'; +$string['customdefault'] = 'Custom'; +$string['defaultoption'] = 'Default'; +$string['invitemonth'] = 'Seleziona un mese'; +$string['inviteyear'] = 'Seleziona un anno'; +$string['lowerbound'] = 'Limite inferiore'; +$string['lowerbound_help'] = 'La più piccola età che l\'utente può inserire'; +$string['maximumage'] = 'Età massima'; +$string['months'] = 'mesi'; +$string['pluginname'] = 'Età'; +$string['privacy:metadata'] = 'La plugin "Age" con contiene alcun dato personale.'; +$string['restriction_lower'] = 'La risposta deve essere maggiore o uguale a {$a}'; +$string['restriction_lowerupper'] = 'La risposta deve essere compresa fra {$a->lowerbound} e {$a->upperbound}'; +$string['restriction_upper'] = 'La risposta deve essere minore o uguale a {$a}'; +$string['uerr_agenotset'] = 'Si selezioni una età o la checkbox "{$a}"'; +$string['upperbound'] = 'Limite inferiore'; +$string['upperbound_help'] = 'La più grande età che l\'utente può inserire'; +$string['userfriendlypluginname'] = 'Age [yy/mm]'; diff --git a/field/age/tests/behat/itemform.feature b/field/age/tests/behat/itemform.feature index 4994987e65b..737fd30ae8b 100644 --- a/field/age/tests/behat/itemform.feature +++ b/field/age/tests/behat/itemform.feature @@ -91,6 +91,6 @@ Feature: Create an age item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a How old were you when you started cycling?" - Then the field "id_surveypro_field_age_2_year" matches value "14" - Then the field "id_surveypro_field_age_2_month" matches value "7" + Then the field "id_field_age_2_year" matches value "14" + Then the field "id_field_age_2_month" matches value "7" Then I should see "Additional note" diff --git a/field/age/tests/behat/submit_age.feature b/field/age/tests/behat/submit_age.feature index 9c94848db36..25a951da06e 100644 --- a/field/age/tests/behat/submit_age.feature +++ b/field/age/tests/behat/submit_age.feature @@ -46,8 +46,8 @@ Feature: Submit using an age item # student1 submits And I set the following fields to these values: - | id_surveypro_field_age_1_year | 23 | - | id_surveypro_field_age_1_month | 8 | + | id_field_age_1_year | 23 | + | id_field_age_1_month | 8 | And I press "Submit" diff --git a/field/age/tests/behat/use_advanced_elements.feature b/field/age/tests/behat/use_advanced_elements.feature index 92948711dd1..4a03f1a1012 100644 --- a/field/age/tests/behat/use_advanced_elements.feature +++ b/field/age/tests/behat/use_advanced_elements.feature @@ -69,8 +69,8 @@ Feature: Use reserved elements # user submit a surveypro And I set the following fields to these values: - | id_surveypro_field_age_1_year | 8 | - | id_surveypro_field_age_1_month | 2 | + | id_field_age_1_year | 8 | + | id_field_age_1_month | 2 | And I press "Submit" And I log out @@ -83,6 +83,6 @@ Feature: Use reserved elements Then I should see "2 Second age item" And I set the following fields to these values: - | id_surveypro_field_age_2_year | 24 | - | id_surveypro_field_age_2_month | 6 | + | id_field_age_2_year | 24 | + | id_field_age_2_month | 6 | And I press "Submit" diff --git a/field/age/tests/fixtures/usertemplate/age_only_2023103100.xml b/field/age/tests/fixtures/usertemplate/age_only_2024032800.xml similarity index 92% rename from field/age/tests/fixtures/usertemplate/age_only_2023103100.xml rename to field/age/tests/fixtures/usertemplate/age_only_2024032800.xml index da8ea737a3d..d7f3a66d88a 100644 --- a/field/age/tests/fixtures/usertemplate/age_only_2023103100.xml +++ b/field/age/tests/fixtures/usertemplate/age_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>AGE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>age specific setting</b>:</p><ol><li>default.</li></ol><p>and with two more <b>validation options</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>AGE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>age specific setting</b>:</p><ol><li>default.</li></ol><p>and with two more <b>validation options</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>an age has been defined as default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>an age has been defined as default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -42,33 +37,33 @@ 1 0 age_001 + 0 + 0 + 0 + + 1 -1186059600 -2148555600 1193914800 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -77,33 +72,33 @@ 2 0 age_002 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -112,33 +107,33 @@ 3 0 age_003 + 0 + 0 + 0 + + 1 -1033563600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -147,33 +142,33 @@ 4 0 age_004 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited only by module level age limit</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -182,33 +177,33 @@ 5 0 age_005 + 0 + 0 + 0 + + 3 -2148555600 -2148555600 1193914800 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>user answer is limited between 20 and 40</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>user answer is limited between 20 and 40</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -217,33 +212,33 @@ 6 0 age_006 + 0 + 0 + 0 + + 1 -1186059600 -1517403600 -886255200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited between 12 years and half and 18</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>user answer is limited between 12 years and half and 18</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 1 @@ -252,33 +247,33 @@ 7 0 age_007 + 0 + 0 + 0 + + 2 -2148555600 -1754139600 -1580562000 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited over 18</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li><li>user answer is limited over 18</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -287,33 +282,33 @@ 8 0 age_008 + 0 + 0 + 0 + + 1 -1033563600 -1580562000 1193914800 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited between 0 and 3 months</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li><li>user answer is limited between 0 and 3 months</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select an age corresponding to his/her answer. Being the item not required, the user can choose as answer: "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -322,33 +317,33 @@ 9 0 age_009 + 0 + 0 + 0 + + 2 -2148555600 -2148555600 -2140779600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited between 18 and 65</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>user answer is limited between 18 and 65</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - How old are you? 1 0 @@ -357,6 +352,11 @@ 10 0 age_010 + 0 + 0 + 0 + + 3 -2148555600 -1580562000 diff --git a/field/age/version.php b/field/age/version.php index c78e1bb9845..06b5cbe21f4 100644 --- a/field/age/version.php +++ b/field/age/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_age'; // Full name of the plugin (used for diagnostics). diff --git a/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php b/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php index fa08c7146ec..d39c3870b76 100644 --- a/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php +++ b/field/autofill/backup/moodle2/backup_surveyprofield_autofill_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'autofill'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginautofill = new backup_nested_element('surveyprofield_autofill', ['id'], [ - 'content', 'contentformat', - 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', ]); + 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/autofill/classes/item.php b/field/autofill/classes/item.php index e7a12729fed..2487eae636e 100644 --- a/field/autofill/classes/item.php +++ b/field/autofill/classes/item.php @@ -39,57 +39,39 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; + // Itembase properties. /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH + * @var bool $hiddenfield = is the static text visible in the mform? */ - protected $position; + protected $hiddenfield; /** - * @var string Optional text with item custom note + * @var string Element #1 for $content */ - protected $extranote; + protected $element01; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Element #2 for $content */ - protected $hideinstructions; + protected $element02; /** - * @var string Name of the field storing data in the db table + * @var string Element #3 for $content */ - protected $variable; + protected $element03; /** - * @var int Indent of the item in the form page + * @var string Element #4 for $content */ - protected $indent; + protected $element04; /** - * @var bool $hiddenfield = is the static text visible in the mform? + * @var string Element #5 for $content */ - protected $hiddenfield; + protected $element05; - /** - * @var string Element #1 for $content - */ - protected $element01; + // Service variables. /** * @var string Select of the element #1 @@ -101,11 +83,6 @@ class item extends itembase { */ protected $element01text; - /** - * @var string Element #2 for $content - */ - protected $element02; - /** * @var string Select of the element #2 */ @@ -116,11 +93,6 @@ class item extends itembase { */ protected $element02text; - /** - * @var string Element #3 for $content - */ - protected $element03; - /** * @var string Select of the element #3 */ @@ -131,11 +103,6 @@ class item extends itembase { */ protected $element03text; - /** - * @var string Element #4 for $content - */ - protected $element04; - /** * @var string Select of the element #4 */ @@ -146,11 +113,6 @@ class item extends itembase { */ protected $element04text; - /** - * @var string Element #5 for $content - */ - protected $element05; - /** * @var string Select of the element #5 */ @@ -161,6 +123,11 @@ class item extends itembase { */ protected $element05text; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -193,7 +160,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['required'] = false; $this->insetupform['hideinstructions'] = false; $this->insetupform['parentid'] = false; @@ -227,14 +196,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -247,14 +212,13 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Autofill'; - $record->contentformat = 1; - $record->position = 0; - $record->variable = 'autofill_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->hiddenfield = 0; $record->element01 = 'userid'; + // $record->element02; + // $record->element03; + // $record->element04; + // $record->element05; } /** @@ -292,7 +256,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -327,29 +291,343 @@ public function item_custom_fields_to_db($record) { * * @return whether the item of this plugin can be mandatory */ - public static function item_uses_mandatory_dbfield() { + public static function has_mandatoryattribute() { return false; } + // MARK set. + + /** + * Set hiddenfield. + * + * @param string $hiddenfield + * @return void + */ + public function set_hiddenfield($hiddenfield) { + $this->hiddenfield = $hiddenfield; + } + + /** + * Set element01. + * + * @param string $element01 + * @return void + */ + public function set_element01($element01) { + $this->element01 = $element01; + } + + /** + * Set element02. + * + * @param string $element02 + * @return void + */ + public function set_element02($element02) { + $this->element02 = $element02; + } + + /** + * Set element03. + * + * @param string $element03 + * @return void + */ + public function set_element03($element03) { + $this->element03 = $element03; + } + + /** + * Set element04. + * + * @param string $element04 + * @return void + */ + public function set_element04($element04) { + $this->element04 = $element04; + } + + /** + * Set element05. + * + * @param string $element05 + * @return void + */ + public function set_element05($element05) { + $this->element05 = $element05; + } + + /** + * Set element01select. + * + * @param string $element01select + * @return void + */ + public function set_element01select($element01select) { + $this->element01select = $element01select; + } + + /** + * Set element01text. + * + * @param string $element01text + * @return void + */ + public function set_element01text($element01text) { + $this->element01text = $element01text; + } + + /** + * Set element02select. + * + * @param string $element02select + * @return void + */ + public function set_element02select($element02select) { + $this->element02select = $element02select; + } + + /** + * Set element02text. + * + * @param string $element02text + * @return void + */ + public function set_element02text($element02text) { + $this->element02text = $element02text; + } + + /** + * Set element03select. + * + * @param string $element03select + * @return void + */ + public function set_element03select($element03select) { + $this->element03select = $element03select; + } + + /** + * Set element03text. + * + * @param string $element03text + * @return void + */ + public function set_element03text($element03text) { + $this->element03text = $element03text; + } + + /** + * Set element04select. + * + * @param string $element04select + * @return void + */ + public function set_element04select($element04select) { + $this->element04select = $element04select; + } + + /** + * Set element04text. + * + * @param string $element04text + * @return void + */ + public function set_element04text($element04text) { + $this->element04text = $element04text; + } + + /** + * Set element05select. + * + * @param string $element05select + * @return void + */ + public function set_element05select($element05select) { + $this->element05select = $element05select; + } + + /** + * Set element05text. + * + * @param string $element05text + * @return void + */ + public function set_element05text($element05text) { + $this->element05text = $element05text; + } + // MARK get. /** - * Is this item available as a parent? + * Get hiddenfield. + * + * @return $this->hiddenfield + */ + public function get_hiddenfield() { + return $this->hiddenfield; + } + + /** + * Get element01. * - * @return the content of the static property "canbeparent" + * @return $this->element01 */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_element01() { + return $this->element01; + } + + /** + * Get element02. + * + * @return $this->element02 + */ + public function get_element02() { + return $this->element02; + } + + /** + * Get element03. + * + * @return $this->element03 + */ + public function get_element03() { + return $this->element03; + } + + /** + * Get element04. + * + * @return $this->element04 + */ + public function get_element04() { + return $this->element04; + } + + /** + * Get element05. + * + * @return $this->element05 + */ + public function get_element05() { + return $this->element05; + } + + /** + * Get element01select. + * + * @return $this->element01select + */ + public function get_element01select() { + return $this->element01select; + } + + /** + * Get element01text. + * + * @return $this->element01text + */ + public function get_element01text() { + return $this->element01text; + } + + /** + * Get element02select. + * + * @return $this->element02select + */ + public function get_element02select() { + return $this->element02select; + } + + /** + * Get element02text. + * + * @return $this->element02text + */ + public function get_element02text() { + return $this->element02text; + } + + /** + * Get element03select. + * + * @return $this->element03select + */ + public function get_element03select() { + return $this->element03select; + } + + /** + * Get element03text. + * + * @return $this->element03text + */ + public function get_element03text() { + return $this->element03text; + } + + /** + * Get element04select. + * + * @return $this->element04select + */ + public function get_element04select() { + return $this->element04select; + } + + /** + * Get element04text. + * + * @return $this->element04text + */ + public function get_element04text() { + return $this->element04text; + } + + /** + * Get element05select. + * + * @return $this->element05select + */ + public function get_element05select() { + return $this->element05select; + } + + /** + * Get element05text. + * + * @return $this->element05text + */ + public function get_element05text() { + return $this->element05text; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'hiddenfield', 'element01', 'element02', 'element03', 'element04', 'element05', + 'element01select', 'element02select', 'element03select', 'element04select', 'element05select', + 'element01text', 'element02text', 'element03text', 'element04text', 'element05text', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_autofill'] = []; return $fieldlist; } @@ -366,27 +644,8 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -438,7 +697,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_autofill_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_autofill_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $basename = $this->itemname; if (!$searchform) { // I can not say: "I can write the content as if the record is new because if the record is not new, @@ -446,52 +709,46 @@ public function userform_mform_element($mform, $searchform, $readonly) { // This is a label! Defults will not be applied. // So, I have to ALWAYS get them now and include them now into the item. - // Is this a new submission or I am editing an old one? + // Is this a new submission? $submissionid = $mform->getElementValue('submissionid'); - if ($submissionid) { // I am editing an old submission. + if ($submissionid) { // I am working on an already saved submission. $wheresql = 'submissionid = :submissionid AND itemid = :itemid'; $whereparams = ['submissionid' => $submissionid, 'itemid' => $this->itemid]; $answer = false; $answer = $DB->get_record('surveypro_answer', $whereparams); if ($answer) { $value = $answer->content; - } else { // This should never be verified. - $message = 'Unexpected lack of answer. '; - $message .= 'The submission id '.$submissionid.' exists '; - $message .= 'but there is not any answer for the item id '.$this->itemid; - debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); - $value = 'NULL'; + } else { + // If the answer does not exist... + // it may be I am saving a new content BUT the autofill item is in the second page of the surveypro. + $value = $this->userform_get_content(0); } } else { // I am editing a new submission. $value = $this->userform_get_content(0); } - $mform->addElement('hidden', $this->itemname, $value); - $mform->setType($this->itemname, PARAM_RAW); - $mform->setDefault($this->itemname, $value); + $mform->addElement('hidden', $basename, $value); + $mform->setType($basename, PARAM_RAW); + $mform->setDefault($basename, $value); if (!$this->hiddenfield) { - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' label_static']; - $mform->addElement('mod_surveypro_label', $this->itemname.'_static', $elementlabel, $value, $attributes); + $attributes = ['id' => $baseid]; + $elementgroup[] = $mform->createElement('static', $basename.'_static', '', $value, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); } } else { - $attributes = []; - $elementgroup = []; - - $itemname = $this->itemname; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' autofill_text'; - $elementgroup[] = $mform->createElement('text', $itemname, '', $attributes); - - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'autofill_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - - $mform->setType($this->itemname, PARAM_RAW); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $basename = $this->itemname; + $attributes['id'] = $baseid; + + $elementgroup[] = $mform->createElement('text', $basename, '', $attributes); + $mform->setType($basename, PARAM_RAW); + + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -505,6 +762,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** @@ -673,8 +931,6 @@ public function userform_get_content($submissionid) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname]; - - return $elementnames; + return []; } } diff --git a/field/autofill/db/install.xml b/field/autofill/db/install.xml index c6ad22960cb..4e354db95a9 100644 --- a/field/autofill/db/install.xml +++ b/field/autofill/db/install.xml @@ -1,35 +1,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/autofill/db/upgrade.php b/field/autofill/db/upgrade.php index 6f7c5a07b9f..77695377c60 100644 --- a/field/autofill/db/upgrade.php +++ b/field/autofill/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyprofield_autofill_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Autofill savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'autofill'); } @@ -63,9 +63,70 @@ function xmldb_surveyprofield_autofill_upgrade($oldversion) { $whereparams = ['parentid' => null, 'parentvalue' => null, 'plugin' => 'autofill']; $DB->execute($sql, $whereparams); - // Surveypro savepoint reached. + // Autofill savepoint reached. upgrade_plugin_savepoint(true, 2024011101, 'surveyprofield', 'autofill'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_autofill. + $table = new xmldb_table('surveyprofield_autofill'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dieing fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_autofill} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Autofill savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'autofill'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_autofill'); + + $fieldnames = ['indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_autofill. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_autofill} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Autofill savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'autofill'); + } + return true; } diff --git a/field/autofill/lang/en/surveyprofield_autofill.php b/field/autofill/lang/en/surveyprofield_autofill.php index e007c76c551..cc7c028fad0 100644 --- a/field/autofill/lang/en/surveyprofield_autofill.php +++ b/field/autofill/lang/en/surveyprofield_autofill.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['contentelement_group_help'] = 'Element building the static text'; $string['contentelement_group'] = 'Content element'; +$string['contentelement_group_help'] = 'Element building the static text'; $string['contentselect_err'] = 'At least one element has to be not null'; $string['courseid'] = 'course ID'; $string['coursename'] = 'course name'; @@ -34,12 +34,13 @@ $string['element03'] = 'Third content element'; $string['element04'] = 'Fourth content element'; $string['element05'] = 'Fifth content element'; -$string['hiddenfield_help'] = 'This option allow you to hide or show this autofill element from the survey form. Selecting this checkbox the element will be added to the form as hidden field so the user will not see it.'; $string['hiddenfield'] = 'Make hidden'; +$string['hiddenfield_help'] = 'This option allow you to hide or show this autofill element from the survey form. Selecting this checkbox the element will be added to the form as hidden field so the user will not see it.'; $string['ierr_contenttext'] = 'The requested text can be null'; $string['label'] = 'static label'; $string['latevalue'] = 'Content will be provided once available'; $string['pluginname'] = 'Autofill'; +$string['privacy:metadata'] = 'The "Autofill" field plugin does not store any personal data.'; $string['submission'] = 'Response'; $string['submissiondate'] = 'response date'; $string['submissiondateandtime'] = 'response date and time'; @@ -54,4 +55,3 @@ $string['usergroupname'] = 'user group name'; $string['userid'] = 'user ID'; $string['userlastname'] = 'user last name'; -$string['privacy:metadata'] = 'The "Autofill" field plugin does not store any personal data.'; diff --git a/field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml b/field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml similarity index 92% rename from field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml rename to field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml index 7c443844ca8..4bb181031b0 100644 --- a/field/autofill/tests/fixtures/usertemplate/autofill_only_2015123000.xml +++ b/field/autofill/tests/fixtures/usertemplate/autofill_only_2024032800.xml @@ -1,74 +1,74 @@ - + + <h5>AUTOFILL</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>autofill specific setting</b>:</p><ol><li>First content element</li><li>Second content element</li><li>Third content element</li><li>Fourth content element</li><li>Fifth content element</li><li>Make hidden</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>AUTOFILL</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>autofill specific setting</b>:</p><ol><li>First content element</li><li>Second content element</li><li>Third content element</li><li>Fourth content element</li><li>Fifth content element</li><li>Make hidden</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is going to be visible in the surveypro page.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is going to be visible in the surveypro page.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Your user ID</p> 1 0 0 autofill_001 + 0 + 0 + 0 + + 0 userid - + + <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is not visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is not going to be visible in the surveypro page. This is the reason why you can not see that element in the surveypro preview page.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>the User ID (probably for future relationship between exported tables)</li><li>field is not visible</li></ul><p>Behaviour: The element is supposed to display the ID of the owner of the record and that ID is not going to be visible in the surveypro page. This is the reason why you can not see that element in the surveypro preview page.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Your user ID</p> 1 0 0 autofill_002 + 0 + 0 + 0 + + 1 userid diff --git a/field/autofill/version.php b/field/autofill/version.php index 1d4482b7ea8..1e0445ccf4b 100644 --- a/field/autofill/version.php +++ b/field/autofill/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_autofill'; // Full name of the plugin (used for diagnostics). diff --git a/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php b/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php index af90253987e..4b320d8aece 100644 --- a/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php +++ b/field/boolean/backup/moodle2/backup_surveyprofield_boolean_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'boolean'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginboolean = new backup_nested_element('surveyprofield_boolean', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'style', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'style', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/boolean/classes/item.php b/field/boolean/classes/item.php index fd423184a0d..5c30b60c000 100644 --- a/field/boolean/classes/item.php +++ b/field/boolean/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string Value of the default setting (invite, custom...) @@ -88,7 +48,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -102,6 +62,13 @@ class item extends itembase { */ protected $style; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -134,7 +101,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -166,14 +135,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (itembase::item_save($record))). return parent::item_save($record); @@ -186,13 +151,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Boolean'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'boolean_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 1; $record->downloadformat = 'strfbool01'; @@ -215,13 +174,13 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. // 2. Override few values. // Hideinstructions is set by design. - $record->hideinstructions = 1; + // Nothing to do: no checkboxes in this plugin item form. // 3. Set values corresponding to checkboxes. // Take care: 'required', 'hideinstructions' were already considered in get_common_settings. @@ -245,15 +204,84 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set style. + * + * @param string $style + * @return void + */ + public function set_style($style) { + $this->style = $style; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get style. * - * @return the content of the static property "canbeparent" + * @return $this->style */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_style() { + return $this->style; } /** @@ -281,14 +309,27 @@ public function get_friendlyformat() { return 'strfbool01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultoption', 'defaultvalue', 'downloadformat', 'style']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_boolean'] = []; return $fieldlist; } @@ -305,29 +346,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -468,14 +490,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_boolean_'.$this->sortindex; - $yeslabel = get_string('yes'); $nolabel = get_string('no'); $noanswerstr = get_string('noanswer', 'mod_surveypro'); $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' boolean_radio'; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_boolean_'.$this->sortindex; + $basename = $this->itemname; if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { // Begin of: element values. @@ -484,8 +507,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $options[SURVEYPRO_INVITEVALUE] = get_string('choosedots'); } - } else { - $options[SURVEYPRO_IGNOREMEVALUE] = ''; } $options['1'] = $yeslabel; $options['0'] = $nolabel; @@ -495,60 +516,49 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - if ($this->required) { - if (!$searchform) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; - } + $attributes['id'] = $baseid; + $elementgroup[] = $mform->createElement('select', $basename, $elementlabel, $options, $attributes); + + if ($searchform) { + $starstr = get_string('star', 'mod_surveypro'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } - $attributes['id'] = $idprefix; - $mform->addElement('select', $this->itemname, $elementlabel, $options, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); // End of: mform element. } else { // SURVEYPROFIELD_BOOLEAN_USERADIOV or SURVEYPROFIELD_BOOLEAN_USERADIOH. $separator = ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOV) ? '
' : ' '; - $elementgroup = []; // Begin of: mform element. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $choosedotsstr = get_string('choosedots'); - $attributes['id'] = $idprefix.'_invite'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; - } + $attributes['id'] = $baseid.'_invite'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); } } else { $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $starstr, SURVEYPRO_IGNOREMEVALUE, $attributes); - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; - } + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $starstr, SURVEYPRO_IGNOREMEVALUE, $attributes); } - $attributes['id'] = $idprefix.'_1'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $yeslabel, '1', $attributes); - - if ($this->style == SURVEYPROFIELD_BOOLEAN_USERADIOH) { - $attributes['class'] = 'boolean_radio'; + $attributes['id'] = $baseid.'_1'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $yeslabel, '1', $attributes); + $attributes['id'] = $baseid.'_0'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $nolabel, '0', $attributes); + if (!$this->required) { + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); } + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); - $attributes['id'] = $idprefix.'_0'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $nolabel, '0', $attributes); - - if (!$this->required) { - $attributes['id'] = $idprefix.'_noanswer'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); + if ($searchform) { + $mform->setDefault($basename.'_group', SURVEYPRO_IGNOREMEVALUE); } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); // End of: mform element. } @@ -559,15 +569,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - if ($this->position == SURVEYPRO_POSITIONTOP) { - $starplace = $this->itemname.'_extrarow'; - } else { - if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { - $starplace = $this->itemname; - } else { // SURVEYPROFIELD_BOOLEAN_USERADIOV or SURVEYPROFIELD_BOOLEAN_USERADIOH. - $starplace = $this->itemname.'_group'; - } - } + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -603,16 +605,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } - $errorkey = ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) ? $this->itemname : $this->itemname.'_group'; + $fieldname = $this->itemname; + $errorkey = $this->itemname.'_group'; // I need to check value is different from SURVEYPRO_INVITEVALUE even if it is not required. - if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { + if ($data[$fieldname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_booleannotset', 'surveyprofield_boolean'); - return; } + + return $errors; } /** @@ -729,12 +733,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - if ($this->style == SURVEYPROFIELD_BOOLEAN_USESELECT) { - $elementnames = [$this->itemname]; - } else { - $elementnames = [$this->itemname.'_group']; - } - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/boolean/db/install.xml b/field/boolean/db/install.xml index bca38258c1c..b997646e51c 100644 --- a/field/boolean/db/install.xml +++ b/field/boolean/db/install.xml @@ -1,33 +1,17 @@ -
- - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/field/boolean/db/upgrade.php b/field/boolean/db/upgrade.php index e77336e1742..5bc5b397da6 100644 --- a/field/boolean/db/upgrade.php +++ b/field/boolean/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_boolean_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Boolean savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'boolean'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_boolean. + $table = new xmldb_table('surveyprofield_boolean'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_boolean} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Boolean savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'boolean'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_boolean'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_boolean. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_boolean} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Boolean savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'boolean'); + } + return true; } diff --git a/field/boolean/lang/en/surveyprofield_boolean.php b/field/boolean/lang/en/surveyprofield_boolean.php index fdb60a64d2d..8db52e977bd 100644 --- a/field/boolean/lang/en/surveyprofield_boolean.php +++ b/field/boolean/lang/en/surveyprofield_boolean.php @@ -23,13 +23,14 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['option'] = 'Option'; $string['parentformat'] = '[0] or [1]'; $string['pluginname'] = 'Boolean'; +$string['privacy:metadata'] = 'The "Boolean" field plugin does not store any personal data.'; $string['strfbool01'] = 'yes/no'; $string['strfbool02'] = 'Yes/No'; $string['strfbool03'] = 'y/n'; @@ -40,11 +41,10 @@ $string['strfbool08'] = 'T/F'; $string['strfbool09'] = '1/0'; $string['strfbool10'] = '+/-'; -$string['style_help'] = 'The style of the field'; $string['style'] = 'Element style'; +$string['style_help'] = 'The style of the field'; $string['uerr_booleannotset'] = 'Please choose a value'; $string['usemenu'] = 'dropdown menu'; $string['useradioh'] = 'horizontal radio buttons'; $string['useradiov'] = 'vertical radio buttons'; $string['userfriendlypluginname'] = 'Boolean'; -$string['privacy:metadata'] = 'The "Boolean" field plugin does not store any personal data.'; diff --git a/field/boolean/tests/behat/itemform.feature b/field/boolean/tests/behat/itemform.feature index e7abe48f499..a8659a209ed 100644 --- a/field/boolean/tests/behat/itemform.feature +++ b/field/boolean/tests/behat/itemform.feature @@ -69,7 +69,7 @@ Feature: Create a boolean item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Is it true?" - Then the field "id_surveypro_field_boolean_2_1" matches value "1" + Then the field "id_field_boolean_2_1" matches value "1" Then I should see "Additional note" And I select "Elements" from the "jump" singleselect @@ -85,5 +85,5 @@ Feature: Create a boolean item And I select "Preview" from the "jump" singleselect Then I should see "II.b Is it true?" - Then the field "id_surveypro_field_boolean_3" matches value "Choose..." + Then the field "id_field_boolean_3" matches value "Choose..." Then I should see "One more additional note" diff --git a/field/boolean/tests/behat/submit_boolean.feature b/field/boolean/tests/behat/submit_boolean.feature index b56646953bc..a3da1623801 100644 --- a/field/boolean/tests/behat/submit_boolean.feature +++ b/field/boolean/tests/behat/submit_boolean.feature @@ -70,8 +70,8 @@ Feature: Submit using a boolean item # student1 submits And I set the following fields to these values: | 4a Is it true? | Yes | - | id_surveypro_field_boolean_2_0 | 1 | - | id_surveypro_field_boolean_3_1 | 1 | + | id_field_boolean_2_0 | 1 | + | id_field_boolean_3_1 | 1 | And I press "Submit" diff --git a/field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml b/field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml similarity index 77% rename from field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml rename to field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml index e24d66eeae5..63a6074ff63 100644 --- a/field/boolean/tests/fixtures/usertemplate/boolean_only_2015123000.xml +++ b/field/boolean/tests/fixtures/usertemplate/boolean_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>BOOLEAN</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>boolean specific setting</b>:</p><ol><li>Element style</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>BOOLEAN</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>boolean specific setting</b>:</p><ol><li>Element style</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -41,33 +36,33 @@ 0 1 boolean_001 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 Intro 0 0 0 - <ul><li>drop down</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -75,33 +70,33 @@ 0 2 boolean_002 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -109,33 +104,33 @@ 0 3 boolean_003 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -143,33 +138,33 @@ 0 4 boolean_004 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>drop down</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -177,32 +172,33 @@ 0 5 boolean_005 + 0 + 0 + 0 + + 3 + 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -210,33 +206,33 @@ 0 6 boolean_006 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 Intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -244,33 +240,33 @@ 0 7 boolean_007 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -278,33 +274,33 @@ 0 8 boolean_008 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -312,33 +308,33 @@ 0 9 boolean_009 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>horizontal radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -346,32 +342,33 @@ 0 10 boolean_010 + 0 + 0 + 0 + + 3 + 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>"yes" is the default (so: "Choose..." is not expected)</li></ul><p>Behaviour: The item is mandatory so the user is theoretically forced to choose a value. In spite of this, the default is set to a valid value so the user will be allowed to "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -379,33 +376,33 @@ 0 11 boolean_011 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 12 Intro 0 0 0 - <ul><li>vertical radio buttons</li><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 12 Intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 1 @@ -413,33 +410,33 @@ 0 12 boolean_012 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Yes" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -447,33 +444,33 @@ 0 13 boolean_013 + 0 + 0 + 0 + + 1 1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> + 1 + 0 + 14 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"Choose..." is the default</li></ul><p>Behaviour: The item is not mandatory but the default is set to an invalid value so the user will be forced to select the item corresponding to his/her answer. Being the item not required, the user can choose as answer the item: "No answer".</p> - 1 - 0 - 14 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -481,33 +478,33 @@ 0 14 boolean_014 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 15 intro 0 0 0 - <ul><li>vertical radio buttons</li><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 15 intro 0 - + - 0 - 0 - 0 - - <p>Is it true?</p> 1 0 @@ -515,7 +512,13 @@ 0 15 boolean_015 + 0 + 0 + 0 + + 3 + 1 strfbool01 diff --git a/field/boolean/version.php b/field/boolean/version.php index 7fd3502e7bb..86f0ed1d491 100644 --- a/field/boolean/version.php +++ b/field/boolean/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_boolean'; // Full name of the plugin (used for diagnostics). diff --git a/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php b/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php index b8ccf94d27b..b07d978b747 100644 --- a/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php +++ b/field/character/backup/moodle2/backup_surveyprofield_character_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'character'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugincharacter = new backup_nested_element('surveyprofield_character', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'trimonsave', - 'defaultvalue', 'pattern', 'minlength', 'maxlength', ]); + 'trimonsave', 'defaultvalue', 'pattern', 'minlength', 'maxlength', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/character/classes/item.php b/field/character/classes/item.php index f6949aa662d..596eefed20f 100644 --- a/field/character/classes/item.php +++ b/field/character/classes/item.php @@ -39,60 +39,15 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the user input will be trimmed at save time + * @var bool True if the user input will be trimmed at save time */ protected $trimonsave; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; - - /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -109,19 +64,26 @@ class item extends itembase { protected $pattern; /** - * @var string Required pattern for the text. Mix of: 'A', 'a', '0' + * @var int Minimum allowed text length */ - protected $patterntext; + protected $minlength; /** - * @var int Minimum allowed length + * @var int Maximum allowed text length */ - protected $minlength; + protected $maxlength; + + // Service variables. /** - * @var int Maximum allowed length + * @var string Required pattern for the text. Mix of: 'A', 'a', '0' */ - protected $maxlength; + protected $patterntext; + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -155,7 +117,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -187,14 +151,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -207,16 +167,12 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Character'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'character_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + $record->trimonsave = 0; + // $record->defaultvalue $record->pattern = SURVEYPROFIELD_CHARACTER_FREEPATTERN; $record->minlength = 0; + // $record->maxlength } /** @@ -248,7 +204,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. if ($record->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN) { $record->pattern = $record->patterntext; @@ -281,56 +237,173 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set trimonsave. + * + * @param string $trimonsave + * @return void + */ + public function set_trimonsave($trimonsave) { + $this->trimonsave = $trimonsave; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set pattern. + * + * @param string $pattern + * @return void + */ + public function set_pattern($pattern) { + $this->pattern = $pattern; + } + + /** + * Set minlength. + * + * @param string $minlength + * @return void + */ + public function set_minlength($minlength) { + $this->minlength = $minlength; + } + + /** + * Set maxlength. + * + * @param string $maxlength + * @return void + */ + public function set_maxlength($maxlength) { + $this->maxlength = $maxlength; + } + + /** + * Set patterntext. + * + * @param string $patterntext + * @return void + */ + public function set_patterntext($patterntext) { + $this->patterntext = $patterntext; + } + // MARK get. /** - * Is this item available as a parent? + * Get trimonsave. + * + * @return $this->trimonsave + */ + public function get_trimonsave() { + return $this->trimonsave; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get pattern. + * + * @return $this->pattern + */ + public function get_pattern() { + return $this->pattern; + } + + /** + * Get minlength. + * + * @return $this->minlength + */ + public function get_minlength() { + return $this->minlength; + } + + /** + * Get maxlength. * - * @return the content of the static property "canbeparent" + * @return $this->maxlength */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_maxlength() { + return $this->maxlength; + } + + /** + * Get patterntext. + * + * @return $this->patterntext + */ + public function get_patterntext() { + return $this->patterntext; } /** * Get the requested property. * * @param string $field - * @return the content of the field + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { - if ($field == 'pattern') { - $condition = ($this->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN); - $condition = $condition || ($this->pattern == SURVEYPROFIELD_CHARACTER_REGEXPATTERN); - if ($condition) { - return $this->patterntext; + if (isset($this->{$field})) { + if ($field == 'pattern') { + $condition = ($this->pattern == SURVEYPROFIELD_CHARACTER_CUSTOMPATTERN); + $condition = $condition || ($this->pattern == SURVEYPROFIELD_CHARACTER_REGEXPATTERN); + if ($condition) { + $return = $this->get_patterntext(); + } else { + $return = $this->get_pattern(); + } } else { - return $this->pattern; + $return = parent::get_generic_property($field); } } else { - return parent::get_generic_property($field); + $return = false; } + + return $return; } /** - * Make the list of multilang plugin fields. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return array of fields + * @return array $data */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'defaultvalue']; + public function get_plugin_presets() { + $pluginproperties = ['trimonsave', 'defaultvalue', 'pattern', 'patterntext', 'minlength', 'maxlength']; + $data = $this->get_base_presets($pluginproperties); - return $fieldlist; + return $data; } /** - * Does the user input need trim? + * Make the list of multilang plugin fields. * - * @return if this plugin requires a user input trim + * @param boolean $includemetafields + * @return array of fields */ - public function get_trimonsave() { - return $this->trimonsave; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_character'] = ['defaultvalue']; + + return $fieldlist; } /** @@ -345,28 +418,9 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - + - - + @@ -422,13 +476,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_character_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_character_'.$this->sortindex; + $basename = $this->itemname; $thresholdsize = 37; $lengthtochar = 1.3; - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' character_text'; + $attributes['id'] = $baseid; if (!empty($this->maxlength)) { $attributes['maxlength'] = $this->maxlength; if ($this->maxlength < $thresholdsize) { @@ -439,33 +495,33 @@ public function userform_mform_element($mform, $searchform, $readonly) { } else { $attributes['size'] = $thresholdsize * $lengthtochar; } + if (!$searchform) { - $mform->addElement('text', $this->itemname, $elementlabel, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - $mform->setDefault($this->itemname, $this->defaultvalue); + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + + $mform->setType($basename, PARAM_RAW); + $mform->setDefault($basename, $this->defaultvalue); if ($this->required) { // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('text', $this->itemname, '', $attributes); + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->setType($basename, PARAM_RAW); - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -479,17 +535,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; + } + + $errorkey = $this->itemname.'_group'; + $fieldname = $this->itemname; + if ($this->trimonsave) { + if (trim($data[$fieldname]) != $data[$fieldname]) { + $warnings[$errorkey] = get_string('uerr_willbetrimmed', 'mod_surveypro'); + } } - $errorkey = $this->itemname; - $userinput = empty($this->trimonsave) ? $data[$this->itemname] : trim($data[$this->itemname]); + $userinput = empty($this->trimonsave) ? $data[$fieldname] : trim($data[$fieldname]); if (empty($userinput)) { if ($this->required) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } $answerlength = \core_text::strlen($userinput); @@ -534,7 +597,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $message = 'Unexpected $this->pattern = '.$this->pattern; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - // Return $errors; is not needed because $errors is passed by reference. + + if ( $errors && isset($warnings) ) { + // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. + $errors += $warnings; + } + + return $errors; } /** @@ -653,8 +722,6 @@ public function userform_get_prefill($fromdb) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname]; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/character/classes/itemsetupform.php b/field/character/classes/itemsetupform.php index da5e8d426f3..0e026f19f99 100644 --- a/field/character/classes/itemsetupform.php +++ b/field/character/classes/itemsetupform.php @@ -61,7 +61,7 @@ public function definition() { $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_character'); $mform->setType($fieldname, PARAM_RAW); - // Item: trimonsave. + // Itembase: trimonsave. $fieldname = 'trimonsave'; $mform->addElement('checkbox', $fieldname, get_string($fieldname, 'surveyprofield_character')); $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_character'); @@ -137,15 +137,16 @@ public function validation($data, $files) { if (!empty($data['defaultvalue'])) { // Maximum characters > length of default. $defaultvaluelength = \core_text::strlen($data['defaultvalue']); - if (!empty($data['maxlength'])) { - if ($defaultvaluelength > $data['maxlength']) { - $errors['defaultvalue'] = get_string('ierr_toolongdefault', 'surveyprofield_character'); + if ($data['pattern'] == SURVEYPROFIELD_CHARACTER_FREEPATTERN) { + if (!empty($data['maxlength'])) { + if ($defaultvaluelength > $data['maxlength']) { + $errors['defaultvalue'] = get_string('ierr_toolongdefault', 'surveyprofield_character'); + } + } + // Minimum characters < length of default. + if ($defaultvaluelength < $data['minlength']) { + $errors['defaultvalue'] = get_string('ierr_tooshortdefault', 'surveyprofield_character'); } - } - - // Minimum characters < length of default. - if ($defaultvaluelength < $data['minlength']) { - $errors['defaultvalue'] = get_string('ierr_tooshortdefault', 'surveyprofield_character'); } // Default has to match the text pattern. diff --git a/field/character/db/install.xml b/field/character/db/install.xml index f8a02e1d0f9..17ffe22c4c7 100644 --- a/field/character/db/install.xml +++ b/field/character/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/character/db/upgrade.php b/field/character/db/upgrade.php index 0d6473a24bc..7da1c228201 100644 --- a/field/character/db/upgrade.php +++ b/field/character/db/upgrade.php @@ -58,6 +58,7 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { // Put any upgrade step following this. if ($oldversion < 2016062401) { + // Define field trimonsave to be added to surveyprofield_character. $table = new xmldb_table('surveyprofield_character'); $field = new xmldb_field('trimonsave', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'required'); @@ -72,7 +73,7 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { } if ($oldversion < 2024020700) { - // Reorder the field if the table. + // Reorder the field in the table. // Define field nexttrimonsave to be added to surveyprofield_character. $table = new xmldb_table('surveyprofield_character'); @@ -104,5 +105,66 @@ function xmldb_surveyprofield_character_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024020700, 'surveyprofield', 'character'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_character. + $table = new xmldb_table('surveyprofield_character'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_character} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Character savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'character'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_character'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_character. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_character} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Character savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'character'); + } + return true; } diff --git a/field/character/lang/en/surveyprofield_character.php b/field/character/lang/en/surveyprofield_character.php index 3d7cae7f713..a736de9e0b4 100644 --- a/field/character/lang/en/surveyprofield_character.php +++ b/field/character/lang/en/surveyprofield_character.php @@ -23,11 +23,11 @@ */ $string['custompattern'] = 'custom pattern'; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['defaultvalue'] = 'Default'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['free'] = 'free pattern'; $string['ierr_defaultbadlength'] = 'Default is not {$a} character long as implicitly declared in the pattern'; -$string['ierr_defaultisnotemail'] = 'Default does not math email pattern'; +$string['ierr_defaultisnotemail'] = 'Default does not match email pattern'; $string['ierr_defaultisnoturl'] = 'Default does not appear a valid URL'; $string['ierr_extracharfound'] = '{$a} characters are not allowed. Please, use only "A", "a", "*" and "0"'; $string['ierr_minexceeds'] = 'Minimum length has to be positive'; @@ -37,15 +37,15 @@ $string['ierr_patternisempty'] = 'pattern is missing'; $string['ierr_toolongdefault'] = 'Default has to be shorter-equal than maximum allowed length'; $string['ierr_tooshortdefault'] = 'Default has to be longer-equal than minimum allowed length'; -$string['length_help'] = 'The width of the field in characters'; $string['length'] = 'Field width in characters'; +$string['length_help'] = 'The width of the field in characters'; $string['mail'] = 'email address'; -$string['maxlength_help'] = 'The maximum number of characters allowed for the answer to this question'; $string['maxlength'] = 'Maximum length (in characters)'; -$string['minlength_help'] = 'The minimum number of characters allowed for the answer to this question'; +$string['maxlength_help'] = 'The maximum number of characters allowed for the answer to this question'; $string['minlength'] = 'Minimum length (in characters)'; -$string['pattern_help'] = 'If the answer is supposed to fit a specific pattern, define it here using
  • "A" for upper case characters;
  • "a" for lower case characters;
  • "0" for numbers;
  • "*" for to include upper case, lower case, numbers or any other character like, for instance: ,_%."$!\' or spaces.
'; +$string['minlength_help'] = 'The minimum number of characters allowed for the answer to this question'; $string['pattern'] = 'Text pattern'; +$string['pattern_help'] = 'If the answer is supposed to fit a specific pattern, define it here using
  • "A" for upper case characters;
  • "a" for lower case characters;
  • "0" for numbers;
  • "*" for to include upper case, lower case, numbers or any other character like, for instance: ,_%."$!\' or spaces.
'; $string['pluginname'] = 'Short text'; $string['privacy:metadata'] = 'The "Character" field plugin does not store any personal data.'; $string['regex'] = 'regular expression'; @@ -57,8 +57,8 @@ $string['restrictions_minmax'] = 'Text length is supposed to range between {$a->minlength} and {$a->maxlength} characters'; $string['restrictions_regex'] = 'Text is supposed to match the following regular expression: "{$a}"'; $string['restrictions_url'] = 'URL is expected here'; -$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['trimonsave'] = 'Clean answer at save time'; +$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['uerr_invalidemail'] = 'Text is not a valid email'; $string['uerr_invalidregex'] = 'Regular expression \'{$a}\' is not valid.'; $string['uerr_invalidurl'] = 'Text is not a valid URL'; diff --git a/field/character/lang/es_mx/surveyprofield_character.php b/field/character/lang/es_mx/surveyprofield_character.php index bebe9a1de99..8d96037c2d6 100644 --- a/field/character/lang/es_mx/surveyprofield_character.php +++ b/field/character/lang/es_mx/surveyprofield_character.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); $string['custompattern'] = 'personalizado'; -$string['defaultvalue_help'] = 'Este es el valor que el usuario remoto encontrará contestado por defecto'; $string['defaultvalue'] = 'Valor por defecto'; +$string['defaultvalue_help'] = 'Este es el valor que el usuario remoto encontrará contestado por defecto'; $string['free'] = 'patrón libre'; $string['ierr_defaultbadlength'] = 'El valor por defecto no es de {$a} caracteres de longitud porque está declarado implícitamente en el patrón'; $string['ierr_defaultisnotemail'] = 'El valor por defecto no coincide con el patrón del Email'; @@ -39,15 +39,15 @@ $string['ierr_patternisempty'] = 'falta el patrón'; $string['ierr_toolongdefault'] = 'El valor por defecto debe de ser menor o igual a la longitud máxima permitida'; $string['ierr_tooshortdefault'] = 'El valor por defecto debe de ser más largo o igual a la longitud mínima permitida'; -$string['length_help'] = 'El ancho del campo en caracteres'; $string['length'] = 'Ancho del campo en caracteres'; +$string['length_help'] = 'El ancho del campo en caracteres'; $string['mail'] = 'dirección Email'; -$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación a esta pregunta'; $string['maxlength'] = 'Longitud máxima (en caracteres)'; -$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; +$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación a esta pregunta'; $string['minlength'] = 'Longitud mínima (en caracteres)'; -$string['pattern_help'] = 'Si se supone que la contestación ajuste a un patrón específico, defínala aquí usando
  • "A" para caracteres en MAYÚSCULAS;
  • "a" para caracteres en minúsculas;
  • "0" para números;
  • "*" para incluir MAYÚSCULAS, minúsculas, números y algun otro caracter como por ejemplo: ,_%."$!\' o espacios.
'; +$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; $string['pattern'] = 'Patrón de texto'; +$string['pattern_help'] = 'Si se supone que la contestación ajuste a un patrón específico, defínala aquí usando
  • "A" para caracteres en MAYÚSCULAS;
  • "a" para caracteres en minúsculas;
  • "0" para números;
  • "*" para incluir MAYÚSCULAS, minúsculas, números y algun otro caracter como por ejemplo: ,_%."$!\' o espacios.
'; $string['pluginname'] = 'Texto corto'; $string['restrictions_custom'] = 'El texto se supone que coincide con el siguiente patrón: "{$a}"'; $string['restrictions_email'] = 'Aquí se espera un Email'; @@ -56,8 +56,8 @@ $string['restrictions_min'] = 'La respuesta se supone que es más larga o igual a {$a} caracteres'; $string['restrictions_minmax'] = 'El rango de la longitud del texto se supone que esté entre {$a->minlength} y {$a->maxlength} caracteres'; $string['restrictions_url'] = 'Aquí se espera una URL'; -$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['trimonsave'] = 'Contestación limpia al momento de guardar'; +$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['uerr_invalidemail'] = 'El texto no es un Email válido'; $string['uerr_invalidurl'] = 'El texto no es una URL válida'; $string['uerr_nopatternmatch'] = 'El texto no coincide con el patrón requerido'; diff --git a/field/character/tests/behat/itemform.feature b/field/character/tests/behat/itemform.feature index f4e9ef9452d..d469efafcca 100644 --- a/field/character/tests/behat/itemform.feature +++ b/field/character/tests/behat/itemform.feature @@ -80,5 +80,5 @@ Feature: Create a character item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a This is a free text" - Then the field "id_surveypro_field_character_2" matches value "simple, but longer, default" + Then the field "id_field_character_2" matches value "simple, but longer, default" Then I should see "Additional note" diff --git a/field/character/tests/behat/trim.feature b/field/character/tests/behat/trim.feature index 4ec4c8088a5..d6cee7482b9 100644 --- a/field/character/tests/behat/trim.feature +++ b/field/character/tests/behat/trim.feature @@ -30,8 +30,8 @@ Feature: Test the use of character trim And I set the following fields to these values: | Content | This is a standard text | | Required | 1 | - | Additional note | This will not be trimmed | | Clean answer at save time | 0 | + | Additional note | This will not be trimmed | | pattern | free pattern | | Minimum length (in characters) | 20 | | Maximum length (in characters) | 30 | @@ -45,8 +45,8 @@ Feature: Test the use of character trim And I set the following fields to these values: | Content | Text to trim | | Required | 1 | - | Additional note | This will be trimmed | | Clean answer at save time | 1 | + | Additional note | This will be trimmed | | pattern | free pattern | | Minimum length (in characters) | 20 | | Maximum length (in characters) | 30 | @@ -60,6 +60,7 @@ Feature: Test the use of character trim And I press "New response" And I set the field "This is a standard text" to " false long text " And I set the field "Text to trim" to " false long text " + And I press "Submit" Then I should see "Text is too short" @@ -74,5 +75,5 @@ Feature: Test the use of character trim And I press "Continue to responses list" And I follow "view_submission_row_1" - Then the field "id_surveypro_field_character_1" matches value " false long text " - Then the field "id_surveypro_field_character_2" matches value "text correctly trimmed" + Then the field "id_field_character_1" matches value " false long text " + Then the field "id_field_character_2" matches value "text correctly trimmed" diff --git a/field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml b/field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml similarity index 87% rename from field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml rename to field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml index 461fa42a441..c2154218660 100644 --- a/field/character/tests/fixtures/usertemplate/textshort_only_2015123000.xml +++ b/field/character/tests/fixtures/usertemplate/text_(short)_only_2024032800.xml @@ -1,287 +1,279 @@ - + + <h5>SHORT TEXT<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>short text specifi</b><b>c setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Text pattern<br /></li><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SHORT TEXT<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>short text specifi</b><b>c setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Text pattern<br /></li><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Name</p> 1 0 0 0 - 1 - 0 + 1 character_001 + 0 + 0 + 0 + + 1 PATTERN_FREE 0 - + + <ul><li>not mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to match the pattern.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to match the pattern.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number</p> 1 0 0 0 - 2 - 0 + 1 character_002 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + + <ul><li>not mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be an email address.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be an email address.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Enter your email address</p> 1 0 0 0 - 3 - 0 + 1 character_003 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + + <ul><li>not mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be a web page URL.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user can "fly" over this element leaving the proposed default untouched (and the question not read). If an input is provided, it will be required to be a web page URL.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site</p> 1 0 0 0 - 4 - 0 + 1 character_004 + 0 + 0 + 0 + + 1 PATTERN_URL 0 - + + <ul><li>mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text.</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory<br /></li><li>free pattern</li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text.</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Name</p> 1 1 0 0 - 5 - 0 + 1 character_005 + 0 + 0 + 0 + + 1 PATTERN_FREE 0 - + + <ul><li>mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text matching the defined pattern.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory<br /></li><li>custom pattern set to 16 digits (Minimum and maximum length are automatically set to 16)<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a text matching the defined pattern.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number</p> 1 1 0 0 - 6 - 0 + 1 character_006 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + + <ul><li>mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a an email address.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory<br /></li><li>pattern set to email address<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a an email address.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Enter your email address</p> 1 1 0 0 - 7 - 0 + 1 character_007 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + + <ul><li>mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a web page URL.</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory<br /></li><li>pattern set to web page URL<br /></li><li>default not set<br /></li></ul><p>Behaviour: The item is mandatory and the default is not set so the user will be forced to enter a web page URL.</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site</p> 1 1 0 0 - 8 - 0 + 1 character_008 + 0 + 0 + 0 + + 1 PATTERN_URL 0 diff --git a/field/character/version.php b/field/character/version.php index 0fd725e4662..10408e78b17 100644 --- a/field/character/version.php +++ b/field/character/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024020700; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_character'; // Full name of the plugin (used for diagnostics). diff --git a/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php b/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php index 28c3c57c104..7acc78543e2 100644 --- a/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php +++ b/field/checkbox/backup/moodle2/backup_surveyprofield_checkbox_subplugin.class.php @@ -40,10 +40,9 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'checkbox'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugincheckbox = new backup_nested_element('surveyprofield_checkbox', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'options', 'labelother', 'defaultvalue', 'noanswerdefault', 'downloadformat', - 'minimumrequired', 'maximumrequired', 'adjustment', ]); + 'minimumrequired', 'maximumrequired', 'adjustment', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/checkbox/classes/item.php b/field/checkbox/classes/item.php index e167cbbe6e9..d3814a2f633 100644 --- a/field/checkbox/classes/item.php +++ b/field/checkbox/classes/item.php @@ -41,68 +41,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - * - * Take in mind that "required" (for checkbox item) means only: "The 'No answer' checkbox is not displayed". - * Each checkbox element is intrinsically required. - * There is noy for a student to jump a standard checkbox element. - * - * Example: "What do you take for breakfast?" milk, bread, jam. - * If the user jumps this element HE/SHE IS STATING THAT HE/SHE DOES NOT TAKE milk AND NOT bread AND NOT jam. - * - * If the editing teacher choose to allow the student to jump this question, he HAS TO leave unchecked the "required" propery. - * In that way the element will be equipped with an additional exclusive "No answer" checkbox. - * This last checkbox privides to the student the possibility to say "I don't tell you what I take for breakfast!" - * - * Note that a checkbox can have $minimumrequired irrespectively of being required or no. - * Alias: a checkbox element can be not $required and have, at the same time, $minimumrequired > 0. - * This is perfectly valid. - * - * Example: "What do you take for breakfast?" milk, bread, jam. - * With: $required = 0 and $minimumrequired = 2 - * - * This means that the student is allowed to select the exclusive "No answer" checkbox and run away BUT - * IF he/she decides to provide an answer THEN he/she has to select at least 2 checkboxes. - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -115,7 +54,7 @@ class item extends itembase { protected $labelother; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -144,6 +83,13 @@ class item extends itembase { */ protected $adjustment; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -176,7 +122,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -208,18 +156,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim trailing spaces from each textarea field. $fieldlist = ['options', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -232,16 +176,12 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Checkbox'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'checkbox_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; $record->noanswerdefault = 0; + // $record->labelother + // $record->defaultvalue + // $record->noanswerdefault $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->minimumrequired = 0; $record->adjustment = 0; @@ -253,7 +193,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -289,7 +229,7 @@ public function item_list_constraints() { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $constraints = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_checkbox'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -303,15 +243,160 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set noanswerdefault. + * + * @param string $noanswerdefault + * @return void + */ + public function set_noanswerdefault($noanswerdefault) { + $this->noanswerdefault = $noanswerdefault; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set minimumrequired. + * + * @param string $minimumrequired + * @return void + */ + public function set_minimumrequired($minimumrequired) { + $this->minimumrequired = $minimumrequired; + } + + /** + * Set maximumrequired. + * + * @param string $maximumrequired + * @return void + */ + public function set_maximumrequired($maximumrequired) { + $this->maximumrequired = $maximumrequired; + } + + /** + * Set adjustment. + * + * @param string $adjustment + * @return void + */ + public function set_adjustment($adjustment) { + $this->adjustment = $adjustment; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. + * + * @return $this->labelother + */ + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get noanswerdefault. + * + * @return $this->noanswerdefault + */ + public function get_noanswerdefault() { + return $this->noanswerdefault; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get minimumrequired. + * + * @return $this->minimumrequired + */ + public function get_minimumrequired() { + return $this->minimumrequired; + } + + /** + * Get maximumrequired. + * + * @return $this->maximumrequired + */ + public function get_maximumrequired() { + return $this->maximumrequired; + } + + /** + * Get adjustment. * - * @return the content of the static property "canbeparent" + * @return $this->adjustment */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_adjustment() { + return $this->adjustment; } /** @@ -329,6 +414,24 @@ public function get_downloadformats() { return $options; } + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } + /** * Get the format recognized (without any really good reason) as friendly. * @@ -338,14 +441,30 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'options', 'labelother', 'defaultvalue', 'noanswerdefault', + 'downloadformat', 'minimumrequired', 'maximumrequired', 'adjustment', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_checkbox'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -371,33 +490,14 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + - + @@ -418,7 +518,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = array_fill(0, count($values), 0); $labels = []; @@ -456,7 +556,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { * return string $childparentcontent */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -505,7 +605,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $expectedcount = count($values); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -541,27 +641,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_checkbox_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_checkbox_'.$this->sortindex; + $basename = $this->itemname; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $utilityitemman = new utility_item($this->cm, $this->surveypro); $defaults = $utilityitemman->multilinetext_to_array($this->defaultvalue); - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' checkbox_check'; $attributes['group'] = 1; $options = ['0', '1']; - $elementgroup = []; $i = 0; foreach ($labels as $label) { - $itemname = $this->itemname.'_'.$i; - $attributes['id'] = $idprefix.'_'.$i; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $itemname, '', $label, $attributes, $options); - - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'checkbox_check'; - } + $itemname = $basename.'_'.$i; + $attributes['id'] = $baseid.'_'.$i; + $elementgroup[] = $mform->createElement('advcheckbox', $itemname, '', $label, $attributes, $options); if (!$searchform) { if (in_array($label, $defaults)) { @@ -573,34 +670,30 @@ public function userform_mform_element($mform, $searchform, $readonly) { if (!empty($this->labelother)) { [$othervalue, $otherlabel] = $this->get_other(); - $itemname = $this->itemname.'_other'; - $attributes['id'] = $idprefix.'_other'; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $itemname, '', $otherlabel, $attributes, $options); + $attributes['id'] = $baseid.'_other'; + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_other', '', $otherlabel, $attributes, $options); unset($attributes['group']); - $attributes['id'] = $idprefix.'_text'; - $attributes['class'] = 'checkbox_check'; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); + $attributes['id'] = $baseid.'_text'; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); if (!$searchform) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); if (in_array($otherlabel, $defaults)) { - $mform->setDefault($this->itemname.'_other', '1'); + $mform->setDefault($basename.'_other', '1'); } } - $mform->disabledIf($this->itemname.'_text', $this->itemname.'_other', 'notchecked'); + $mform->disabledIf($basename.'_text', $basename.'_other', 'notchecked'); } if (!$this->required) { - $elementtype = 'mod_surveypro_advcheckbox'; - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'surveypro'); $options = ['0', '1']; - $elementgroup[] = $mform->createElement($elementtype, $itemname, '', $noanswerstr, $attributes, $options); + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_noanswer', '', $noanswerstr, $attributes, $options); if (!empty($this->noanswerdefault)) { - $mform->setDefault($itemname, '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } @@ -609,20 +702,23 @@ public function userform_mform_element($mform, $searchform, $readonly) { } else { // SURVEYPRO_HORIZONTAL. $separator = ' '; } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); if (!$this->required) { - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } if ($searchform) { - $itemname = $this->itemname.'_ignoreme'; $this->item_add_color_unifier($mform); - $attributes['id'] = $idprefix.'_ignoreme'; - $mform->addElement('mod_surveypro_checkbox', $itemname, '', get_string('star', 'mod_surveypro'), $attributes); + + $elementgroup = []; + $itemname = $basename.'_ignoreme'; + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $itemname, '', get_string('star', 'mod_surveypro'), $attributes); + $mform->addGroup($elementgroup, $itemname.'_group', '', '', false, $class); $mform->setDefault($itemname, '1'); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); + $mform->disabledIf($basename.'_group', $itemname, 'checked'); } if (!$searchform) { @@ -631,7 +727,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } @@ -648,7 +744,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { * @return array $separator */ public function userform_get_separator(): array { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $optioncount = count($labels); $addother = !empty($this->labelother); $mandatory = $this->required; @@ -664,16 +760,15 @@ public function userform_get_separator(): array { if ($addother) { $separator[] = '
'; // From "Option N" to "Other". $separator[] = ' '; // From "Other" to the corresponding "text field". - if (!$mandatory) { - $separator[] = '
'; // From the "text field" to "No answer". - } - } else { - if (!$mandatory) { - $separator[] = '
'; // From Option N to "No answer". - } } - array_shift($separator); // Bloody workaround: drop first break. + if (!$mandatory) { + $separator[] = '
'; // From "Option N" or "text field" to "No answer". + } + + if (count($separator) > 1) { + array_shift($separator); // Bloody workaround: drop first break. + } return $separator; } @@ -688,10 +783,10 @@ public function userform_get_separator(): array { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (isset($data[$this->itemname.'_noanswer']) && ($data[$this->itemname.'_noanswer'] == 1) ) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -699,12 +794,12 @@ public function userform_mform_validation($data, &$errors, $searchform) { if (!empty($this->labelother)) { if (($data[$this->itemname.'_other']) && empty($data[$this->itemname.'_text']) ) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_checkbox'); - return; + return $errors; } } // Begin of: get answercount. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $answercount = 0; foreach ($labels as $k => $unused) { @@ -736,6 +831,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum_more', 'surveyprofield_checkbox', $this->maximumrequired); } } + + return $errors; } /** @@ -1013,7 +1110,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); foreach ($values as $k => $value) { if ($answers[$k] == 1) { @@ -1036,7 +1133,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($values as $k => $value) { if ($answers[$k] == 1) { @@ -1075,8 +1172,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/checkbox/db/install.xml b/field/checkbox/db/install.xml index e0027681b44..ae940f24199 100644 --- a/field/checkbox/db/install.xml +++ b/field/checkbox/db/install.xml @@ -1,37 +1,21 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/field/checkbox/db/upgrade.php b/field/checkbox/db/upgrade.php index 4f47fa13428..5da0eda1a91 100644 --- a/field/checkbox/db/upgrade.php +++ b/field/checkbox/db/upgrade.php @@ -144,5 +144,66 @@ function xmldb_surveyprofield_checkbox_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2023111401, 'surveyprofield', 'checkbox'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_checkbox. + $table = new xmldb_table('surveyprofield_checkbox'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_checkbox} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Checkbox savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'checkbox'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_checkbox'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_checkbox. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_checkbox} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Checkbox savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'checkbox'); + } + return true; } diff --git a/field/checkbox/lang/en/surveyprofield_checkbox.php b/field/checkbox/lang/en/surveyprofield_checkbox.php index 840ad4f58d4..bd3af947ae8 100644 --- a/field/checkbox/lang/en/surveyprofield_checkbox.php +++ b/field/checkbox/lang/en/surveyprofield_checkbox.php @@ -23,13 +23,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['adjustment'] = 'Adjustment'; +$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['allowed'] = 'allowed'; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default.'; $string['defaultvalue'] = 'Default'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['horizontal'] = 'horizontal'; $string['ierr_defaultsduplicated'] = 'Defaults must be different each other'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; @@ -39,19 +39,20 @@ $string['ierr_minimumrequired'] = 'The minimum number of checkboxes to select must be lower than {$a}'; $string['ierr_optionswithseparator'] = 'Options can not contain "{$a}"'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; -$string['maximumrequired_help'] = 'The maximum number of checkboxes the user can choose in his/her answer'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['maximumrequired'] = 'Maximum allowed options'; -$string['minimumrequired_help'] = 'The minimum number of checkboxes the user is forced to choose in his/her answer'; +$string['maximumrequired_help'] = 'The maximum number of checkboxes the user can choose in his/her answer'; $string['minimumrequired'] = 'Minimum required options'; -$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; +$string['minimumrequired_help'] = 'The minimum number of checkboxes the user is forced to choose in his/her answer'; $string['noanswerdefault'] = '"No answer" as defaults'; +$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding checkbox, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding checkbox, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[One
label
per
line]'; $string['pluginname'] = 'Checkbox'; +$string['privacy:metadata'] = 'The "Checkbox" field plugin does not store any personal data.'; $string['restrictions_maximumrequired_more'] = 'No more than {$a} checkboxes are allowed'; $string['restrictions_maximumrequired_one'] = 'No more than 1 checkbox is allowed'; $string['restrictions_minimumrequired_more'] = 'At least {$a} checkboxes have to be selected'; @@ -66,4 +67,3 @@ $string['uerr_missingothertext'] = 'Please add the text required by your selection'; $string['userfriendlypluginname'] = 'Checkbox'; $string['vertical'] = 'vertical'; -$string['privacy:metadata'] = 'The "Checkbox" field plugin does not store any personal data.'; diff --git a/field/checkbox/mform/advcheckbox.php b/field/checkbox/mform/advcheckbox.php deleted file mode 100644 index bc45fd78af6..00000000000 --- a/field/checkbox/mform/advcheckbox.php +++ /dev/null @@ -1,77 +0,0 @@ -. - -/** - * advcheckbox mform element - * - * Extends the core mform class for advcheckbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/advcheckbox.php'); - -// @codingStandardsIgnoreFile - -/** - * advcheckbox mform element - * - * Extends the core mform class for advcheckbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_advcheckbox extends \MoodleQuickForm_advcheckbox { - - /** - * Class constructor. - * - * @param string $elementName Optional name of the checkbox - * @param string $elementLabel Optional checkbox label - * @param string $text Optional text to put after the checkbox - * @param mixed $attributes optional either a typical HTML attribute string - * or an associative array - * @param mixed $options Optional values to pass if checked or not checked - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $text, $attributes, $options); - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/checkbox/mform/checkbox.php b/field/checkbox/mform/checkbox.php deleted file mode 100644 index 30486698c56..00000000000 --- a/field/checkbox/mform/checkbox.php +++ /dev/null @@ -1,76 +0,0 @@ -. - -/** - * checkbox mform element - * - * Extends the core mform class for checkbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/checkbox.php'); - -// @codingStandardsIgnoreFile - -/** - * checkbox mform element - * - * Extends the core mform class for checkbox element - * - * @package surveyprofield_checkbox - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_checkbox extends \MoodleQuickForm_checkbox { - - /** - * Constructor. - * - * @param string $elementName Optional name of the checkbox - * @param string $elementLabel Optional checkbox label - * @param string $text Optional text to put after the checkbox - * @param mixed $attributes Optional either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $text, $attributes); - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/checkbox/tests/behat/itemform.feature b/field/checkbox/tests/behat/itemform.feature index 63f783f9204..1ea3bd4fc8b 100644 --- a/field/checkbox/tests/behat/itemform.feature +++ b/field/checkbox/tests/behat/itemform.feature @@ -91,10 +91,10 @@ Feature: Create a checkbox item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a What do you usually get for breakfast?" - Then the field "id_surveypro_field_checkbox_2_0" matches value "0" - Then the field "id_surveypro_field_checkbox_2_1" matches value "1" - Then the field "id_surveypro_field_checkbox_2_2" matches value "0" - Then the field "id_surveypro_field_checkbox_2_3" matches value "1" - Then the field "id_surveypro_field_checkbox_2_other" matches value "1" - Then the field "id_surveypro_field_checkbox_2_text" matches value "specify" + Then the field "id_field_checkbox_2_0" matches value "0" + Then the field "id_field_checkbox_2_1" matches value "1" + Then the field "id_field_checkbox_2_2" matches value "0" + Then the field "id_field_checkbox_2_3" matches value "1" + Then the field "id_field_checkbox_2_other" matches value "1" + Then the field "id_field_checkbox_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/checkbox/tests/behat/settings_configuration_01.feature b/field/checkbox/tests/behat/settings_configuration_01.feature index 7905defa236..01c991da982 100644 --- a/field/checkbox/tests/behat/settings_configuration_01.feature +++ b/field/checkbox/tests/behat/settings_configuration_01.feature @@ -57,8 +57,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -67,8 +67,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions @@ -99,10 +99,10 @@ Feature: Submit using checkbox item and check form validation (1 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -112,8 +112,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -123,8 +123,8 @@ Feature: Submit using checkbox item and check form validation (1 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_02.feature b/field/checkbox/tests/behat/settings_configuration_02.feature index 7077103792c..f24263dc65a 100644 --- a/field/checkbox/tests/behat/settings_configuration_02.feature +++ b/field/checkbox/tests/behat/settings_configuration_02.feature @@ -57,8 +57,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -67,8 +67,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_noanswer | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_noanswer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions @@ -99,7 +99,7 @@ Feature: Submit using checkbox item and check form validation (2 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -109,8 +109,8 @@ Feature: Submit using checkbox item and check form validation (2 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -119,7 +119,7 @@ Feature: Submit using checkbox item and check form validation (2 of 4) # Test number 6: Student chooses "No answer" And I press "New response" Then I should see "At least 2 checkboxes have to be selected" - And I set the field "id_surveypro_field_checkbox_1_noanswer" to "1" + And I set the field "id_field_checkbox_1_noanswer" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_03.feature b/field/checkbox/tests/behat/settings_configuration_03.feature index 029e00191af..a39e6a45954 100644 --- a/field/checkbox/tests/behat/settings_configuration_03.feature +++ b/field/checkbox/tests/behat/settings_configuration_03.feature @@ -58,8 +58,8 @@ Feature: Submit using checkbox item and check form validation (3 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -91,10 +91,10 @@ Feature: Submit using checkbox item and check form validation (3 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_1" to "1" + And I set the field "id_field_checkbox_1_1" to "1" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_2" to "1" + And I set the field "id_field_checkbox_1_2" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -104,8 +104,8 @@ Feature: Submit using checkbox item and check form validation (3 of 4) And I press "New response" Then I should see "At least 2 checkboxes have to be selected" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_04.feature b/field/checkbox/tests/behat/settings_configuration_04.feature index 5c51c9d35d2..fdc719f7401 100644 --- a/field/checkbox/tests/behat/settings_configuration_04.feature +++ b/field/checkbox/tests/behat/settings_configuration_04.feature @@ -58,8 +58,8 @@ Feature: Submit using checkbox item and check form validation (4 of 4) # Test number 2: Student submits a standard answer And I press "New response" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -91,7 +91,7 @@ Feature: Submit using checkbox item and check form validation (4 of 4) Then I should see "At least 2 checkboxes have to be selected" And I press "Submit" Then I should see "Please tick at least 2 options" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,7 +100,7 @@ Feature: Submit using checkbox item and check form validation (4 of 4) # Test number 4: Student submits a standard answer And I press "New response" Then I should see "At least 2 checkboxes have to be selected" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/behat/settings_configuration_05.feature b/field/checkbox/tests/behat/settings_configuration_05.feature index 5e2fa3f8476..71b07c38cf0 100644 --- a/field/checkbox/tests/behat/settings_configuration_05.feature +++ b/field/checkbox/tests/behat/settings_configuration_05.feature @@ -40,8 +40,8 @@ Feature: Submit using checkbox item and check form validation And I press "New response" Then I should not see "No more than" And I set the following fields to these values: - | id_surveypro_field_checkbox_1_0 | 1 | - | id_surveypro_field_checkbox_1_3 | 1 | + | id_field_checkbox_1_0 | 1 | + | id_field_checkbox_1_3 | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -62,13 +62,13 @@ Feature: Submit using checkbox item and check form validation # Test number 2: Student ticks too many checkboxes And I press "New response" Then I should see "No more than 3 checkboxes are allowed" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" - And I set the field "id_surveypro_field_checkbox_1_1" to "1" - And I set the field "id_surveypro_field_checkbox_1_2" to "1" - And I set the field "id_surveypro_field_checkbox_1_3" to "1" + And I set the field "id_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_1" to "1" + And I set the field "id_field_checkbox_1_2" to "1" + And I set the field "id_field_checkbox_1_3" to "1" And I press "Submit" Then I should see "Please tick no more than 3 options" - And I set the field "id_surveypro_field_checkbox_1_1" to "0" + And I set the field "id_field_checkbox_1_1" to "0" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -77,7 +77,7 @@ Feature: Submit using checkbox item and check form validation # Test number 3: Student submits a standard answer And I press "New response" Then I should see "No more than 3 checkboxes are allowed" - And I set the field "id_surveypro_field_checkbox_1_0" to "1" + And I set the field "id_field_checkbox_1_0" to "1" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml b/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml similarity index 93% rename from field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml rename to field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml index 2670b5e66e8..de1b71eaf44 100644 --- a/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2015123000.xml +++ b/field/checkbox/tests/fixtures/usertemplate/checkbox_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>CHECKBOX</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>checkbox specific setting</b>:</p><ol><li>Options</li><li>"Option other"</li><li>Default</li><li>"No answer" as defaults</li><li>Adjustment</li><li>Minimum required options</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>CHECKBOX</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>checkbox specific setting</b>:</p><ol><li>Options</li><li>"Option other"</li><li>Default</li><li>"No answer" as defaults</li><li>Adjustment</li><li>Minimum required options</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -42,6 +37,11 @@ 1 0 checkbox_001 + 0 + 0 + 0 + + milk coffee butter @@ -54,27 +54,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -83,6 +78,11 @@ bread 2 0 checkbox_002 + 0 + 0 + 0 + + milk coffee butter @@ -95,27 +95,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.<br /> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.<br /> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -124,6 +119,11 @@ bread 3 0 checkbox_003 + 0 + 0 + 0 + + milk coffee butter @@ -136,28 +136,23 @@ bread 1 - + - 0 - 0 - 0 - - <ul><li>mandatory (so: "No answer" is not expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select al least two checkboxes.</p> 1 0 4 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 1 @@ -166,6 +161,11 @@ required options is set to 2. So he/she is forced to or select al least two chec 4 0 checkbox_004 + 0 + 0 + 0 + + milk coffee butter @@ -178,27 +178,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -207,6 +202,11 @@ bread 5 0 checkbox_005 + 0 + 0 + 0 + + milk coffee butter @@ -218,27 +218,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -247,6 +242,11 @@ bread 6 0 checkbox_006 + 0 + 0 + 0 + + milk coffee butter @@ -258,27 +258,22 @@ bread 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -287,6 +282,11 @@ bread 7 0 checkbox_007 + 0 + 0 + 0 + + milk coffee butter @@ -298,27 +298,22 @@ bread 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is not set so the user is forced to tick at least two checkboxes.</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 @@ -327,6 +322,11 @@ bread 8 0 checkbox_008 + 0 + 0 + 0 + + milk coffee butter @@ -338,27 +338,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -367,6 +362,11 @@ bread 9 0 checkbox_009 + 0 + 0 + 0 + + milk coffee butter @@ -379,27 +379,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>"butter" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer".</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -408,6 +403,11 @@ bread 10 0 checkbox_010 + 0 + 0 + 0 + + milk coffee butter @@ -420,13 +420,8 @@ bread 0 - + - 0 - 0 - 0 - - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two @@ -434,16 +429,16 @@ options or to tick the "No answer" checkbox.</p> 1 0 11 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 0 @@ -452,6 +447,11 @@ options or to tick the "No answer" checkbox.</p> 11 0 checkbox_011 + 0 + 0 + 0 + + milk coffee butter @@ -464,27 +464,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"butter" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -493,6 +488,11 @@ bread 12 0 checkbox_013 + 0 + 0 + 0 + + milk coffee butter @@ -505,27 +505,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -534,6 +529,11 @@ bread 13 0 checkbox_012 + 0 + 0 + 0 + + milk coffee butter @@ -546,27 +546,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to an invalid value so the user is forced to tick at least one checkbox.</p> + 1 + 0 + 14 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to an invalid value so the user is forced to tick at least one checkbox.</p> - 1 - 0 - 14 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -575,6 +570,11 @@ bread 14 0 checkbox_014 + 0 + 0 + 0 + + milk coffee butter @@ -587,27 +587,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value <span class="rangySelectionBoundary" style="line-height:0;"></span>so the user can "fly" over this element leaving the proposed default untouched (and the question not read).<br /> + 1 + 0 + 15 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value <span class="rangySelectionBoundary" style="line-height:0;"></span>so the user can "fly" over this element leaving the proposed default untouched (and the question not read).<br /> - 1 - 0 - 15 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -616,6 +611,11 @@ bread 15 0 checkbox_015 + 0 + 0 + 0 + + milk coffee butter @@ -628,28 +628,23 @@ bread 1 - + - 0 - 0 - 0 - - <ul><li>not mandatory (so: "No answer" is expected)</li><li>"No answer" is the default</li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value but the user can not "fly" over this element because the minimum required options is set to 2. So he/she is forced to or select two options or to tick the "No answer" checkbox.</p> 1 0 16 intro - 0 - - - - 0 0 0 - + + 0 + + + + <p>What do you usually get for breakfast?</p> 1 0 @@ -658,6 +653,11 @@ options or to tick the "No answer" checkbox.</p> 16 0 checkbox_016 + 0 + 0 + 0 + + milk coffee butter @@ -670,27 +670,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> + 1 + 0 + 17 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> - 1 - 0 - 17 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -699,6 +694,11 @@ bread 17 0 checkbox_017 + 0 + 0 + 0 + + milk coffee butter @@ -710,27 +710,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> + 1 + 0 + 18 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 1<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least one checkbox or to select the "No answer" checkbox.</p> - 1 - 0 - 18 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -739,6 +734,11 @@ bread 18 0 checkbox_018 + 0 + 0 + 0 + + milk coffee butter @@ -750,27 +750,22 @@ bread 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" chackbox.</p> + 1 + 0 + 19 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are horizzontally displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" chackbox.</p> - 1 - 0 - 19 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -779,6 +774,11 @@ bread 19 0 checkbox_019 + 0 + 0 + 0 + + milk coffee butter @@ -790,27 +790,22 @@ bread 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" checkbox.</p> + 1 + 0 + 20 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>default is not set<br /></li><li>minimum required options set to 2<br /></li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is not set so the user is forced to tick at least two checkboxes or to select the "No answer" checkbox.</p> - 1 - 0 - 20 intro 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -819,6 +814,11 @@ bread 20 0 checkbox_020 + 0 + 0 + 0 + + milk coffee butter diff --git a/field/checkbox/version.php b/field/checkbox/version.php index edec4f389b7..de38867efca 100644 --- a/field/checkbox/version.php +++ b/field/checkbox/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023111401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_checkbox'; // Full name of the plugin (used for diagnostics). diff --git a/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php b/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php index 9ab1acb14cd..df5f8bcbb30 100644 --- a/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php +++ b/field/date/backup/moodle2/backup_surveyprofield_date_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'date'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugindate = new backup_nested_element('surveyprofield_date', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/date/classes/item.php b/field/date/classes/item.php index a05029b53b8..9ee18e4b441 100644 --- a/field/date/classes/item.php +++ b/field/date/classes/item.php @@ -40,67 +40,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var string Format of the content once downloaded */ - protected $variable; + protected $downloadformat; /** - * @var int Indent of the item in the form page + * @var int Defaultvalue for the item answer */ - protected $indent; + protected $defaultvalue; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the date in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Upperbound for the date in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the date in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Year of the defaultvalue for the date in unixtime @@ -117,11 +84,6 @@ class item extends itembase { */ protected $defaultvalueday; - /** - * @var int Lowerbound for the date in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the date in unixtime */ @@ -137,11 +99,6 @@ class item extends itembase { */ protected $lowerboundday; - /** - * @var int Upperbound for the date in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the date in unixtime */ @@ -157,6 +114,11 @@ class item extends itembase { */ protected $upperboundday; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -193,7 +155,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_date_to_unix_time($this->surveypro->stopyear, 12, 31); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -225,28 +189,15 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } - /** - * Is this item available as a parent? - * - * @return the content of the static property "canbeparent" - */ - public static function get_canbeparent() { - return self::$canbeparent; - } - /** * Item add mandatory plugin fields * Copy mandatory fields to $record @@ -254,14 +205,7 @@ public static function get_canbeparent() { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date [dd/mm/yyyy]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'date_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 43200; $record->downloadformat = 'strftime05'; @@ -278,7 +222,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_date_to_unix_time($year, $month, $day) { - return (mktime(12, 0, 0, $month, $day, $year)); + return (gmmktime(12, 0, 0, $month, $day, $year)); } /** @@ -328,7 +272,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -355,8 +299,276 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + // MARK get. + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; + } + /** * Get the list of composite fields. * @@ -393,14 +605,31 @@ public function get_friendlyformat() { return 'strftime05'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'defaultvalueday', 'lowerboundyear', + 'lowerboundmonth', 'lowerboundday', 'upperboundyear', 'upperboundmonth', 'upperboundday', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_date'] = []; return $fieldlist; } @@ -417,30 +646,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -474,8 +684,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_date_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -513,66 +721,58 @@ public function userform_mform_element($mform, $searchform, $readonly) { // End of: element values. // Begin of: mform element. - $attributes = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_date_'.$this->sortindex; $elementgroup = []; + $attributes = []; + $basename = $this->itemname; - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' date_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'date_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + $mform->setType($basename, PARAM_RAW); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'date_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + $mform->setType($basename, PARAM_RAW); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -586,7 +786,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $datearray['year'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -623,13 +823,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $datearray['mday']); - $mform->setDefault($this->itemname.'_month', $datearray['mon']); - $mform->setDefault($this->itemname.'_year', $datearray['year']); + $mform->setDefault($basename.'_day', $datearray['mday']); + $mform->setDefault($basename.'_month', $datearray['mon']); + $mform->setDefault($basename.'_year', $datearray['year']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -693,12 +893,12 @@ public function userform_mform_validation($data, &$errors, $searchform) { if (!utility_item::date_is_valid($userday, $usermonth, $useryear)) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_date_to_unix_time($this->surveypro->startyear, 1, 1)); @@ -719,6 +919,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_date'); } } + + return $errors; } /** @@ -866,8 +1068,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/date/db/install.xml b/field/date/db/install.xml index fce59831c68..4ad6c7df1dc 100644 --- a/field/date/db/install.xml +++ b/field/date/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/date/db/upgrade.php b/field/date/db/upgrade.php index 949c9ac37d3..6265f2a464e 100644 --- a/field/date/db/upgrade.php +++ b/field/date/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_date_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Date savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'date'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_date. + $table = new xmldb_table('surveyprofield_date'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_date} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Date savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'date'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_date'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_date. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_date} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Date savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'date'); + } + return true; } diff --git a/field/date/lang/en/surveyprofield_date.php b/field/date/lang/en/surveyprofield_date.php index a5de32ebe80..7f123739482 100644 --- a/field/date/lang/en/surveyprofield_date.php +++ b/field/date/lang/en/surveyprofield_date.php @@ -25,19 +25,20 @@ $string['currentdatedefault'] = 'Current date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the date the remote user will find answered by default. The default for this type of question is mandatory. If "Current date" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the date the remote user will find answered by default. The default for this type of question is mandatory. If "Current date" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['inviteday'] = 'Choose a day'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['pluginname'] = 'Date'; +$string['privacy:metadata'] = 'The "Date" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -56,7 +57,6 @@ $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date [dd/mm/yyyy]'; -$string['privacy:metadata'] = 'The "Date" field plugin does not store any personal data.'; diff --git a/field/date/tests/behat/itemform.feature b/field/date/tests/behat/itemform.feature index b932043ddd3..f9d80718193 100644 --- a/field/date/tests/behat/itemform.feature +++ b/field/date/tests/behat/itemform.feature @@ -112,7 +112,7 @@ Feature: Create a date item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When were you born?" - Then the field "id_surveypro_field_date_2_day" matches value "1" - Then the field "id_surveypro_field_date_2_month" matches value "January" - Then the field "id_surveypro_field_date_2_year" matches value "1980" + Then the field "id_field_date_2_day" matches value "1" + Then the field "id_field_date_2_month" matches value "January" + Then the field "id_field_date_2_year" matches value "1980" Then I should see "Additional note" diff --git a/field/date/tests/behat/submit_date.feature b/field/date/tests/behat/submit_date.feature index 05dc972463a..644a1ca7874 100644 --- a/field/date/tests/behat/submit_date.feature +++ b/field/date/tests/behat/submit_date.feature @@ -43,9 +43,9 @@ Feature: Submit using a date item # student1 submits And I set the following fields to these values: - | id_surveypro_field_date_1_day | 16 | - | id_surveypro_field_date_1_month | October | - | id_surveypro_field_date_1_year | 1988 | + | id_field_date_1_day | 16 | + | id_field_date_1_month | October | + | id_field_date_1_year | 1988 | And I press "Submit" diff --git a/field/date/tests/fixtures/usertemplate/date_only_2023103100.xml b/field/date/tests/fixtures/usertemplate/date_only_2024032800.xml similarity index 91% rename from field/date/tests/fixtures/usertemplate/date_only_2023103100.xml rename to field/date/tests/fixtures/usertemplate/date_only_2024032800.xml index 7fcd9490203..13e0f5b7a19 100644 --- a/field/date/tests/fixtures/usertemplate/date_only_2023103100.xml +++ b/field/date/tests/fixtures/usertemplate/date_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -42,6 +37,11 @@ 1 0 date_001 + 0 + 0 + 0 + + 2 39600 strftime09 @@ -49,28 +49,23 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - - When did you get your degree? + <p>When did you get your degree?</p> 1 0 0 @@ -78,35 +73,35 @@ 2 0 date_002 + 0 + 0 + 0 + + 1 - 1420110000 + 1420023600 strftime09 1414839600 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - - When did you get your degree? + <p>When did you get your degree?</p> 1 0 0 @@ -114,6 +109,11 @@ 3 0 date_003 + 0 + 0 + 0 + + 4 39600 strftime09 @@ -121,27 +121,22 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -150,6 +145,11 @@ 4 0 date_004 + 0 + 0 + 0 + + 5 39600 strftime09 @@ -157,27 +157,22 @@ 1446289200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 0 @@ -186,6 +181,11 @@ 5 0 date_005 + 0 + 0 + 0 + + 3 39600 strftime09 @@ -193,27 +193,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -222,6 +217,11 @@ 6 0 date_006 + 0 + 0 + 0 + + 2 39600 strftime09 @@ -229,27 +229,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -258,34 +253,34 @@ 7 0 date_007 + 0 + 0 + 0 + + 1 - 1420110000 + 31489200 strftime09 1414839600 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -294,6 +289,11 @@ 8 0 date_008 + 0 + 0 + 0 + + 4 39600 strftime09 @@ -301,27 +301,22 @@ 1446289200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited to academic year 2014/2015, i.e. November 1st, 2014 - October 31, 2015</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When did you get your degree? 1 1 @@ -330,6 +325,11 @@ 9 0 date_009 + 0 + 0 + 0 + + 5 39600 strftime09 diff --git a/field/date/version.php b/field/date/version.php index c549b7b54b7..ff766dd14d2 100644 --- a/field/date/version.php +++ b/field/date/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_date'; // Full name of the plugin (used for diagnostics). diff --git a/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php b/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php index 71ad0f6c81a..4eff204d942 100644 --- a/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php +++ b/field/datetime/backup/moodle2/backup_surveyprofield_datetime_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'datetime'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugindatetime = new backup_nested_element('surveyprofield_datetime', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/datetime/classes/item.php b/field/datetime/classes/item.php index 37c4a8e7d2f..a229302423f 100644 --- a/field/datetime/classes/item.php +++ b/field/datetime/classes/item.php @@ -40,52 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Step for minutes drop down menu @@ -103,10 +58,22 @@ class item extends itembase { protected $downloadformat; /** - * @var int Defaultvalue for the datetime in unixtime + * @var int Defaultvalue for the item answer */ protected $defaultvalue; + /** + * @var int Lowerbound for the datetime in unixtime + */ + protected $lowerbound; + + /** + * @var int Upperbound for the datetime in unixtime + */ + protected $upperbound; + + // Service variables. + /** * @var int Year of the defaultvalue for the datetime in unixtime */ @@ -132,11 +99,6 @@ class item extends itembase { */ protected $defaultvalueminute; - /** - * @var int Lowerbound for the datetime in unixtime - */ - protected $lowerbound; - /** * @var int Year of the lowerbound for the datetime in unixtime */ @@ -162,11 +124,6 @@ class item extends itembase { */ protected $lowerboundminute; - /** - * @var int Upperbound for the datetime in unixtime - */ - protected $upperbound; - /** * @var int Year of the upperbound for the datetime in unixtime */ @@ -192,6 +149,11 @@ class item extends itembase { */ protected $upperboundminute; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -228,7 +190,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_datetime_to_unix_time($this->surveypro->stopyear, 12, 31, 23, 59); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -260,14 +224,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -280,14 +240,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date and time [dd/mm/yyyy;hh:mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'datetime_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->step = 1; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; @@ -307,7 +260,9 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_datetime_to_unix_time($year, $month, $day, $hour, $minute) { - return (mktime($hour, $minute, 0, $month, $day, $year)); + $unixtime = gmmktime($hour, $minute, 0, $month, $day, $year); + + return $unixtime; } /** @@ -360,7 +315,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -392,15 +347,407 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set step. + * + * @param string $step + * @return void + */ + public function set_step($step) { + $this->step = $step; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set defaultvaluehour. + * + * @param string $defaultvaluehour + * @return void + */ + public function set_defaultvaluehour($defaultvaluehour) { + $this->defaultvaluehour = $defaultvaluehour; + } + + /** + * Set defaultvalueminute. + * + * @param string $defaultvalueminute + * @return void + */ + public function set_defaultvalueminute($defaultvalueminute) { + $this->defaultvalueminute = $defaultvalueminute; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set lowerboundhour. + * + * @param string $lowerboundhour + * @return void + */ + public function set_lowerboundhour($lowerboundhour) { + $this->lowerboundhour = $lowerboundhour; + } + + /** + * Set lowerboundminute. + * + * @param string $lowerboundminute + * @return void + */ + public function set_lowerboundminute($lowerboundminute) { + $this->lowerboundminute = $lowerboundminute; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + + /** + * Set upperboundhour. + * + * @param string $upperboundhour + * @return void + */ + public function set_upperboundhour($upperboundhour) { + $this->upperboundhour = $upperboundhour; + } + + /** + * Set upperboundminute. + * + * @param string $upperboundminute + * @return void + */ + public function set_upperboundminute($upperboundminute) { + $this->upperboundminute = $upperboundminute; + } + // MARK get. /** - * Is this item available as a parent? + * Get step. + * + * @return $this->step + */ + public function get_step() { + return $this->step; + } + + /** + * Get defaultoption. * - * @return the content of the static property "canbeparent" + * @return $this->defaultoption */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get defaultvaluehour. + * + * @return $this->defaultvaluehour + */ + public function get_defaultvaluehour() { + return $this->defaultvaluehour; + } + + /** + * Get defaultvalueminute. + * + * @return $this->defaultvalueminute + */ + public function get_defaultvalueminute() { + return $this->defaultvalueminute; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get lowerboundhour. + * + * @return $this->lowerboundhour + */ + public function get_lowerboundhour() { + return $this->lowerboundhour; + } + + /** + * Get lowerboundminute. + * + * @return $this->lowerboundminute + */ + public function get_lowerboundminute() { + return $this->lowerboundminute; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; + } + + /** + * Get upperboundhour. + * + * @return $this->upperboundhour + */ + public function get_upperboundhour() { + return $this->upperboundhour; + } + + /** + * Get upperboundminute. + * + * @return $this->upperboundminute + */ + public function get_upperboundminute() { + return $this->upperboundminute; } /** @@ -439,14 +786,32 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'defaultvalueday', 'defaultvaluehour', 'defaultvalueminute', + 'lowerboundyear', 'lowerboundmonth', 'lowerboundday', 'lowerboundhour', 'lowerboundminute', + 'upperboundyear', 'upperboundmonth', 'upperboundday', 'upperboundhour', 'upperboundminute', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_datetime'] = []; return $fieldlist; } @@ -463,31 +828,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - - + + + @@ -521,8 +867,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_datetime_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -595,28 +939,20 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; - - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' datetime_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); - - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'datetime_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); - - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); - - $itemname = $this->itemname.'_hour'; - $attributes['id'] = $idprefix.'_hour'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $hours, $attributes); - - $itemname = $this->itemname.'_minute'; - $attributes['id'] = $idprefix.'_minute'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $minutes, $attributes); + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_datetime_'.$this->sortindex; + $basename = $this->itemname; + + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); + $attributes['id'] = $baseid.'_hour'; + $elementgroup[] = $mform->createElement('select', $basename.'_hour', '', $hours, $attributes); + $attributes['id'] = $baseid.'_minute'; + $elementgroup[] = $mform->createElement('select', $basename.'_minute', '', $minutes, $attributes); $separator = [' ', ' ']; $nextseparator = \html_writer::tag('div', ',', ['class' => 'datetime_separator_comma']); @@ -626,48 +962,40 @@ public function userform_mform_element($mform, $searchform, $readonly) { if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'datetime_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); $separator[] = ' '; if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -683,7 +1011,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $datetimearray['minutes'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -722,15 +1050,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $datetimearray['mday']); - $mform->setDefault($this->itemname.'_month', $datetimearray['mon']); - $mform->setDefault($this->itemname.'_year', $datetimearray['year']); - $mform->setDefault($this->itemname.'_hour', $datetimearray['hours']); - $mform->setDefault($this->itemname.'_minute', $datetimearray['minutes']); + $mform->setDefault($basename.'_day', $datetimearray['mday']); + $mform->setDefault($basename.'_month', $datetimearray['mon']); + $mform->setDefault($basename.'_year', $datetimearray['year']); + $mform->setDefault($basename.'_hour', $datetimearray['hours']); + $mform->setDefault($basename.'_minute', $datetimearray['minutes']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -749,13 +1077,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -797,18 +1125,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_datetimenotset', 'surveyprofield_datetime', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if (!utility_item::date_is_valid($userday, $usermonth, $useryear)) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_datetime_to_unix_time($this->surveypro->startyear, 1, 1, 0, 0)); @@ -829,6 +1157,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_datetime'); } } + + return $errors; } /** @@ -988,8 +1318,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/datetime/db/install.xml b/field/datetime/db/install.xml index 99c032be40c..7b5488e3cfc 100644 --- a/field/datetime/db/install.xml +++ b/field/datetime/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/datetime/db/upgrade.php b/field/datetime/db/upgrade.php index e3c173d356a..ece59f8e32d 100644 --- a/field/datetime/db/upgrade.php +++ b/field/datetime/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_datetime_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Datetime savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'datetime'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_datetime. + $table = new xmldb_table('surveyprofield_datetime'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_datetime} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Datetime savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'datetime'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_datetime'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_datetime. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_datetime} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Datetime savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'datetime'); + } + return true; } diff --git a/field/datetime/lang/en/surveyprofield_datetime.php b/field/datetime/lang/en/surveyprofield_datetime.php index 5a5a7954dae..8af4b2455cb 100644 --- a/field/datetime/lang/en/surveyprofield_datetime.php +++ b/field/datetime/lang/en/surveyprofield_datetime.php @@ -25,10 +25,10 @@ $string['currentdatetimedefault'] = 'Current date and time'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the date and time the remote user will find answered by default. The default for this type of question is mandatory. If "Current date and time" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the date and time the remote user will find answered by default. The default for this type of question is mandatory. If "Current date and time" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['fifteenminutes'] = 'fifteen minutes'; $string['fiveminutes'] = 'five minutes'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; @@ -39,15 +39,16 @@ $string['inviteminute'] = 'Choose a minute'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date and time the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date and time the user is allowed to enter'; $string['oneminute'] = 'one minute'; $string['pluginname'] = 'Date and time'; +$string['privacy:metadata'] = 'The "Date and time" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; -$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['step'] = 'Step'; +$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['strftime01'] = '%A, %d %B %Y, %H:%M'; $string['strftime02'] = '%A, %d %B %Y, %I:%M %p'; $string['strftime03'] = '%a, %d %b %Y, %H:%M'; @@ -68,7 +69,6 @@ $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest date and time the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date and time the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date and time [dd/mm/yyyy;hh:mm]'; -$string['privacy:metadata'] = 'The "Date and time" field plugin does not store any personal data.'; diff --git a/field/datetime/tests/behat/itemform.feature b/field/datetime/tests/behat/itemform.feature index d04171b14b3..4bf000248c7 100644 --- a/field/datetime/tests/behat/itemform.feature +++ b/field/datetime/tests/behat/itemform.feature @@ -136,9 +136,9 @@ Feature: Create a datetime item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Please, write down date and time of your last flight to Los Angeles." - Then the field "id_surveypro_field_datetime_2_day" matches value "1" - Then the field "id_surveypro_field_datetime_2_month" matches value "January" - Then the field "id_surveypro_field_datetime_2_year" matches value "1980" - Then the field "id_surveypro_field_datetime_2_hour" matches value "0" - Then the field "id_surveypro_field_datetime_2_minute" matches value "0" + Then the field "id_field_datetime_2_day" matches value "1" + Then the field "id_field_datetime_2_month" matches value "January" + Then the field "id_field_datetime_2_year" matches value "1980" + Then the field "id_field_datetime_2_hour" matches value "0" + Then the field "id_field_datetime_2_minute" matches value "0" Then I should see "Additional note" diff --git a/field/datetime/tests/behat/submit_datetime.feature b/field/datetime/tests/behat/submit_datetime.feature index 45ffd8cc0ca..f2982c12a94 100644 --- a/field/datetime/tests/behat/submit_datetime.feature +++ b/field/datetime/tests/behat/submit_datetime.feature @@ -43,11 +43,11 @@ Feature: Submit using a datetime item # student1 submits And I set the following fields to these values: - | id_surveypro_field_datetime_1_day | 23 | - | id_surveypro_field_datetime_1_month | August | - | id_surveypro_field_datetime_1_year | 2010 | - | id_surveypro_field_datetime_1_hour | 17 | - | id_surveypro_field_datetime_1_minute | 35 | + | id_field_datetime_1_day | 23 | + | id_field_datetime_1_month | August | + | id_field_datetime_1_year | 2010 | + | id_field_datetime_1_hour | 17 | + | id_field_datetime_1_minute | 35 | And I press "Submit" diff --git a/field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml b/field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml similarity index 88% rename from field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml rename to field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml index c0fe8b25843..446785b16cf 100644 --- a/field/datetime/tests/fixtures/usertemplate/datetime_only_2023103100.xml +++ b/field/datetime/tests/fixtures/usertemplate/date_and_time_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>DATETIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>datetime specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>DATETIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>datetime specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 1 - 0 + 1 datetime_001 + 0 + 0 + 0 + + 1 2 -3600 @@ -50,35 +49,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 2 - 0 + 1 datetime_002 + 0 + 0 + 0 + + 1 1 1442758320 @@ -87,35 +85,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 3 - 0 + 1 datetime_003 + 0 + 0 + 0 + + 1 4 -3600 @@ -124,35 +121,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date and time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date and time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 4 - 0 + 1 datetime_004 + 0 + 0 + 0 + + 1 5 -3600 @@ -161,35 +157,34 @@ 1442966340 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 0 0 0 - 5 - 0 + 1 datetime_005 + 0 + 0 + 0 + + 1 3 -3600 @@ -198,35 +193,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 6 - 0 + 1 datetime_006 + 0 + 0 + 0 + + 1 2 -3600 @@ -235,35 +229,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 7 - 0 + 1 datetime_007 + 0 + 0 + 0 + + 1 1 1442758320 @@ -272,35 +265,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 8 - 0 + 1 datetime_008 + 0 + 0 + 0 + + 1 4 -3600 @@ -309,35 +301,34 @@ 1442966340 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is limited between 15 to 22 September</li><li>the default is set to the current date</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - Please, write down date and time of your last flight to Los Angeles. 1 1 0 0 - 9 - 0 + 1 datetime_009 + 0 + 0 + 0 + + 1 5 -3600 diff --git a/field/datetime/version.php b/field/datetime/version.php index 7716c4e99de..7ae855ed948 100644 --- a/field/datetime/version.php +++ b/field/datetime/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_datetime'; // Full name of the plugin (used for diagnostics). diff --git a/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php b/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php index 0f73a57b256..c0755eb23f5 100644 --- a/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php +++ b/field/fileupload/backup/moodle2/backup_surveyprofield_fileupload_subplugin.class.php @@ -42,9 +42,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'fileupload'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginfileupload = new backup_nested_element('surveyprofield_fileupload', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'maxfiles', 'maxbytes', 'filetypes', ]); + 'maxfiles', 'maxbytes', 'filetypes', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/fileupload/classes/item.php b/field/fileupload/classes/item.php index 4a38c701b35..debfb67c5a9 100644 --- a/field/fileupload/classes/item.php +++ b/field/fileupload/classes/item.php @@ -39,47 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Maximum number of files allowed to upload @@ -96,6 +56,13 @@ class item extends itembase { */ protected $filetypes; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -128,9 +95,11 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. - $this->insetupform['insearchform'] = false; + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -159,14 +128,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -178,7 +143,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -199,37 +164,94 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Attachment'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'fileupload_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->maxfiles = 1; $record->maxbytes = 1048576; $record->filetypes = '*'; } + // MARK set. + + /** + * Set maxfiles. + * + * @param string $maxfiles + * @return void + */ + public function set_maxfiles($maxfiles) { + $this->maxfiles = $maxfiles; + } + + /** + * Set maxbytes. + * + * @param string $maxbytes + * @return void + */ + public function set_maxbytes($maxbytes) { + $this->maxbytes = $maxbytes; + } + + /** + * Set filetypes. + * + * @param string $filetypes + * @return void + */ + public function set_filetypes($filetypes) { + $this->filetypes = $filetypes; + } + // MARK get. /** - * Is this item available as a parent? + * Get maxfiles. + * + * @return $this->maxfiles + */ + public function get_maxfiles() { + return $this->maxfiles; + } + + /** + * Get maxbytes. * - * @return the content of the static property "canbeparent" + * @return $this->maxbytes */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_maxbytes() { + return $this->maxbytes; + } + + /** + * Get filetypes. + * + * @return $this->filetypes + */ + public function get_filetypes() { + return $this->filetypes; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['maxfiles', 'maxbytes', 'filetypes']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_fileupload'] = []; return $fieldlist; } @@ -246,28 +268,9 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -290,34 +293,69 @@ public static function get_plugin_schema() { public function userform_mform_element($mform, $searchform, $readonly) { // This plugin has $this->insetupform['insearchform'] = false; so it will never be part of a search form. - $fieldname = $this->itemname.'_filemanager'; + $useinline = true; + if (!$useinline) { + $fieldname = $this->itemname.'_filemanager'; + + if ($this->position == SURVEYPRO_POSITIONLEFT) { + $elementlabel = $this->get_contentwithnumber(); + } else { + $elementlabel = ' '; + } + + $idprefix = 'id_surveypro_field_fileupload_'.$this->sortindex; + + $filetypes = array_map('trim', explode(',', $this->filetypes)); - if ($this->position == SURVEYPRO_POSITIONLEFT) { - $elementlabel = $this->get_contentwithnumber(); + $attributes = []; + $attributes['id'] = $idprefix; + $attributes['class'] = 'indent-'.$this->indent.' fileupload_filemanager'; // Does not work: MDL-28194. + $attributes['maxbytes'] = $this->maxbytes; + $attributes['accepted_types'] = $filetypes; + $attributes['subdirs'] = false; + $attributes['maxfiles'] = $this->maxfiles; + $mform->addElement('filemanager', $fieldname, $elementlabel, null, $attributes); + + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $mform->_required[] = $starplace; + } } else { - $elementlabel = ' '; - } + if ($this->position == SURVEYPRO_POSITIONLEFT) { + $elementlabel = $this->get_contentwithnumber(); + } else { + $elementlabel = ' '; + } - $idprefix = 'id_surveypro_field_fileupload_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_fileupload_'.$this->sortindex; + $basename = $this->itemname; - $filetypes = array_map('trim', explode(',', $this->filetypes)); + $filetypes = array_map('trim', explode(',', $this->filetypes)); - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' fileupload_filemanager'; // Does not work: MDL-28194. - $attributes['maxbytes'] = $this->maxbytes; - $attributes['accepted_types'] = $filetypes; - $attributes['subdirs'] = false; - $attributes['maxfiles'] = $this->maxfiles; - $mform->addElement('mod_surveypro_fileupload', $fieldname, $elementlabel, null, $attributes); + $attributes['id'] = $baseid; + $attributes['maxbytes'] = $this->maxbytes; + $attributes['accepted_types'] = $filetypes; + $attributes['subdirs'] = false; + $attributes['maxfiles'] = $this->maxfiles; - if ($this->required) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; + $elementgroup[] = $mform->createElement('filemanager', $basename.'_filemanager', $elementlabel, null, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); + + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; + } } } @@ -331,7 +369,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if ($this->required) { @@ -340,9 +378,10 @@ public function userform_mform_validation($data, &$errors, $searchform) { $fieldname = $this->itemname.'_filemanager'; if (empty($data[$fieldname])) { $errors[$errorkey] = get_string('required'); - return; } } + + return $errors; } /** @@ -365,8 +404,10 @@ public function userform_get_user_answer($answer, &$olduseranswer, $searchform) $attributes['accepted_types'] = $this->filetypes; $attributes['subdirs'] = false; $attributes['maxfiles'] = $this->maxfiles; - file_save_draft_area_files($answer['filemanager'], $context->id, 'surveyprofield_fileupload', - 'fileuploadfiles', $olduseranswer->id, $attributes); + file_save_draft_area_files( + $answer['filemanager'], $context->id, 'surveyprofield_fileupload', + 'fileuploadfiles', $olduseranswer->id, $attributes + ); $olduseranswer->content = ''; // Nothing is expected here. } @@ -388,7 +429,7 @@ public function userform_get_prefill($fromdb) { $context = \context_module::instance($this->cm->id); $fieldname = $this->itemname.'_filemanager'; - $draftitemid = 0; + $draftitemid = file_get_submitted_draft_itemid('surveyprofield_fileupload'); // ???? $attributes = []; $attributes['maxbytes'] = $this->maxbytes; $attributes['accepted_types'] = $this->filetypes; @@ -432,8 +473,6 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_filemanager']; - - return $elementnames; + return [$this->itemname.'_filemanager']; } } diff --git a/field/fileupload/db/install.xml b/field/fileupload/db/install.xml index 14e27e774d4..fd2c1bf3eb5 100644 --- a/field/fileupload/db/install.xml +++ b/field/fileupload/db/install.xml @@ -1,32 +1,16 @@ -
- - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/field/fileupload/db/upgrade.php b/field/fileupload/db/upgrade.php index 69707b74462..8c8a5d900ea 100644 --- a/field/fileupload/db/upgrade.php +++ b/field/fileupload/db/upgrade.php @@ -95,5 +95,66 @@ function xmldb_surveyprofield_fileupload_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2018060501, 'surveyprofield', 'fileupload'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_fileupload. + $table = new xmldb_table('surveyprofield_fileupload'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_fileupload} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Fileupload savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'fileupload'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_fileupload'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_fileupload. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_fileupload} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Fileupload savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'fileupload'); + } + return true; } diff --git a/field/fileupload/lang/en/surveyprofield_fileupload.php b/field/fileupload/lang/en/surveyprofield_fileupload.php index 3fc24982295..e704f401ec8 100644 --- a/field/fileupload/lang/en/surveyprofield_fileupload.php +++ b/field/fileupload/lang/en/surveyprofield_fileupload.php @@ -23,18 +23,18 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['filetypes_help'] = 'The comma separated list of allowed file extension'; -$string['filetypes'] = 'Allowed file types (comma separated)'; $string['fileextensions'] = 'Allowed file extensions: '; +$string['filetypes'] = 'Allowed file types (comma separated)'; +$string['filetypes_help'] = 'The comma separated list of allowed file extension'; +$string['ierr_dirtyextension'] = 'Only lower case letters and numbers are allowed into file extensions'; $string['ierr_extensionisempty'] = 'File extensions can not be empty. Probabily you typed a comma twice.'; $string['ierr_extensionmissingdot'] = 'File extensions must start with a dot'; $string['ierr_extensiononlyonedot'] = 'Only one dot is allowed per each file extension'; -$string['ierr_dirtyextension'] = 'Only lower case letters and numbers are allowed into file extensions'; $string['ierr_staramongextensions'] = '\'*\' is meaningful only if used individually'; -$string['maxbytes_help'] = 'Maximum size of the file to upload'; $string['maxbytes'] = 'Maximum file size'; -$string['maxfiles_help'] = 'Maximum uploadable attachments'; +$string['maxbytes_help'] = 'Maximum size of the file to upload'; $string['maxfiles'] = 'Maximum files'; +$string['maxfiles_help'] = 'Maximum uploadable attachments'; $string['pluginname'] = 'File upload'; -$string['userfriendlypluginname'] = 'Attachment'; $string['privacy:metadata'] = 'The "Fileupload" field plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Attachment'; diff --git a/field/fileupload/mform/fileupload.php b/field/fileupload/mform/fileupload.php deleted file mode 100644 index 8e485f1a668..00000000000 --- a/field/fileupload/mform/fileupload.php +++ /dev/null @@ -1,159 +0,0 @@ -. - -/** - * filemanager mform element - * - * Extends the core mform class for filemanager element - * - * @package surveyprofield_fileupload - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/filemanager.php'); - -// @codingStandardsIgnoreFile - -/** - * filemanager mform element - * - * Extends the core mform class for filemanager element - * - * @package surveyprofield_fileupload - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_fileupload extends \MoodleQuickForm_filemanager { - - /** - * Constructor. - * - * @param string $elementName Optional name of the filemanager - * @param string $elementLabel Optional filemanager label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filemanager - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - $this->_options['class'] = !isset($options['class']) ? 'indent-0' : $options['class']; - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * I want to change at the beginning: - *
- * to - *
- * - * @return string $output - */ - public function toHtml() { - $output = parent::toHtml(); // Core code. - - // I need to trim the code because mform library add a newline at the beginning. - $output = trim($output); - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
_options['class']; - $replacement = $tabs.'
dirroot/repository/lib.php"); - - $id = $this->_attributes['id']; - // $elname = $this->_attributes['name']; - // $subdirs = $this->_options['subdirs']; - // $maxbytes = $this->_options['maxbytes']; - $draftitemid = $this->getValue(); - $accepted_types = $this->_options['accepted_types']; - - if (empty($draftitemid)) { - // No existing area info provided - let's use fresh new draft area. - require_once($CFG->libdir/filelib.php); - $this->setValue(file_get_unused_draft_itemid()); - $draftitemid = $this->getValue(); - } - - $client_id = uniqid(); - - // Filemanager options. - $options = new \stdClass(); - $options->mainfile = $this->_options['mainfile']; - $options->maxbytes = $this->_options['maxbytes']; - $options->maxfiles = $this->getMaxfiles(); - $options->client_id = $client_id; - $options->itemid = $draftitemid; - $options->subdirs = $this->_options['subdirs']; - $options->target = $id; - $options->accepted_types = $accepted_types; - $options->return_types = $this->_options['return_types']; - $options->context = $PAGE->context; - $options->areamaxbytes = $this->_options['areamaxbytes']; - - $class = $this->_options['class']; - - $fm = new form_filemanager($options); - - $return = ''; - $attachmentcount = count($fm->options->list); - $attachmentcount -= 1; - foreach ($fm->options->list as $list) { - $return .= \html_writer::start_tag('div', ['class' => $class]); - - // $return .= ''; - $return .= \html_writer::start_tag('a', ['title' => s($list->filename), 'href' => $list->url]); - $return .= \html_writer::empty_tag('img', ['src' => $list->thumbnail]); - $return .= \html_writer::end_tag('a'); - - // $return .= ''.s($list->filename).'
'; - $return .= \html_writer::start_tag('a', ['title' => s($list->filename), 'href' => $list->url]); - $return .= s($list->filename); - $return .= \html_writer::end_tag('a'); - - $return .= \html_writer::end_tag('div'); - } - - return $return; - } -} diff --git a/field/fileupload/tests/behat/submit_attachment.feature b/field/fileupload/tests/behat/submit_attachment.feature index a6ebc777d51..28c39cbbc1d 100644 --- a/field/fileupload/tests/behat/submit_attachment.feature +++ b/field/fileupload/tests/behat/submit_attachment.feature @@ -13,13 +13,13 @@ Feature: Submit using a fileupload item | username | firstname | lastname | email | | teacher1 | Teacher | teacher | teacher1@nowhere.net | | student1 | Student1 | user1 | student1@nowhere.net | + And the following "user preferences" exist: + | user | preference | value | + | teacher1 | htmleditor | textarea | And the following "course enrolments" exist: | user | course | role | | teacher1 | Attachment submission test | editingteacher | | student1 | Attachment submission test | student | - And the following "user preferences" exist: - | user | preference | value | - | teacher1 | htmleditor | textarea | And the following "activities" exist: | activity | name | intro | course | | surveypro | Attachment test | To test submission of attachment item | Attachment submission test | @@ -30,20 +30,22 @@ Feature: Submit using a fileupload item And I expand all fieldsets And I set the following fields to these values: - | Content | Please upload your CV | - | Required | 1 | - | Indent | 0 | - | Question position | left | + | Content | Upload your CV | + | Required | 1 | + | Indent | 0 | + | Question position | left | And I press "Add" And I log out # student1 logs in + When I am on the "Attachment test" "surveypro activity" page logged in as student1 And I press "New response" # student1 submits - And I upload "mod/surveypro/tests/fixtures/dummyCV.pdf" file to "Please upload your CV" filemanager + # And I pause scenario execution + And I upload "mod/surveypro/tests/fixtures/dummyCV.pdf" file to "Upload your CV" filemanager And I press "Submit" diff --git a/field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml b/field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml similarity index 90% rename from field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml rename to field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml index b1a805df5e9..3bfed02f075 100644 --- a/field/fileupload/tests/fixtures/usertemplate/attachment_only_2015123000.xml +++ b/field/fileupload/tests/fixtures/usertemplate/attachment_only_2024032800.xml @@ -1,49 +1,47 @@ - + + <h5>ATTACHMENT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with three <b>file upload specific setting</b>:</p><ol><li>Maximum files</li><li>Maximum file size</li><li>Allowed file types</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>ATTACHMENT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with three <b>file upload specific setting</b>:</p><ol><li>Maximum files</li><li>Maximum file size</li><li>Allowed file types</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + - 0 - 0 - 0 - - <p>Upload your CV, please.</p> 1 0 0 0 fileupload_001 + 0 + 0 + + 1 0 .pdf, .docx - + - 0 - 0 - 0 - - <p>Please, upload the menu of the next week using a specific file per each working day.</p> 1 0 0 0 fileupload_002 + 0 + 0 + + 5 512000 .pdf diff --git a/field/fileupload/version.php b/field/fileupload/version.php index 9e252ee3d07..91b6fe82326 100644 --- a/field/fileupload/version.php +++ b/field/fileupload/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2018060501; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_fileupload'; // Full name of the plugin (used for diagnostics). diff --git a/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php b/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php index d32a34f652f..622d6dbd6d1 100644 --- a/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php +++ b/field/integer/backup/moodle2/backup_surveyprofield_integer_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'integer'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugininteger = new backup_nested_element('surveyprofield_integer', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/integer/classes/item.php b/field/integer/classes/item.php index 4b3d93d6405..74f8a56e97a 100644 --- a/field/integer/classes/item.php +++ b/field/integer/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string Value of the default setting (invite, custom...) @@ -88,7 +48,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -102,6 +62,13 @@ class item extends itembase { */ protected $upperbound; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -135,7 +102,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -165,14 +134,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -184,7 +149,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -205,13 +170,7 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Integer (small)'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'integer_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; $record->lowerbound = 0; @@ -249,25 +208,107 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return the content of the static property "canbeparent" + * @return array $data */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_plugin_presets() { + $pluginproperties = ['defaultoption', 'defaultvalue', 'lowerbound', 'upperbound']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_integer'] = []; return $fieldlist; } @@ -284,29 +325,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + @@ -438,8 +460,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_integer_'.$this->sortindex; - // Begin of: element values. $integers = []; if (!$searchform) { @@ -456,17 +476,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: element values. - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' integer_select']; - $elementgroup = [$mform->createElement('select', $this->itemname, '', $integers, $attributes)]; - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false); + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_integer_'.$this->sortindex; + $basename = $this->itemname; + + $attributes = ['id' => $baseid]; + $elementgroup[] = $mform->createElement('select', $basename, '', $integers, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); + $attributes = ['id' => $baseid]; if (!$searchform) { if ($this->required) { // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } @@ -474,7 +501,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Default section. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); } else { switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: @@ -484,10 +511,10 @@ public function userform_mform_element($mform, $searchform, $readonly) { $defaultinteger = SURVEYPRO_NOANSWERVALUE; break; } - $mform->setDefault($this->itemname, "$defaultinteger"); + $mform->setDefault($basename, "$defaultinteger"); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } } @@ -501,7 +528,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } // This plugin displays as dropdown menu. It will never return empty values. @@ -520,14 +547,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_integernotset', 'surveyprofield_integer', $a); } - return; + return $errors; } $haslowerbound = ($this->lowerbound != 0); $hasupperbound = ($this->upperbound != $maximuminteger); if ($userinput == SURVEYPRO_NOANSWERVALUE) { - return; + return $errors; } if ($haslowerbound && $hasupperbound) { // Internal range. @@ -542,6 +569,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_integer'); } } + + return $errors; } /** @@ -652,8 +681,6 @@ public function userform_get_prefill($fromdb) { * @return array */ public function userform_get_root_elements_name() { - $elementnames = [$this->itemname.'_group']; - - return $elementnames; + return [$this->itemname.'_group']; } } diff --git a/field/integer/db/install.xml b/field/integer/db/install.xml index c8e19e68803..209e887f5e3 100644 --- a/field/integer/db/install.xml +++ b/field/integer/db/install.xml @@ -1,33 +1,17 @@ -
- - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/field/integer/db/upgrade.php b/field/integer/db/upgrade.php index e8cf700fc79..c78f1472b05 100644 --- a/field/integer/db/upgrade.php +++ b/field/integer/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'integer'); } @@ -64,7 +64,7 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2014090401, 'surveyprofield', 'integer'); } @@ -78,9 +78,70 @@ function xmldb_surveyprofield_integer_upgrade($oldversion) { $dbman->add_field($table, $field); } - // Fileupload savepoint reached. + // Integer savepoint reached. upgrade_plugin_savepoint(true, 2016072001, 'surveyprofield', 'integer'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_integer. + $table = new xmldb_table('surveyprofield_integer'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_integer} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Integer savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'integer'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_integer'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_integer. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_integer} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Integer savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'integer'); + } + return true; } diff --git a/field/integer/lang/en/surveyprofield_integer.php b/field/integer/lang/en/surveyprofield_integer.php index 94edfe04b1c..d8e346f0185 100644 --- a/field/integer/lang/en/surveyprofield_integer.php +++ b/field/integer/lang/en/surveyprofield_integer.php @@ -24,17 +24,18 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the integer the remote user will find answered by default. The default for this type of question is mandatory.'; $string['defaultoption'] = 'Default'; +$string['defaultoption_help'] = 'This is the integer the remote user will find answered by default. The default for this type of question is mandatory.'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; -$string['lowerbound_help'] = 'The lowest integer the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; -$string['maximuminteger_desc'] = 'The maximun integer this software will allow to ever enter'; +$string['lowerbound_help'] = 'The lowest integer the user is allowed to enter'; $string['maximuminteger'] = 'Maximum integer'; +$string['maximuminteger_desc'] = 'The maximun integer this software will allow to ever enter'; $string['parentformat'] = '[an integer]'; $string['pluginname'] = 'Integer'; +$string['privacy:metadata'] = 'The "Integer" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -43,7 +44,6 @@ $string['uerr_integernotsetrequired'] = 'Please choose a value'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest integer the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest integer the user is allowed to enter'; $string['userfriendlypluginname'] = 'Integer (small)'; -$string['privacy:metadata'] = 'The "Integer" field plugin does not store any personal data.'; diff --git a/field/integer/lang/it/surveyprofield_integer.php b/field/integer/lang/it/surveyprofield_integer.php index c5f55ce0101..b751dc1e7a0 100644 --- a/field/integer/lang/it/surveyprofield_integer.php +++ b/field/integer/lang/it/surveyprofield_integer.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['uerr_integernotsetrequired'] = 'Si selezioni un valore'; -$string['uerr_integernotset'] = 'Si selezioni un valore oppure l\'ultima voce: "{$a}"'; $string['restriction_lower'] = 'La risposta deve essere maggiore o uguale a {$a}'; $string['restriction_lowerupper'] = 'La risposta deve essere compresa fra {$a->lowerbound} e {$a->upperbound}'; $string['restriction_upper'] = 'La risposta deve essere minore o uguale a {$a}'; +$string['uerr_integernotset'] = 'Si selezioni un valore oppure l\'ultima voce: "{$a}"'; +$string['uerr_integernotsetrequired'] = 'Si selezioni un valore'; diff --git a/field/integer/tests/behat/itemform.feature b/field/integer/tests/behat/itemform.feature index ec353ed5610..016cd4450f6 100644 --- a/field/integer/tests/behat/itemform.feature +++ b/field/integer/tests/behat/itemform.feature @@ -87,5 +87,5 @@ Feature: Create an integer item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a How many people does your family counts?" - Then the field "id_surveypro_field_integer_2" matches value "5" + Then the field "id_field_integer_2" matches value "5" Then I should see "Additional note" diff --git a/field/integer/tests/behat/submit_integer.feature b/field/integer/tests/behat/submit_integer.feature index 41dede4af0d..3a2d7d36062 100644 --- a/field/integer/tests/behat/submit_integer.feature +++ b/field/integer/tests/behat/submit_integer.feature @@ -41,7 +41,7 @@ Feature: Submit using an integer item And I press "New response" # student1 submits - And I set the field "id_surveypro_field_integer_1" to "3" + And I set the field "id_field_integer_1" to "3" And I press "Submit" diff --git a/field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml b/field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml similarity index 88% rename from field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml rename to field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml index c7893ef0e86..802d11c11eb 100644 --- a/field/integer/tests/fixtures/usertemplate/integer_only_2015123000.xml +++ b/field/integer/tests/fixtures/usertemplate/integer_only_2024032800.xml @@ -1,155 +1,154 @@ - + + <h5>INTEGER</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>integer specific setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>INTEGER</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one <b>integer specific setting</b>:</p><ol><li>Default</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 1 0 0 - 1 - 0 + 1 integer_001 Include yourself in the count + 0 + 0 + 0 + + 2 + 0 1 19 - + + <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. + 1 + 0 + 2 info 0 0 0 - <ul><li>mandatory</li><li>input is lower limited to 1</li><li>input is upper limited to at least 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different value or select the "No answer" item. - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 1 0 0 - 2 - 0 + 1 integer_002b Include yourself in the count + 0 + 0 + 0 + + 1 + 0 1 19 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is upper limited to 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this item leaving the proposed default untouched (and the question not read) or select the "No answer" item. + 1 + 0 + 3 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is upper limited to 19</li><li>the default is set to 1 (to count the person filling the survey)</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this item leaving the proposed default untouched (and the question not read) or select the "No answer" item. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 0 0 0 - 3 - 0 + 1 integer_003 Include yourself in the count + 0 + 0 + 0 + + 1 1 1 19 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is lower limited to 1</li><li>input is limited to at least 19</li><li>the default invites the user to choose a value.</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>How many children do your parents have?</p> 1 0 0 0 - 4 - 0 + 1 integer_004 Include yourself in the count + 0 + 0 + 0 + + 2 + 0 1 19 diff --git a/field/integer/version.php b/field/integer/version.php index 98bb89361aa..a866d702863 100644 --- a/field/integer/version.php +++ b/field/integer/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_integer'; // Full name of the plugin (used for diagnostics). diff --git a/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php b/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php index b1ebea6458d..255b0e0297b 100644 --- a/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php +++ b/field/multiselect/backup/moodle2/backup_surveyprofield_multiselect_subplugin.class.php @@ -40,10 +40,9 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'multiselect'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginmultiselect = new backup_nested_element('surveyprofield_multiselect', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'options', 'defaultvalue', 'noanswerdefault', 'downloadformat', - 'minimumrequired', 'maximumrequired', 'heightinrows', ]); + 'minimumrequired', 'maximumrequired', 'heightinrows', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/multiselect/classes/item.php b/field/multiselect/classes/item.php index f14d60eacb7..91ecc49f76b 100644 --- a/field/multiselect/classes/item.php +++ b/field/multiselect/classes/item.php @@ -40,57 +40,27 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var string Name of the field storing data in the db table + * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" */ - protected $variable; + protected $options; /** - * @var int Indent of the item in the form page + * @var int Defaultvalue for the item answer */ - protected $indent; + protected $defaultvalue; /** - * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" + * @var string Format of the content once downloaded */ - protected $options; + protected $downloadformat; /** - * @var string Format of the content once downloaded + * @var string noanswerdefault */ - protected $downloadformat; + protected $noanswerdefault; /** * @var int Height of the multiselect in rows @@ -107,6 +77,13 @@ class item extends itembase { */ protected $maximumrequired; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -139,7 +116,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -169,18 +148,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -192,7 +167,7 @@ public function item_save($record) { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -216,17 +191,13 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Multiple selection'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'multiselect_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->defaultvalue + // $record->noanswerdefault $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->minimumrequired = 0; + // $record->maximumrequired $record->heightinrows = 4; } @@ -239,7 +210,7 @@ public function item_list_constraints() { $constraints = []; $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_multiselect'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -248,15 +219,141 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set noanswerdefault. + * + * @param string $noanswerdefault + * @return void + */ + public function set_noanswerdefault($noanswerdefault) { + $this->noanswerdefault = $noanswerdefault; + } + + /** + * Set heightinrows. + * + * @param string $heightinrows + * @return void + */ + public function set_heightinrows($heightinrows) { + $this->heightinrows = $heightinrows; + } + + /** + * Set minimumrequired. + * + * @param string $minimumrequired + * @return void + */ + public function set_minimumrequired($minimumrequired) { + $this->minimumrequired = $minimumrequired; + } + + /** + * Set maximumrequired. + * + * @param string $maximumrequired + * @return void + */ + public function set_maximumrequired($maximumrequired) { + $this->maximumrequired = $maximumrequired; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get noanswerdefault. * - * @return the content of the static property "canbeparent" + * @return $this->noanswerdefault */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_noanswerdefault() { + return $this->noanswerdefault; + } + + /** + * Get heightinrows. + * + * @return $this->heightinrows + */ + public function get_heightinrows() { + return $this->heightinrows; + } + + /** + * Get minimumrequired. + * + * @return $this->minimumrequired + */ + public function get_minimumrequired() { + return $this->minimumrequired; + } + + /** + * Get maximumrequired. + * + * @return $this->maximumrequired + */ + public function get_maximumrequired() { + return $this->maximumrequired; } /** @@ -283,14 +380,29 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'options', 'defaultvalue', 'noanswerdefault', 'downloadformat', 'minimumrequired', 'maximumrequired', 'heightinrows', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_multiselect'] = ['options', 'defaultvalue']; return $fieldlist; } @@ -316,32 +428,13 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + - + @@ -362,7 +455,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = array_fill(0, count($values), 0); $labels = []; @@ -400,7 +493,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { * return string $childparentcontent */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -449,7 +542,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optioncount = count($values); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -494,65 +587,65 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_multiselect_'.$this->sortindex; - - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' multiselect_select'; + $elementgroup = []; + $baseid = 'id_field_multiselect_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $basename = $this->itemname; + + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); + $attributes['id'] = $baseid; $attributes['size'] = $this->heightinrows; + + $select = $mform->createElement('select', $basename, '', $labels, $attributes); + $select->setMultiple(true); + $elementgroup[] = $select; + + unset($attributes['size']); // No longer needed. + if (!$searchform) { if ($this->required) { - $select = $mform->addElement('select', $this->itemname, $elementlabel, $labels, $attributes); - $select->setMultiple(true); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); } else { - $elementgroup = []; - $select = $mform->createElement('select', $this->itemname, '', $labels, $attributes); - $select->setMultiple(true); - $elementgroup[] = $select; - - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'multiselect_check'; - unset($attributes['size']); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '', false, $class); // Multiselect uses a special syntax - // that is different from the syntax of all the other mform groups with disabilitation chechbox. - // $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked');. - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_noanswer', 'checked'); + // that is different from all the other mform group with disabilitation chechbox syntax. + // $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked');. + $mform->disabledIf($basename.'[]', $basename.'_noanswer', 'checked'); } } else { - $elementgroup = []; - $select = $mform->createElement('select', $this->itemname, '', $labels, $attributes); - $select->setMultiple(true); - $elementgroup[] = $select; - - $attributes['class'] = 'multiselect_check'; - unset($attributes['size']); - if (!$this->required) { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); } - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'multiselect_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '
', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, '
', false, $class); if (!$this->required) { // Multiselect uses a special syntax - // that is different from the syntax of all the other mform groups with disabilitation chechbox. - // $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked');. - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_noanswer', 'checked'); + // that is different from all the other mform group with disabilitation chechbox syntax. + // $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked');. + $mform->disabledIf($basename.'[]', $basename.'_noanswer', 'checked'); + } + $mform->disabledIf($basename.'[]', $basename.'_ignoreme', 'checked'); + $mform->disabledIf($basename.'_noanswer', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); + } + + if (!$searchform) { + if ($this->required) { + // Even if the item is required I CAN NOT ADD ANY RULE HERE because... + // I do not want JS form validation if the page is submitted through the "previous" button. + // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. + // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; + $mform->_required[] = $starplace; } - $mform->disabledIf($this->itemname.'[]', $this->itemname.'_ignoreme', 'checked'); - $mform->disabledIf($this->itemname.'_noanswer', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); } // Begin of: defaults. @@ -562,16 +655,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { foreach ($defaults as $default) { $defaultkeys[] = array_search($default, $labels); } - $mform->setDefault($this->itemname, $defaultkeys); + $mform->setDefault($basename, $defaultkeys); } - $itemname = $this->itemname.'_noanswer'; if (!empty($this->noanswerdefault)) { - $mform->setDefault($itemname, '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } // End of: defaults. - // This last item is needed because the check for the not empty field is performed in the validation routine (not by JS). + // This last item is needed because the check for "not empty" field is performed in the validation routine (not by JS). // For multiselect element, nothing is submitted if no option is selected // so, if the user neglects the mandatory multiselect AT ALL, it is not submitted and, as conseguence, not validated. // TO ALWAYS SUBMIT A MULTISELECT I add a dummy hidden item. @@ -581,17 +673,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $placeholderitemname = SURVEYPRO_PLACEHOLDERPREFIX.'_'.$this->type.'_'.$this->plugin.'_'.$this->itemid; $mform->addElement('hidden', $placeholderitemname, 1); $mform->setType($placeholderitemname, PARAM_INT); - - if (!$searchform) { - if ($this->required) { - // Even if the item is required I CAN NOT ADD ANY RULE HERE because... - // I do not want JS form validation if the page is submitted through the "previous" button. - // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. - // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; - $mform->_required[] = $starplace; - } - } } /** @@ -604,13 +685,13 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (isset($data[$this->itemname.'_noanswer']) && ($data[$this->itemname.'_noanswer'] == 1) ) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } - $errorkey = $this->required ? $this->itemname : $this->itemname.'_group'; + $errorkey = $this->itemname.'_group'; // I don't care if this element is required or not. // If the user provides an answer, it has to be compliant with the field validation rules. @@ -631,6 +712,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum_more', 'surveyprofield_multiselect', $a); } } + + return $errors; } /** @@ -774,13 +857,13 @@ public function userform_get_user_answer($answer, &$olduseranswer, $searchform) } if (!isset($answer['mainelement'])) { // Only placeholder arrived here. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $olduseranswer->content = implode(SURVEYPRO_DBMULTICONTENTSEPARATOR, array_fill(1, count($labels), '0')); } else { // Here $answer is an array with the keys of the selected elements. $olduseranswer->content = implode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $answer['mainelement']); - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); $itemcount = count($labels); $contentarray = array_fill(0, $itemcount, 0); foreach ($answer['mainelement'] as $k) { @@ -860,7 +943,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); foreach ($answers as $k => $answer) { if ($answer == 1) { $output[] = $values[$k]; @@ -871,7 +954,7 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($answers as $k => $answer) { if ($answer == 1) { diff --git a/field/multiselect/db/install.xml b/field/multiselect/db/install.xml index 6bb2b0fb687..7ae6ec42f6e 100644 --- a/field/multiselect/db/install.xml +++ b/field/multiselect/db/install.xml @@ -1,36 +1,20 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/field/multiselect/db/upgrade.php b/field/multiselect/db/upgrade.php index b4a6eed4535..2ca244e7e99 100644 --- a/field/multiselect/db/upgrade.php +++ b/field/multiselect/db/upgrade.php @@ -148,5 +148,66 @@ function xmldb_surveyprofield_multiselect_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2023111401, 'surveyprofield', 'multiselect'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_multiselect. + $table = new xmldb_table('surveyprofield_multiselect'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_multiselect} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Multiselect savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'multiselect'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_multiselect'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_multiselect. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_multiselect} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Multiselect savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'multiselect'); + } + return true; } diff --git a/field/multiselect/lang/en/surveyprofield_multiselect.php b/field/multiselect/lang/en/surveyprofield_multiselect.php index 449d02bd07c..e24d94e9742 100644 --- a/field/multiselect/lang/en/surveyprofield_multiselect.php +++ b/field/multiselect/lang/en/surveyprofield_multiselect.php @@ -23,12 +23,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['defaultvalue'] = 'Default'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default'; $string['downloadformat'] = 'Download format'; -$string['heightinrows_help'] = 'The number of rows the multiselect will show'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['heightinrows'] = 'Height in rows'; +$string['heightinrows_help'] = 'The number of rows the multiselect will show'; $string['ierr_defaultsduplicated'] = 'Defaults must be different each other'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; $string['ierr_labelsduplicated'] = 'Options must be different each other'; @@ -37,21 +37,22 @@ $string['ierr_minimumrequired'] = 'The minimum number of items to select must be lower than {$a} (options count)'; $string['ierr_optionswithseparator'] = 'Options can not contain "{$a}"'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['maximumrequired_help'] = 'The maximum number of items the user can choose in his/her answer'; $string['maximumrequired'] = 'Maximum allowed options'; -$string['minimumrequired_help'] = 'The minimum number of items the user is forced to choose in his/her answer'; +$string['maximumrequired_help'] = 'The maximum number of items the user can choose in his/her answer'; $string['minimumrequired'] = 'Minimum required items'; -$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; +$string['minimumrequired_help'] = 'The minimum number of items the user is forced to choose in his/her answer'; $string['noanswerdefault'] = '"No answer" as defaults'; +$string['noanswerdefault_help'] = 'Use this option to include "No answer" among defaults'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the element list, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the element list, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[One
label
per
line]'; $string['pluginname'] = 'Multiple selection'; -$string['restrictions_maximumrequired_more'] = 'No more than {$a} items are allowed'; -$string['restrictions_maximumrequired_one'] = 'No more than 1 item is allowed'; -$string['restrictions_minimumrequired_more'] = 'At least {$a} items have to be selected'; -$string['restrictions_minimumrequired_one'] = 'At least 1 item has to be selected'; +$string['privacy:metadata'] = 'The "Multiselect" field plugin does not store any personal data.'; +$string['restrictions_maximumrequired_more'] = 'No more than {$a} options are allowed'; +$string['restrictions_maximumrequired_one'] = 'No more than 1 option is allowed'; +$string['restrictions_minimumrequired_more'] = 'At least {$a} options have to be selected'; +$string['restrictions_minimumrequired_one'] = 'At least 1 option has to be selected'; $string['returnlabels'] = 'label of selected items'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected items'; @@ -60,4 +61,3 @@ $string['uerr_lowerthanminimum_more'] = 'Please select at least {$a} options'; $string['uerr_lowerthanminimum_one'] = 'Please select at least 1 option'; $string['userfriendlypluginname'] = 'Multiple selection'; -$string['privacy:metadata'] = 'The "Multiselect" field plugin does not store any personal data.'; diff --git a/field/multiselect/tests/behat/itemform.feature b/field/multiselect/tests/behat/itemform.feature index 4320c312941..1b0263e28f1 100644 --- a/field/multiselect/tests/behat/itemform.feature +++ b/field/multiselect/tests/behat/itemform.feature @@ -88,5 +88,5 @@ Feature: Create a multiselect item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a What do you usually get for breakfast?" - Then the field "id_surveypro_field_multiselect_2" matches value "coffee, bread" + Then the field "id_field_multiselect_2" matches value "coffee, bread" Then I should see "Additional note" diff --git a/field/multiselect/tests/behat/settings_configuration_01.feature b/field/multiselect/tests/behat/settings_configuration_01.feature index 5f1923a6a56..30d25a7567f 100644 --- a/field/multiselect/tests/behat/settings_configuration_01.feature +++ b/field/multiselect/tests/behat/settings_configuration_01.feature @@ -56,7 +56,7 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -65,7 +65,7 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 | milk, bread | + | id_field_multiselect_1 | milk, bread | | No answer | 1 | And I press "Submit" And I press "Continue to responses list" @@ -94,13 +94,13 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 4: Student flies over the answer And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -108,8 +108,8 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 5: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -117,10 +117,10 @@ Feature: Submit using multiselect item and check form validation (1 of 4) # Test number 6: Student chooses "No answer" And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 |milk, bread | - | No answer | 1 | + | id_field_multiselect_1 |milk, bread | + | No answer | 1 | And I press "Submit" And I press "Continue to responses list" Then I should see "3" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_02.feature b/field/multiselect/tests/behat/settings_configuration_02.feature index 361a8188854..7e1d645ae84 100644 --- a/field/multiselect/tests/behat/settings_configuration_02.feature +++ b/field/multiselect/tests/behat/settings_configuration_02.feature @@ -56,7 +56,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -65,7 +65,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 3: Student chooses "No answer" And I press "New response" And I set the following fields to these values: - | id_surveypro_field_multiselect_1 |milk, bread | + | id_field_multiselect_1 |milk, bread | | No answer | 1 | And I press "Submit" And I press "Continue to responses list" @@ -94,10 +94,10 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 4: Student flies over the answer And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -105,8 +105,8 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 5: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -114,7 +114,7 @@ Feature: Submit using multiselect item and check form validation (2 of 4) # Test number 6: Student chooses "No answer" And I press "New response" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I set the field "No answer" to "1" And I press "Submit" And I press "Continue to responses list" diff --git a/field/multiselect/tests/behat/settings_configuration_03.feature b/field/multiselect/tests/behat/settings_configuration_03.feature index 522b8079645..818b11f3b6a 100644 --- a/field/multiselect/tests/behat/settings_configuration_03.feature +++ b/field/multiselect/tests/behat/settings_configuration_03.feature @@ -57,7 +57,7 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -86,13 +86,13 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 3: Student flies over the answer And I press "New response" Then I should not see "No answer" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,7 +100,7 @@ Feature: Submit using multiselect item and check form validation (3 of 4) # Test number 4: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_04.feature b/field/multiselect/tests/behat/settings_configuration_04.feature index 2b9e2f2368a..0c57e9af92f 100644 --- a/field/multiselect/tests/behat/settings_configuration_04.feature +++ b/field/multiselect/tests/behat/settings_configuration_04.feature @@ -57,7 +57,7 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 2: Student submits a standard answer And I press "New response" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions @@ -86,13 +86,13 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 3: Student flies over the answer And I press "New response" Then I should not see "No answer" - Then I should see "At least 2 items have to be selected" + Then I should see "At least 2 options have to be selected" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk" + And I set the field "id_field_multiselect_1" to "milk" And I press "Submit" Then I should see "Please select at least 2 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, bread" + And I set the field "id_field_multiselect_1" to "milk, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -100,8 +100,8 @@ Feature: Submit using multiselect item and check form validation (4 of 4) # Test number 4: Student submits a standard answer And I press "New response" - Then I should see "At least 2 items have to be selected" - And I set the field "id_surveypro_field_multiselect_1" to "bread, coffee" + Then I should see "At least 2 options have to be selected" + And I set the field "id_field_multiselect_1" to "bread, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/behat/settings_configuration_05.feature b/field/multiselect/tests/behat/settings_configuration_05.feature index 2f0fdc828b5..5ec1414ea78 100644 --- a/field/multiselect/tests/behat/settings_configuration_05.feature +++ b/field/multiselect/tests/behat/settings_configuration_05.feature @@ -39,7 +39,7 @@ Feature: Submit using multiselect item and check form validation # Test number 1: Student submits a standard answer And I press "New response" Then I should not see "No more than" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee" + And I set the field "id_field_multiselect_1" to "milk, coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -59,11 +59,11 @@ Feature: Submit using multiselect item and check form validation # Test number 2: Student ticks too many items And I press "New response" - Then I should see "No more than 3 items are allowed" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee, butter, bread" + Then I should see "No more than 3 options are allowed" + And I set the field "id_field_multiselect_1" to "milk, coffee, butter, bread" And I press "Submit" Then I should see "Please tick no more than 3 options" - And I set the field "id_surveypro_field_multiselect_1" to "milk, coffee, bread" + And I set the field "id_field_multiselect_1" to "milk, coffee, bread" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions @@ -71,8 +71,8 @@ Feature: Submit using multiselect item and check form validation # Test number 3: Student submits a standard answer And I press "New response" - Then I should see "No more than 3 items are allowed" - And I set the field "id_surveypro_field_multiselect_1" to "coffee" + Then I should see "No more than 3 options are allowed" + And I set the field "id_field_multiselect_1" to "coffee" And I press "Submit" And I press "Continue to responses list" Then I should see "2" submissions diff --git a/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml b/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml similarity index 87% rename from field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml rename to field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml index d8d5bf6fe00..9cd5bfdade2 100644 --- a/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2015123000.xml +++ b/field/multiselect/tests/fixtures/usertemplate/multiselect_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>MULTISELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some<b>multiple selection specific setting</b>:</p><ol><li>Options</li><li>Default</li><li>Height in rows</li><li>Minimum required items</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>MULTISELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some<b>multiple selection specific setting</b>:</p><ol><li>Options</li><li>Default</li><li>Height in rows</li><li>Minimum required items</li><li>Download format</li></ol><p>and with one <b>validation options</b></p><ol><li>Minimum required options</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least one item. + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least one item. - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 1 - 0 + 1 multiselect_001 + 0 + 0 + 0 + + milk sugar jam @@ -53,35 +52,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 2 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 2 - 0 + 1 multiselect_002 + 0 + 0 + 0 + + milk sugar jam @@ -95,35 +93,34 @@ jam 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least one item or to select the "No answer" checkbox. + 1 + 0 + 3 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least one item or to select the "No answer" checkbox. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 3 - 0 + 1 multiselect_003 + 0 + 0 + 0 + + milk sugar jam @@ -135,35 +132,34 @@ chocolate 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 4 - 0 + 1 multiselect_004 + 0 + 0 + 0 + + milk sugar jam @@ -176,35 +172,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least two items. + 1 + 0 + 5 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is not set so the user is forced to select at least two items. - 1 - 0 - 5 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 5 - 0 + 1 multiselect_005 + 0 + 0 + 0 + + milk sugar jam @@ -216,36 +211,34 @@ chocolate 3 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value but the user can not "fly" over this element because the minimum required options is set to 2.<br /> + 1 + 0 + 6 info 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>a default is set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is mandatory and the default is set so to a valid value but the user can not "fly" over this element because the minimum -required options is set to 2.<br /> - 1 - 0 - 6 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 1 0 0 - 6 - 0 + 1 multiselect_006 + 0 + 0 + 0 + + milk sugar jam @@ -259,35 +252,34 @@ jam 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least two items or to select the "No answer" checkbox. + 1 + 0 + 7 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is not set</li><li>minimum required is set to 2<br /></li></ul>Behaviour: The item is not mandatory and the default is not set so the user is forced to select at least two items or to select the "No answer" checkbox. - 1 - 0 - 7 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 7 - 0 + 1 multiselect_007 + 0 + 0 + 0 + + milk sugar jam @@ -299,35 +291,34 @@ chocolate 3 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. + 1 + 0 + 8 info 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>a default is set</li><li>minimum required is (automatically) set to 1<br /></li></ul>Behaviour: The item is not mandatory and the default is set but so the user is forced to select at least one item. - 1 - 0 - 8 info 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 0 0 - 8 - 0 + 1 multiselect_008 + 0 + 0 + 0 + + milk sugar jam diff --git a/field/multiselect/version.php b/field/multiselect/version.php index fdf57da80d1..1dfcca3f7d9 100644 --- a/field/multiselect/version.php +++ b/field/multiselect/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023111401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_multiselect'; // Full name of the plugin (used for diagnostics). diff --git a/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php b/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php index 6f327472a5a..7910f852293 100644 --- a/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php +++ b/field/numeric/backup/moodle2/backup_surveyprofield_numeric_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'numeric'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginnumeric = new backup_nested_element('surveyprofield_numeric', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals', ]); + 'defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/numeric/classes/item.php b/field/numeric/classes/item.php index 076584ab52f..877bd4af124 100644 --- a/field/numeric/classes/item.php +++ b/field/numeric/classes/item.php @@ -40,82 +40,46 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH + * @var int Defaultvalue for the item answer */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; + protected $defaultvalue; /** - * @var bool 0 => optional item; 1 => mandatory item; + * @var bool Is the number signed? */ - protected $required; + protected $signed; /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var int Number lowerbound */ - protected $hideinstructions; + protected $lowerbound; /** - * @var string Name of the field storing data in the db table + * @var int Number upperbound */ - protected $variable; + protected $upperbound; /** - * @var int Indent of the item in the form page + * @var int Number of decimals allowed for this number */ - protected $indent; + protected $decimals; - /** - * @var string Value of the field when the form is initially displayed - */ - protected $defaultvalue; + // Service variables. /** * @var string Decimal separator */ protected $decimalseparator; - /** - * @var bool Is the number signed? - */ - protected $signed; - - /** - * @var int Number lowerbound - */ - protected $lowerbound; - - /** - * @var int Number upperbound - */ - protected $upperbound; + // Service variables. /** - * @var int Number of decimals allowed for this number + * @var bool Does this item use the child table surveypro(field|format)_plugin? */ - protected $decimals; + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -149,7 +113,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -181,14 +147,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -201,15 +163,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Numeric'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'numeric_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + // $record->defaultvalue $record->signed = 0; + // $record->lowerbound + // $record->upperbound $record->decimals = 0; } @@ -223,12 +181,12 @@ public function item_custom_fields_to_form() { // Nothing to do: they don't exist in this plugin. // 2. float numbers need more attention because I can write them using , or . - if (core_text::strlen($this->defaultvalue)) { - $this->defaultvalue = format_float($this->defaultvalue, $this->decimals); + $numericfields = ['defaultvalue', 'lowerbound', 'upperbound']; + foreach ($numericfields as $numericfield) { + if (core_text::strlen($this->{$numericfield})) { + $this->{$numericfield} = format_float($this->{$numericfield}, $this->decimals); + } } - // Note: $this->lowerbound and $this->upperbound comes from db and are correctly written. - // I am not going to put them in a field so I can leave them well written... - // ...instead of changing them according to the local language. } /** @@ -237,7 +195,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -249,39 +207,139 @@ public function item_custom_fields_to_db($record) { // Nothing to do: no checkboxes in this plugin item form. // 4. Other: float numbers need more attention because I can write them using , or . - if (core_text::strlen($record->defaultvalue)) { - $record->defaultvalue = $this->get_international_number($record->defaultvalue); - } else { - $record->defaultvalue = null; - } - if (core_text::strlen($record->lowerbound)) { - $record->lowerbound = $this->get_international_number($record->lowerbound); - } else { - $record->lowerbound = null; - } - if (core_text::strlen($record->upperbound)) { - $record->upperbound = $this->get_international_number($record->upperbound); - } else { - $record->upperbound = null; + $numericfields = ['defaultvalue', 'lowerbound', 'upperbound']; + foreach ($numericfields as $numericfield) { + if (core_text::strlen($record->{$numericfield})) { + $record->{$numericfield} = $this->get_international_number($record->{$numericfield}); + } else { + $record->{$numericfield} = null; + } } } + // MARK set. + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set signed. + * + * @param string $signed + * @return void + */ + public function set_signed($signed) { + $this->signed = $signed; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set decimals. + * + * @param string $decimals + * @return void + */ + public function set_decimals($decimals) { + $this->decimals = $decimals; + } + + /** + * Set decimalseparator. + * + * @param string $decimalseparator + * @return void + */ + public function set_decimalseparator($decimalseparator) { + $this->decimalseparator = $decimalseparator; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get signed. + * + * @return $this->signed + */ + public function get_signed() { + return $this->signed; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get decimals. + * + * @return $this->decimals + */ + public function get_decimals() { + return $this->decimals; + } + + /** + * Get decimalseparator. * - * @return the content of the static property "canbeparent" + * @return $this->decimalseparator */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_decimalseparator() { + return $this->decimalseparator; } /** * Get the requested property. * * @param string $field - * @return the content of the field or false if the field is not set. + * @return the content of the field or false if it is not set. */ public function get_generic_property($field) { if (isset($this->{$field})) { @@ -292,7 +350,8 @@ public function get_generic_property($field) { if ($condition) { $return = $this->get_international_number($this->{$field}); } else { - $return = $this->{$field}; + $method = 'get_'.$field; + $return = $this->{$method}(); } } else { $return = false; @@ -303,32 +362,52 @@ public function get_generic_property($field) { /** * get_international_number - * starting from justanumber written using local decimal separator, + * starting from localnumber written using local decimal separator, * this function returns the same number written using the dot as decimal separator. * - * @param double $localnumber + * @param double|bool $localnumber false in case of error * @return void or double $internationalnumber */ public function get_international_number($localnumber) { $localnumber = trim($localnumber); - $internationalnumber = str_replace($this->decimalseparator, '.', $localnumber); - if (is_numeric($internationalnumber)) { - $return = $internationalnumber; - } else { + $condition = ($this->decimals > 0); + $condition = $condition && (strpos($localnumber, $this->decimalseparator) === false); + if ($condition) { $return = false; + } else { + // It does not matter if $this->decimalseparator is not onboard. It could be. + $internationalnumber = str_replace($this->decimalseparator, '.', $localnumber); + if (is_numeric($internationalnumber)) { + $return = $internationalnumber; + } else { + $return = false; + } } return $return; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultvalue', 'signed', 'lowerbound', 'upperbound', 'decimals']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_numeric'] = []; return $fieldlist; } @@ -345,30 +424,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - + @@ -396,21 +456,24 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_numeric_'.$this->sortindex; - $attributes = []; - $attributes['id'] = $idprefix; - $attributes['class'] = 'indent-'.$this->indent.' numeric_text'; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_numeric_'.$this->sortindex; + $basename = $this->itemname; + $attributes['id'] = $baseid; // Cool for browsers supporting html 5. // $attributes['type'] = 'number'; // But it doesn't work because "type" property is reserved to mform library. if (!$searchform) { - $mform->addElement('text', $this->itemname, $elementlabel, $attributes); - $mform->setType($this->itemname, PARAM_RAW); // See: moodlelib.php lines 133+. + $elementgroup[] = $mform->createElement('text', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename, PARAM_RAW); // See: moodlelib.php lines 133+. + if (core_text::strlen($this->defaultvalue)) { - $mform->setDefault($this->itemname, "$this->defaultvalue"); + $mform->setDefault($basename, "$this->defaultvalue"); } if ($this->required) { @@ -418,22 +481,18 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('text', $this->itemname, '', $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $itemname = $this->itemname.'_ignoreme'; - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'numeric_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $elementgroup[] = $mform->createElement('text', $basename, '', $attributes); + $mform->setType($basename, PARAM_RAW); + + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } @@ -447,24 +506,25 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } - $errorkey = $this->itemname; + $errorkey = $this->itemname.'_group'; $draftuserinput = $data[$this->itemname]; if (!core_text::strlen($draftuserinput)) { if (!empty($this->required)) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } $userinput = $this->get_international_number($draftuserinput); + if (!is_numeric($userinput)) { // It is not a number, shouts. $errors[$errorkey] = get_string('uerr_notanumber', 'surveyprofield_numeric'); - return; + return $errors; } else { // If it is < 0 but has been defined as unsigned, shouts. if (!$this->signed && ($userinput < 0)) { @@ -503,6 +563,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_numeric'); } } + + return $errors; } /** @@ -615,13 +677,4 @@ public function userform_get_root_elements_name() { return $elementnames; } - - /** - * Does the user input need trim? - * - * @return if this plugin requires a user input trim - */ - public static function userform_input_needs_trim() { - return true; - } } diff --git a/field/numeric/db/install.xml b/field/numeric/db/install.xml index a30fada2cdd..109fd7f4cc1 100644 --- a/field/numeric/db/install.xml +++ b/field/numeric/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/numeric/db/upgrade.php b/field/numeric/db/upgrade.php index 48eb38db66d..7533742b7d9 100644 --- a/field/numeric/db/upgrade.php +++ b/field/numeric/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_numeric_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Numeric savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'numeric'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_numeric. + $table = new xmldb_table('surveyprofield_numeric'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_numeric} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Numeric savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'numeric'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_numeric'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_numeric. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_numeric} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Numeric savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'numeric'); + } + return true; } diff --git a/field/numeric/lang/en/surveyprofield_numeric.php b/field/numeric/lang/en/surveyprofield_numeric.php index 2929f21162b..7ae0eedfec0 100644 --- a/field/numeric/lang/en/surveyprofield_numeric.php +++ b/field/numeric/lang/en/surveyprofield_numeric.php @@ -25,11 +25,11 @@ $string['allowed'] = 'allowed'; $string['decimalautofix'] = 'exceeding or missing decimals will be dropped out or filled with zeroes'; -$string['decimals_help'] = 'The number of decimals places of the request number'; $string['decimals'] = 'Decimal positions'; +$string['decimals_help'] = 'The number of decimals places of the request number'; $string['declaredecimalseparator'] = 'decimal separator is supposed to be \'{$a}\''; -$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default. Blank to leave default unassigned.'; $string['defaultvalue'] = 'Default'; +$string['defaultvalue_help'] = 'This is the value the remote user will find answered by default. Blank to leave default unassigned.'; $string['ierr_default_notinteger'] = 'Default is not an integer'; $string['ierr_default_outofrange'] = 'Default does not fall within the specified range'; $string['ierr_defaultsignnotallowed'] = 'Default is supposed to be unsigned'; @@ -39,25 +39,25 @@ $string['ierr_notanumber'] = 'This is not a number'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['ierr_uppernegative'] = 'Upper bound is supposed to be unsigned'; -$string['lowerbound_help'] = 'The minimum allowed value. Blank to leave minimum unassigned.'; $string['lowerbound'] = 'Minimum value'; +$string['lowerbound_help'] = 'The minimum allowed value. Blank to leave minimum unassigned.'; $string['number'] = 'Number '; $string['pluginname'] = 'Numeric'; -$string['restriction_hasdecimals'] = 'is supposed to have {$a} decimal positions'; +$string['privacy:metadata'] = 'The "Numeric" field plugin does not store any personal data.'; +$string['restriction_hasdecimals'] = 'it is supposed to have {$a} decimal positions'; $string['restriction_hassign'] = 'can be negative'; -$string['restriction_isinteger'] = 'is supposed to be an integer'; +$string['restriction_isinteger'] = 'it is supposed to be an integer'; $string['restriction_lower'] = 'Answer is supposed be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed be lower-equal than {$a}'; -$string['signed_help'] = 'Is the expected number supposed to be signed?'; $string['signed'] = 'Signed value'; +$string['signed_help'] = 'Is the expected number supposed to be signed?'; $string['uerr_greaterthanmaximum'] = 'Provided value is greater than maximum allowed'; $string['uerr_lowerthanminimum'] = 'Provided value is lower than minimum allowed'; $string['uerr_negative'] = 'Provided value is supposed to be unsigned'; $string['uerr_notanumber'] = 'Provided value is not a number'; $string['uerr_notinteger'] = 'Provided value is supposed to be integer'; $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; -$string['upperbound_help'] = 'The biggest number the user is allowed to enter.'; $string['upperbound'] = 'Maximum value'; +$string['upperbound_help'] = 'The biggest number the user is allowed to enter.'; $string['userfriendlypluginname'] = 'Numeric'; -$string['privacy:metadata'] = 'The "Numeric" field plugin does not store any personal data.'; diff --git a/field/numeric/tests/behat/itemform.feature b/field/numeric/tests/behat/itemform.feature index 86e729acdb9..9584664507b 100644 --- a/field/numeric/tests/behat/itemform.feature +++ b/field/numeric/tests/behat/itemform.feature @@ -87,5 +87,5 @@ Feature: Create a numeric item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Type the best approximation of π you know" - Then the field "id_surveypro_field_numeric_2" matches value "3.14" + Then the field "id_field_numeric_2" matches value "3.14" Then I should see "Additional note" diff --git a/field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml b/field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml similarity index 84% rename from field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml rename to field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml index 73262741681..14da0541a47 100644 --- a/field/numeric/tests/fixtures/usertemplate/numeric_only_2015123000.xml +++ b/field/numeric/tests/fixtures/usertemplate/numeric_only_2024032800.xml @@ -1,157 +1,153 @@ - + + <h5>NUMERIC</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one<b> </b><b>numeric specific setting</b>:</p><ol><li>Default</li></ol><p>and with some more <b>validation options</b></p><ol><li>Signed value</li><li>Decimal positions</li><li>Minimum value</li><li>Maximum value</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>NUMERIC</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only one<b> </b><b>numeric specific setting</b>:</p><ol><li>Default</li></ol><p>and with some more <b>validation options</b></p><ol><li>Signed value</li><li>Decimal positions</li><li>Minimum value</li><li>Maximum value</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 1 info 0 0 0 - <ul><li>mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 1 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 1 0 0 - 1 - 0 + 1 numeric_001 - 3.1 + 0 + 0 + 0 + + + 3.1000 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>not mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or blank the field. + 1 + 0 + 2 info 0 0 0 - <ul><li>not mandatory</li><li>default is set to 3.1</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or blank the field. - 1 - 0 - 2 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 0 0 0 - 2 - 0 + 1 numeric_002 - 3.1 + 0 + 0 + 0 + + + 3.1000 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory but the default is unset. The user will be forced to choose a value. + 1 + 0 + 3 info 0 0 0 - <ul><li>mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is mandatory but the default is unset. The user will be forced to choose a value. - 1 - 0 - 3 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 1 0 0 - 3 - 0 + 1 numeric_003 + 0 + 0 + 0 + + 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 - + + <ul><li>not mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 4 info 0 0 0 - <ul><li>not mandatory</li><li>default is not set</li><li>decimal positions set to 4</li><li>minimum value set to 3.1</li><li>maximum value set to 3.2</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 4 info 0 - + - 0 - 0 - 0 - - <p>Type the best approximation of π you know.</p> 1 0 0 0 - 4 - 0 + 1 numeric_004 + 0 + 0 + 0 + + 0 - 3.1 - 3.2 + 3.1000000000 + 3.2000000000 4 diff --git a/field/numeric/version.php b/field/numeric/version.php index 3bc0801fca9..642ae66ba6a 100644 --- a/field/numeric/version.php +++ b/field/numeric/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_numeric'; // Full name of the plugin (used for diagnostics). diff --git a/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php b/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php index 6988434c917..ac7e01b435c 100644 --- a/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php +++ b/field/radiobutton/backup/moodle2/backup_surveyprofield_radiobutton_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'radiobutton'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginradiobutton = new backup_nested_element('surveyprofield_radiobutton', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment', ]); + 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/radiobutton/classes/item.php b/field/radiobutton/classes/item.php index b04e1b1d6bb..a8599398f24 100644 --- a/field/radiobutton/classes/item.php +++ b/field/radiobutton/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -88,17 +48,17 @@ class item extends itembase { protected $options; /** - * @var string Value of the default setting (invite, custom...) + * @var string Text label for the optional option "other" in the form of "$value SURVEYPRO_OTHERSEPARATOR $label" */ - protected $defaultoption; + protected $labelother; /** - * @var string Text label for the optional option "other" in the form of "$value SURVEYPRO_OTHERSEPARATOR $label" + * @var string Value of the default setting (invite, custom...) */ - protected $labelother; + protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -112,6 +72,13 @@ class item extends itembase { */ protected $adjustment; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -144,7 +111,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -176,18 +145,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim trialing spaces from each row of each textarea field. $fieldlist = ['options']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -200,15 +165,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Radio buttons'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'radiobutton_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->labelother $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->adjustment = SURVEYPRO_VERTICAL; } @@ -229,7 +190,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -253,7 +214,7 @@ public function item_list_constraints() { $constraints = []; $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_radiobutton'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -267,15 +228,122 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set adjustment. + * + * @param string $adjustment + * @return void + */ + public function set_adjustment($adjustment) { + $this->adjustment = $adjustment; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. + * + * @return $this->labelother + */ + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get adjustment. + * + * @return $this->adjustment + */ + public function get_adjustment() { + return $this->adjustment; } /** @@ -302,14 +370,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', 'adjustment']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_radiobutton'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -335,31 +416,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - + + @@ -380,7 +442,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = []; $labels = []; @@ -418,7 +480,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -464,7 +526,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -507,61 +569,45 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_radiobutton_'.$this->sortindex; - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' radiobutton_radio'; - $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_radiobutton_'.$this->sortindex; + $basename = $this->itemname; // Begin of: mform element. if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { - $attributes['id'] = $idprefix.'_invite'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_invite'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $choosedotsstr, SURVEYPRO_INVITEVALUE, $attributes); } } else { - $attributes['id'] = $idprefix.'_ignoreme'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $starsstr, SURVEYPRO_IGNOREMEVALUE, $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $starsstr, SURVEYPRO_IGNOREMEVALUE, $attributes); } - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); foreach ($labels as $k => $label) { - $attributes['id'] = $idprefix.'_'.$k; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', $label, "$k", $attributes); - if ($this->adjustment == SURVEYPRO_HORIZONTAL) { - $attributes['class'] = 'radiobutton_radio'; - } + $attributes['id'] = $baseid.'_'.$k; + $elementgroup[] = $mform->createElement('radio', $basename, '', $label, "$k", $attributes); } if (!empty($this->labelother)) { [$othervalue, $otherlabel] = $this->get_other(); $labels['other'] = $otherlabel; - $attributes['id'] = $idprefix.'_other'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $otherlabel, 'other', $attributes); + $attributes['id'] = $baseid.'_other'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $otherlabel, 'other', $attributes); - $attributes['id'] = $idprefix.'_text'; - $attributes['class'] = 'radiobutton_radio'; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); - $mform->disabledIf($this->itemname.'_text', $this->itemname, 'neq', 'other'); + $attributes['id'] = $baseid.'_text'; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); + $mform->disabledIf($basename.'_text', $basename, 'neq', 'other'); } if (!$this->required) { - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'indent-'.$this->indent.' radiobutton_radio'; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $this->itemname, '', - $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('radio', $basename, '', $noanswerstr, SURVEYPRO_NOANSWERVALUE, $attributes); } // End of: mform element. @@ -573,7 +619,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: definition of separator. - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); // Begin of: default section. if (!$searchform) { @@ -582,7 +628,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -590,25 +636,25 @@ public function userform_mform_element($mform, $searchform, $readonly) { case SURVEYPRO_CUSTOMDEFAULT: $key = array_search($this->defaultvalue, $labels); if ($key !== false) { - $mform->setDefault($this->itemname, "$key"); + $mform->setDefault($basename, "$key"); } break; case SURVEYPRO_INVITEDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_NOANSWERVALUE); + $mform->setDefault($basename, SURVEYPRO_NOANSWERVALUE); break; default: $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } - // Note: $this->itemname.'_text' has to ALWAYS get a default (if it exists) even if it is not selected. + // Note: $basename.'_text' has to ALWAYS get a default (if it exists) even if it is not selected. if (!empty($this->labelother)) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); } // End of: default section. } @@ -619,7 +665,8 @@ public function userform_mform_element($mform, $searchform, $readonly) { * @return array $separator */ public function userform_get_separator(): array { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); + $optioncount = count($labels); $invitation = ($this->defaultoption == SURVEYPRO_INVITEDEFAULT); $addother = !empty($this->labelother); @@ -680,21 +727,22 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } $errorkey = $this->itemname.'_group'; if ( ($data[$this->itemname] == 'other') && empty($data[$this->itemname.'_text']) ) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_radiobutton'); - return; + return $errors; } // I need to check value is different from SURVEYPRO_INVITEVALUE even if it is not required. if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_optionnotset', 'surveyprofield_radiobutton'); - return; } + + return $errors; } /** @@ -807,7 +855,7 @@ public function userform_get_prefill($fromdb) { } if (isset($fromdb->content)) { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($fromdb->content, $labels)) { $prefill[$this->itemname] = $fromdb->content; } else { @@ -852,7 +900,7 @@ public function userform_db_to_export($answer, $format='') { // Output. switch ($format) { case SURVEYPRO_ITEMSRETURNSVALUES: - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -860,7 +908,7 @@ public function userform_db_to_export($answer, $format='') { } break; case SURVEYPRO_ITEMRETURNSLABELS: - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -888,4 +936,24 @@ public function userform_get_root_elements_name() { return $elementnames; } + + // MARK other. + + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } } diff --git a/field/radiobutton/classes/itemsetupform.php b/field/radiobutton/classes/itemsetupform.php index 56c984b5570..617263a2ecc 100644 --- a/field/radiobutton/classes/itemsetupform.php +++ b/field/radiobutton/classes/itemsetupform.php @@ -86,7 +86,6 @@ public function definition() { // Item: defaultvalue. $fieldname = 'defaultvalue'; - $elementgroup = []; $mform->addElement('text', $fieldname, ''); $mform->disabledIf($fieldname, 'defaultoption', 'neq', SURVEYPRO_CUSTOMDEFAULT); $mform->setType($fieldname, PARAM_RAW); @@ -166,6 +165,10 @@ public function validation($data, $files) { if (count($values) != count($arrayunique)) { $errors['options'] = get_string('ierr_valuesduplicated', 'surveyprofield_radiobutton'); } + // A single option is not allowed. + if (count($arrayunique) == 1) { + $errors['options'] = get_string('ierr_singleoption', 'surveyprofield_radiobutton'); + } // Each single label has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { diff --git a/field/radiobutton/db/install.xml b/field/radiobutton/db/install.xml index 333829bbf39..0cb502e502c 100644 --- a/field/radiobutton/db/install.xml +++ b/field/radiobutton/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/radiobutton/db/upgrade.php b/field/radiobutton/db/upgrade.php index f12d0ff9e1d..45261971031 100644 --- a/field/radiobutton/db/upgrade.php +++ b/field/radiobutton/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_radiobutton_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Radiobutton savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'radiobutton'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_radiobutton. + $table = new xmldb_table('surveyprofield_radiobutton'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_radiobutton} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Radiobutton savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'radiobutton'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_radiobutton'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_radiobutton. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_radiobutton} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Radiobutton savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'radiobutton'); + } + return true; } diff --git a/field/radiobutton/lang/en/surveyprofield_radiobutton.php b/field/radiobutton/lang/en/surveyprofield_radiobutton.php index 566a6abb490..c3ce45f290c 100644 --- a/field/radiobutton/lang/en/surveyprofield_radiobutton.php +++ b/field/radiobutton/lang/en/surveyprofield_radiobutton.php @@ -23,26 +23,28 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['adjustment'] = 'Adjustment'; +$string['adjustment_help'] = 'How this list of items will be shown? In horizontal or in vertical?'; $string['allowed'] = 'allowed'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['horizontal'] = 'horizontal'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; -$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_labelsduplicated'] = 'Labels must be different each other'; +$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; +$string['ierr_singleoption'] = 'A single option is not allowed'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding radio button, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed close to the corresponding radio button, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[label]'; $string['pluginname'] = 'Radio button'; +$string['privacy:metadata'] = 'The "Radio button" field plugin does not store any personal data.'; $string['returnlabels'] = 'label of selected items'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected items'; @@ -50,4 +52,3 @@ $string['uerr_optionnotset'] = 'Please choose an option'; $string['userfriendlypluginname'] = 'Radio buttons'; $string['vertical'] = 'vertical'; -$string['privacy:metadata'] = 'The "Radio button" field plugin does not store any personal data.'; diff --git a/field/radiobutton/mform/radiobutton.php b/field/radiobutton/mform/radiobutton.php deleted file mode 100644 index c15ba2a7624..00000000000 --- a/field/radiobutton/mform/radiobutton.php +++ /dev/null @@ -1,85 +0,0 @@ -. - -/** - * radio mform element - * - * Extends the core mform class for a radio type element - * - * @package surveyprofield_radiobutton - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -global $CFG; - -require_once($CFG->libdir.'/form/radio.php'); - -// @codingStandardsIgnoreFile - -/** - * radio form element - * - * HTML class for a radio type element - * - * @package surveyprofield_radiobutton - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_radiobutton extends \MoodleQuickForm_radio { - - /** - * Class constructor. - * - * @param string $elementName Optional name of the radio element - * @param string $elementLabel Optional label for radio element - * @param string $text Optional Text to put after the radio element - * @param string $value Optional default value - * @param mixed $attributes Optional Either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $text, $value, $attributes); - } - - /** - * Slightly different container template when frozen. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns the disabled field. Accessibility: the return "( )" from parent - * class is not acceptable for screenreader users, and we DO want a label - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $output = parent::getFrozenHtml(); - - if (isset($this->_attributes['class'])) { - $pattern = 'disabled="disabled"'; - $class = $this->_attributes['class']; - $replacement = 'disabled="disabled" class="'.$class.'"'; - $output = str_replace($pattern, $replacement, $output); - } - - return $output; - } -} diff --git a/field/radiobutton/tests/behat/itemform.feature b/field/radiobutton/tests/behat/itemform.feature index ac4eb59ee49..36a14ae166f 100644 --- a/field/radiobutton/tests/behat/itemform.feature +++ b/field/radiobutton/tests/behat/itemform.feature @@ -85,11 +85,11 @@ Feature: Create a radiobutton item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Which summer holidays place do you prefer?" - Then the field "id_surveypro_field_radiobutton_2_0" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_1" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_2" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_3" matches value "1" - Then the field "id_surveypro_field_radiobutton_2_4" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_other" matches value "0" - Then the field "id_surveypro_field_radiobutton_2_text" matches value "specify" + Then the field "id_field_radiobutton_2_0" matches value "0" + Then the field "id_field_radiobutton_2_1" matches value "0" + Then the field "id_field_radiobutton_2_2" matches value "0" + Then the field "id_field_radiobutton_2_3" matches value "1" + Then the field "id_field_radiobutton_2_4" matches value "0" + Then the field "id_field_radiobutton_2_other" matches value "0" + Then the field "id_field_radiobutton_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/radiobutton/tests/behat/submit_radiobutton.feature b/field/radiobutton/tests/behat/submit_radiobutton.feature index d671c7a535c..339338d397a 100644 --- a/field/radiobutton/tests/behat/submit_radiobutton.feature +++ b/field/radiobutton/tests/behat/submit_radiobutton.feature @@ -58,8 +58,8 @@ Feature: Submit using a radiobutton item # student1 submits And I set the following fields to these values: - | id_surveypro_field_radiobutton_1_3 | 1 | - | id_surveypro_field_radiobutton_2_2 | 1 | + | id_field_radiobutton_1_3 | 1 | + | id_field_radiobutton_2_2 | 1 | And I press "Submit" diff --git a/field/radiobutton/tests/behat/two_option_test.feature b/field/radiobutton/tests/behat/two_option_test.feature index e5ceed28398..51ef7cf6171 100644 --- a/field/radiobutton/tests/behat/two_option_test.feature +++ b/field/radiobutton/tests/behat/two_option_test.feature @@ -1,8 +1,8 @@ @mod @mod_surveypro -Feature: Load and apply mum_or_dad_test usertemplates to test preview do not rise up errors +Feature: Load and apply mum_or_dad usertemplates to test preview do not rise up errors In order to test correct preview As teacher1 - I load mum_or_dad_test usertemplates and ask for preview + I load mum_or_dad usertemplates and ask for preview @javascript @_file_upload Scenario: Test mum or dad displays correctly @@ -23,7 +23,7 @@ Feature: Load and apply mum_or_dad_test usertemplates to test preview do not ris # now I am in the "Manage" page And I select "Import" from the "jump" singleselect - And I upload "mod/surveypro/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml" file to "Choose files to import" filemanager + And I upload "mod/surveypro/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml" file to "Choose files to import" filemanager And I set the field "Sharing level" to "This course" And I press "Import" @@ -33,7 +33,7 @@ Feature: Load and apply mum_or_dad_test usertemplates to test preview do not ris And I select "Apply" from the "jump" singleselect And I set the following fields to these values: - | User templates | (This course) mum_or_dad_test.xml | + | User templates | (This course) mum_or_dad.xml | | id_action_0 | 1 | And I press "Apply" diff --git a/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml b/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml similarity index 90% rename from field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml rename to field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml index f2c052a2032..10d4b42896b 100644 --- a/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad_test.xml +++ b/field/radiobutton/tests/fixtures/usertemplate/mum_or_dad.xml @@ -1,18 +1,18 @@ - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_test_01 + 0 + 0 + 0 + + Mum Dad 1 @@ -21,19 +21,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_02 + 0 + 0 + 0 + + Mum Dad 2 @@ -41,19 +41,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_04 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -63,19 +63,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 1 0 0 radiobutton_test_05 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -84,19 +84,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_07 + 0 + 0 + 0 + + Mum Dad 1 @@ -105,19 +105,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_08 + 0 + 0 + 0 + + Mum Dad 2 @@ -125,19 +125,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_09 + 0 + 0 + 0 + + Mum Dad 3 @@ -145,19 +145,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_10 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -167,19 +167,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_11 + 0 + 0 + 0 + + Mum Dad Other (please, specify) @@ -188,19 +188,19 @@ Dad 0 - + - 0 - 0 - 0 - - Who do you love the most? 1 0 0 0 radiobutton_test_12 + 0 + 0 + 0 + + Mum Dad Other (please, specify) diff --git a/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml b/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml similarity index 92% rename from field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml rename to field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml index 9e2102cb8b9..35857f36e42 100644 --- a/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2015123000.xml +++ b/field/radiobutton/tests/fixtures/usertemplate/radiobutton_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>RADIO BUTTON</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>radio button specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li><li>Adjustment</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RADIO BUTTON</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>radio button specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li><li>Adjustment</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -41,6 +36,11 @@ 0 1 radiobutton_001 + 0 + 0 + 0 + + sea mountain lake @@ -51,27 +51,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -79,6 +74,11 @@ desert 0 2 radiobutton_002 + 0 + 0 + 0 + + sea mountain lake @@ -89,27 +89,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -117,6 +112,11 @@ desert 0 3 radiobutton_003 + 0 + 0 + 0 + + sea mountain lake @@ -127,27 +127,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -155,6 +150,11 @@ desert 0 4 radiobutton_004 + 0 + 0 + 0 + + sea mountain lake @@ -166,27 +166,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -194,6 +189,11 @@ desert 0 5 radiobutton_005 + 0 + 0 + 0 + + sea mountain lake @@ -205,27 +205,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -233,6 +228,11 @@ desert 0 6 radiobutton_006 + 0 + 0 + 0 + + sea mountain lake @@ -244,27 +244,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -272,6 +267,11 @@ desert 0 7 radiobutton_007 + 0 + 0 + 0 + + sea mountain lake @@ -283,27 +283,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -311,6 +306,11 @@ desert 0 8 radiobutton_008 + 0 + 0 + 0 + + sea mountain lake @@ -322,27 +322,22 @@ desert 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -350,6 +345,11 @@ desert 0 9 radiobutton_009 + 0 + 0 + 0 + + sea mountain lake @@ -362,27 +362,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -390,6 +385,11 @@ desert 0 10 radiobutton_010 + 0 + 0 + 0 + + sea mountain lake @@ -402,27 +402,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the defaultis set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the defaultis set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -430,6 +425,11 @@ desert 0 11 radiobutton_012 + 0 + 0 + 0 + + sea mountain lake @@ -442,27 +442,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -470,6 +465,11 @@ desert 0 12 radiobutton_011 + 0 + 0 + 0 + + sea mountain lake @@ -482,27 +482,22 @@ desert 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li><li>checkboxes are vertically displayed</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -510,6 +505,11 @@ desert 0 13 radiobutton_013 + 0 + 0 + 0 + + sea mountain lake diff --git a/field/radiobutton/version.php b/field/radiobutton/version.php index a225b45b524..15a0a646125 100644 --- a/field/radiobutton/version.php +++ b/field/radiobutton/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_radiobutton'; // Full name of the plugin (used for diagnostics). diff --git a/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php b/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php index f2f5d09882a..20d6c0c3724 100644 --- a/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php +++ b/field/rate/backup/moodle2/backup_surveyprofield_rate_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'rate'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginrate = new backup_nested_element('surveyprofield_rate', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates', ]); + 'options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/rate/classes/item.php b/field/rate/classes/item.php index bed770ad029..a407009ab3d 100644 --- a/field/rate/classes/item.php +++ b/field/rate/classes/item.php @@ -40,52 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -103,7 +58,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -122,6 +77,13 @@ class item extends itembase { */ protected $differentrates; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -154,9 +116,11 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['insearchform'] = false; - $this->insetupform['position'] = SURVEYPRO_POSITIONLEFT; + // $this->insetupform['position'] = SURVEYPRO_POSITIONLEFT; <-- What does it mean? if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -187,19 +151,15 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. + // Set custom fields values as defined by this specific plugin. // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options', 'rates', 'defaultvalue']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -212,17 +172,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Rate'; - $record->contentformat = 1; - $record->position = 1; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'rate_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; $record->rates = "up\ndown"; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; $record->style = 0; $record->differentrates = 0; @@ -244,7 +198,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -254,7 +208,7 @@ public function item_custom_fields_to_db($record) { // 3. Set values corresponding to checkboxes. // Take care: 'required', 'hideinstructions' were already considered in get_common_settings. - $checkboxes = ['hideinstructions', 'differentrates']; + $checkboxes = ['differentrates']; foreach ($checkboxes as $checkbox) { $record->{$checkbox} = (isset($record->{$checkbox})) ? 1 : 0; } @@ -271,15 +225,141 @@ public function item_left_position_allowed() { return false; } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set rates. + * + * @param string $rates + * @return void + */ + public function set_rates($rates) { + $this->rates = $rates; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set style. + * + * @param string $style + * @return void + */ + public function set_style($style) { + $this->style = $style; + } + + /** + * Set differentrates. + * + * @param string $differentrates + * @return void + */ + public function set_differentrates($differentrates) { + $this->differentrates = $differentrates; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get rates. + * + * @return $this->rates + */ + public function get_rates() { + return $this->rates; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get style. + * + * @return $this->style + */ + public function get_style() { + return $this->style; + } + + /** + * Get differentrates. + * + * @return $this->differentrates + */ + public function get_differentrates() { + return $this->differentrates; } /** @@ -306,14 +386,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'rates', 'defaultoption', 'defaultvalue', 'downloadformat', 'style', 'differentrates']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'rates', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_rate'] = ['options', 'rates', 'defaultvalue']; return $fieldlist; } @@ -330,32 +423,13 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - - - + + + @@ -381,10 +455,14 @@ public function userform_mform_element($mform, $searchform, $readonly) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $options = $utilityitemman->multilinetext_to_array($this->options); $optioncount = count($options) - 1; - $rates = $this->get_content_array(SURVEYPRO_LABELS, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_LABELS, 'rates'); $defaultvalues = $utilityitemman->multilinetext_to_array($this->defaultvalue); - $idprefix = 'id_surveypro_field_rate_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_rate_'.$this->sortindex; + $elementgroup = []; + $attributes = []; + $basename = $this->itemname; if (($this->defaultoption == SURVEYPRO_INVITEDEFAULT)) { if ($this->style == SURVEYPROFIELD_RATE_USERADIO) { @@ -394,18 +472,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { } } - $attributes = []; if ($this->style == SURVEYPROFIELD_RATE_USERADIO) { foreach ($options as $row => $option) { - $attributes['class'] = 'indent-'.$this->indent.' rate_radio'; - $uniquename = $this->itemname.'_'.$row; $elementgroup = []; + $uniquename = $basename.'_'.$row; foreach ($rates as $col => $rate) { - $attributes['id'] = $idprefix.'_'.$row.'_'.$col; - $elementgroup[] = $mform->createElement('mod_surveypro_radiobutton', $uniquename, '', $rate, $col, $attributes); - $attributes['class'] = 'rate_radio'; + $attributes['id'] = $baseid.'_'.$row.'_'.$col; + $elementgroup[] = $mform->createElement('radio', $uniquename, '', $rate, $col, $attributes); } - $mform->addGroup($elementgroup, $uniquename.'_group', $option, ' ', false); + $mform->addGroup($elementgroup, $uniquename.'_group', $option, ' ', false, $class); // Don' add a colorunifier div after the last rate element. if ($row < $optioncount) { @@ -415,12 +490,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { } if ($this->style == SURVEYPROFIELD_RATE_USESELECT) { - $attributes['class'] = 'indent-'.$this->indent.' rate_select'; foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; - $attributes['id'] = $idprefix.'_'.$row; - $elementgroup = [$mform->createElement('select', $uniquename, '', $rates, $attributes)]; - $mform->addGroup($elementgroup, $uniquename.'_group', $option, '', false); + $elementgroup = []; + $uniquename = $basename.'_'.$row; + $attributes['id'] = $baseid.'_'.$row; + $elementgroup[] = $mform->createElement('select', $uniquename, '', $rates, $attributes); + $mform->addGroup($elementgroup, $uniquename.'_group', $option, '', false, $class); // Don't add a colorunifier div after the last rate element. if ($row < $optioncount) { @@ -432,14 +507,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { if (!$this->required) { // This is the last if it exists. $this->item_add_color_unifier($mform); - // Bloody hack to align the noanswer checkbox according to the indent. $elementgroup = []; - $uniquename = 'checkbox'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'indent-'.$this->indent.' rate_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_advcheckbox', $uniquename, '', $noanswerstr, $attributes); - $mform->addGroup($elementgroup, $this->itemname.'_noanswer'); + $attributes['id'] = $baseid.'_noanswer'; + $elementgroup[] = $mform->createElement('advcheckbox', $basename.'_noanswer', '', $noanswerstr, $attributes); + $mform->addGroup($elementgroup, $basename.'_noanswer_group', $noanswerstr, '', false, $class); } if ($this->required) { @@ -447,35 +519,35 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $mform->_required[] = $this->itemname.'_extrarow'; + $mform->_required[] = $basename.'_extrarow_group'; } else { - // Disable if $this->itemname.'_noanswer' is selected. + // Disable if $basename.'_noanswer' is selected. $optionindex = 0; foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row.'_group'; - $mform->disabledIf($uniquename, $this->itemname.'_noanswer[checkbox]', 'checked'); + $uniquename = $basename.'_'.$row; + $mform->disabledIf($uniquename, $basename.'_noanswer', 'checked'); } if ($this->defaultoption == SURVEYPRO_NOANSWERDEFAULT) { - $mform->setDefault($this->itemname.'_noanswer[checkbox]', '1'); + $mform->setDefault($basename.'_noanswer', '1'); } } switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; + $uniquename = $basename.'_'.$row; $defaultindex = array_search($defaultvalues[$row], $rates); $mform->setDefault($uniquename, "$defaultindex"); } break; case SURVEYPRO_INVITEDEFAULT: foreach ($options as $row => $option) { - $uniquename = $this->itemname.'_'.$row; + $uniquename = $basename.'_'.$row; $mform->setDefault($uniquename, SURVEYPRO_INVITEVALUE); } break; case SURVEYPRO_NOANSWERDEFAULT: - $uniquename = $this->itemname.'_noanswer[checkbox]'; + $uniquename = $basename.'_noanswer[checkbox]'; $mform->setDefault($uniquename, 1); break; default: @@ -497,14 +569,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } // If different rates were requested, it is time to verify this. $utilityitemman = new utility_item($this->cm, $this->surveypro); $options = $utilityitemman->multilinetext_to_array($this->options); if ((isset($data[$this->itemname.'_noanswer']['checkbox'])) && ($data[$this->itemname.'_noanswer']['checkbox'] == 1)) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $return = false; @@ -517,11 +589,11 @@ public function userform_mform_validation($data, &$errors, $searchform) { } } if ($return) { - return; + return $errors; } if (!empty($this->differentrates)) { - $optionscount = count($this->get_content_array(SURVEYPRO_LABELS, 'options')); + $optionscount = count($this->get_textarea_content(SURVEYPRO_LABELS, 'options')); $rates = []; for ($i = 0; $i < $optionscount; $i++) { $rates[] = $data[$this->itemname.'_'.$i]; @@ -535,6 +607,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$elementname] = get_string('uerr_duplicaterate', 'surveyprofield_rate'); } } + + return $errors; } /** @@ -638,9 +712,9 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMSRETURNSVALUES: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); - $rates = $this->get_content_array(SURVEYPRO_VALUES, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_VALUES, 'rates'); foreach ($labels as $col => $label) { $index = $answers[$col]; $output[] = $label.SURVEYPROFIELD_RATE_VALUERATESEPARATOR.$rates[$index]; @@ -650,9 +724,9 @@ public function userform_db_to_export($answer, $format='') { case SURVEYPRO_ITEMRETURNSLABELS: $answers = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $content); $output = []; - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); - $rates = $this->get_content_array(SURVEYPRO_LABELS, 'rates'); + $rates = $this->get_textarea_content(SURVEYPRO_LABELS, 'rates'); foreach ($labels as $col => $label) { $index = $answers[$col]; $output[] = $label.SURVEYPROFIELD_RATE_VALUERATESEPARATOR.$rates[$index]; @@ -688,7 +762,7 @@ public function userform_get_root_elements_name() { } if (!$this->required) { - $elementnames[] = $this->itemname.'_noanswer[checkbox]'; + $elementnames[] = $this->itemname.'_noanswer'; } return $elementnames; diff --git a/field/rate/classes/itemsetupform.php b/field/rate/classes/itemsetupform.php index cdc5e34f24b..1c0e4f8e5c4 100644 --- a/field/rate/classes/itemsetupform.php +++ b/field/rate/classes/itemsetupform.php @@ -160,13 +160,21 @@ public function validation($data, $files) { // Each single label has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { - $errors['rates'] = get_string('ierr_labelsduplicated', 'surveyprofield_rate'); + $errors['options'] = get_string('ierr_labelsduplicated', 'surveyprofield_rate'); + } + // A single option is not allowed. + if (count($cleanoptions) == 1) { + $errors['options'] = get_string('ierr_singleoption', 'surveyprofield_rate'); } // Each single value has to be unique. $arrayunique = array_unique($values); if (count($values) != count($arrayunique)) { $errors['rates'] = get_string('ierr_valuesduplicated', 'surveyprofield_rate'); } + // A single rate is not allowed. + if (count($cleanrates) == 1) { + $errors['rates'] = get_string('ierr_singlerate', 'surveyprofield_rate'); + } // Each single option has to be unique. $arrayunique = array_unique($labels); if (count($labels) != count($arrayunique)) { diff --git a/field/rate/db/install.xml b/field/rate/db/install.xml index 6bb9162820b..1ed46323ef0 100644 --- a/field/rate/db/install.xml +++ b/field/rate/db/install.xml @@ -1,36 +1,20 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/field/rate/db/upgrade.php b/field/rate/db/upgrade.php index 0f40b3a2c97..a3e2263f0d3 100644 --- a/field/rate/db/upgrade.php +++ b/field/rate/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_rate_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Rate savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'rate'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_rate. + $table = new xmldb_table('surveyprofield_rate'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_rate} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Rate savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'rate'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_rate'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_rate. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_rate} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Rate savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'rate'); + } + return true; } diff --git a/field/rate/lang/en/surveyprofield_rate.php b/field/rate/lang/en/surveyprofield_rate.php index bdfa6eabe58..edcbf0c3563 100644 --- a/field/rate/lang/en/surveyprofield_rate.php +++ b/field/rate/lang/en/surveyprofield_rate.php @@ -24,33 +24,35 @@ */ $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['differentrates_help'] = 'Force the user to rate each element with a different value'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['differentrates'] = 'Force different rates'; +$string['differentrates_help'] = 'Force the user to rate each element with a different value'; $string['diffratesrequired'] = 'Scores are supposed to be different each other'; -$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Use this option to define the format of the value returned by this field.
Choosing \'selection\' you get a comma separated list of the values corresponding to the selection of the remote user.
Choosing \'positional answer\' you get an answer made by as much values as the number of the options defined for this field. For each option selected by the remote user you will get a 1 (or the corresponding value whether defined), for each option not selected by the remote user you will get a 0.
Example: let us suppose the question: "What do you usually get for breakfast?" with options: "milk, jam, ham, eggs, bread, orange juice". Let us futher suppose that the user selected: "ham" AND "eggs" AND "orange juice".
By choosing \'selection\' here, the value returned by this item will be: "ham, eggs, orange juice".
By choosing \'positional answer\' here, the value returned by this item will be: "0, 0, 1, 1, 0, 1" because the first and the second options ("milk, jam") were not choosed, the third and the fourth options ("ham, eggs") were selected, the second last ("bread") was not selected and the last one ("orange juice") was choosed by the remote user.'; +$string['ierr_defaultsduplicated'] = 'Defaults have to be different when different rates is required'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among rates'; $string['ierr_invaliddefaultscount'] = 'Number of defaults has to be equal to the number of options'; +$string['ierr_labelsduplicated'] = 'Rates must be different each other'; $string['ierr_notenoughrates'] = 'Number of rates is not enough to force different rates'; -$string['ierr_defaultsduplicated'] = 'Defaults have to be different when different rates is required'; -$string['options_help'] = 'The list of the options for this item.'; +$string['ierr_optionsduplicated'] = 'Options must be different each other'; +$string['ierr_singleoption'] = 'A single option is not allowed'; +$string['ierr_singlerate'] = 'A single rate is not allowed'; +$string['ierr_valuesduplicated'] = 'Values must be different each other'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item.'; $string['pluginname'] = 'Rate'; -$string['rates_help'] = 'The list of values to rate the options of this question. You can choose to write them with the format: value::label. The label will be displayed on the screen, the value will be stored in the survey field. If you only specify one word per line, value and label will both be valued to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; +$string['privacy:metadata'] = 'The "Rate" field plugin does not store any personal data.'; $string['rates'] = 'Rates'; +$string['rates_help'] = 'The list of values to rate the options of this question. You can choose to write them with the format: value::label. The label will be displayed on the screen, the value will be stored in the survey field. If you only specify one word per line, value and label will both be valued to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['returnlabels'] = 'list of options with corresponding labels of rates'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'list of options with corresponding values of rates'; -$string['style_help'] = 'You can choose whether you want to allow the rate of elements using drop down menus or radio button. The overall result will be affected by this option.'; $string['style'] = 'Element style'; +$string['style_help'] = 'You can choose whether you want to allow the rate of elements using drop down menus or radio button. The overall result will be affected by this option.'; $string['uerr_duplicaterate'] = 'Duplicate rate is not allowed'; $string['uerr_optionnotset'] = 'Please choose an option'; $string['usemenu'] = 'dropdown menu'; $string['useradio'] = 'radio buttons'; $string['userfriendlypluginname'] = 'Rate'; -$string['ierr_labelsduplicated'] = 'Rates must be different each other'; -$string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['ierr_optionsduplicated'] = 'Options must be different each other'; -$string['privacy:metadata'] = 'The "Rate" field plugin does not store any personal data.'; diff --git a/field/rate/tests/behat/itemform.feature b/field/rate/tests/behat/itemform.feature index a324b1a30bd..127694baaa7 100644 --- a/field/rate/tests/behat/itemform.feature +++ b/field/rate/tests/behat/itemform.feature @@ -42,9 +42,9 @@ Feature: Create a rate item | Parent content | 1 | | Element style | dropdown menu | And I set the multiline field "Options" to "\nItalian\n\n\n Spanish\nEnglish\nFrench\n\n\nGerman\n\nDeutch\n\n" - And I set the multiline field "Rates" to " Mother tongue\nVery confident\n\nNot enought\n\n\n\n\nCompletely unknown\n\n" + And I set the multiline field "Rates" to " Mother tongue\nVery confident\n\nSomewhat confident\n\n\n\n\nNot confident at all\n\n" And I set the field "id_defaultoption_1" to "1" - And I set the multiline field "id_defaultvalue" to "Not enought\n\n\n Not enought\n\n\n\nNot enought\nNot enought\n\n\n" + And I set the multiline field "id_defaultvalue" to "Somewhat confident\n\n\n Somewhat confident\n\n\n\nSomewhat confident\nSomewhat confident\n\n\n" And I set the following fields to these values: | Download format | list of options with corresponding values of rates | | Force different rates | 1 | @@ -52,16 +52,16 @@ Feature: Create a rate item Then I should see "Number of rates is not enough to force different rates" Then I should see "Defaults have to be different when different rates is required" - And I set the multiline field "Rates" to "\n\n Mother tongue\nVery confident\n\n\n100 words vocabulary\n\nNot enought\nReally ridicolous\n\nCompletely unknown\n\n\n" - And I set the multiline field "id_defaultvalue" to "\n\nCompletely unknown\n\n Absolutely ridicolous\nNot enought\n\n\n100 words vocabulary\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\nVery confident\n\n\n100 words vocabulary\n\nSomewhat confident\nReally ridicolous\n\nNot confident at all\n\n\n" + And I set the multiline field "id_defaultvalue" to "\n\nNot confident at all\n\n Absolutely ridicolous\nSomewhat confident\n\n\n100 words vocabulary\n" And I press "Add" Then I should see "The default item \"Absolutely ridicolous\" was not found among rates" - And I set the multiline field "id_defaultvalue" to "\n Completely unknown\nReally ridicolous\n\n\nNot enought\n\n\n100 words vocabulary\n" + And I set the multiline field "id_defaultvalue" to "\n Not confident at all\nReally ridicolous\n\n\nSomewhat confident\n\n\n100 words vocabulary\n" And I press "Add" Then I should see "Number of defaults has to be equal to the number of options" - And I set the multiline field "id_defaultvalue" to "\n Completely unknown\nReally ridicolous\n\n\nNot enought\n\n\n100 words vocabulary\nVery confident\nMother tongue\n\n\n\n\n" + And I set the multiline field "id_defaultvalue" to "\n Not confident at all\nReally ridicolous\n\n\nSomewhat confident\n\n\n100 words vocabulary\nVery confident\nMother tongue\n\n\n\n\n" And I press "Add" And I follow "edit_item_2" @@ -91,16 +91,16 @@ Feature: Create a rate item Mother tongue Very confident 100 words vocabulary - Not enought + Somewhat confident Really ridicolous - Completely unknown + Not confident at all """ Then the field "id_defaultoption_1" matches value "1" Then the field "defaultvalue" matches multiline: """ - Completely unknown + Not confident at all Really ridicolous - Not enought + Somewhat confident 100 words vocabulary Very confident Mother tongue @@ -113,12 +113,12 @@ Feature: Create a rate item And I select "Preview" from the "jump" singleselect Then I should see "II.a" Then I should see "How confident are you with the following languages?" - Then the field "id_surveypro_field_rate_2_0" matches value "Completely unknown" - Then the field "id_surveypro_field_rate_2_1" matches value "Really ridicolous" - Then the field "id_surveypro_field_rate_2_2" matches value "Not enought" - Then the field "id_surveypro_field_rate_2_3" matches value "100 words vocabulary" - Then the field "id_surveypro_field_rate_2_4" matches value "Very confident" - Then the field "id_surveypro_field_rate_2_5" matches value "Mother tongue" + Then the field "id_field_rate_2_0" matches value "Not confident at all" + Then the field "id_field_rate_2_1" matches value "Really ridicolous" + Then the field "id_field_rate_2_2" matches value "Somewhat confident" + Then the field "id_field_rate_2_3" matches value "100 words vocabulary" + Then the field "id_field_rate_2_4" matches value "Very confident" + Then the field "id_field_rate_2_5" matches value "Mother tongue" Then I should see "Additional note" And I select "Elements" from the "jump" singleselect @@ -137,45 +137,45 @@ Feature: Create a rate item And I select "Preview" from the "jump" singleselect Then I should see "II.b" - Then the field "id_surveypro_field_rate_3_0_0" matches value "0" - Then the field "id_surveypro_field_rate_3_0_1" matches value "0" - Then the field "id_surveypro_field_rate_3_0_2" matches value "0" - Then the field "id_surveypro_field_rate_3_0_3" matches value "0" - Then the field "id_surveypro_field_rate_3_0_4" matches value "0" - Then the field "id_surveypro_field_rate_3_0_5" matches value "1" + Then the field "id_field_rate_3_0_0" matches value "0" + Then the field "id_field_rate_3_0_1" matches value "0" + Then the field "id_field_rate_3_0_2" matches value "0" + Then the field "id_field_rate_3_0_3" matches value "0" + Then the field "id_field_rate_3_0_4" matches value "0" + Then the field "id_field_rate_3_0_5" matches value "1" - Then the field "id_surveypro_field_rate_3_1_0" matches value "0" - Then the field "id_surveypro_field_rate_3_1_1" matches value "0" - Then the field "id_surveypro_field_rate_3_1_2" matches value "0" - Then the field "id_surveypro_field_rate_3_1_3" matches value "0" - Then the field "id_surveypro_field_rate_3_1_4" matches value "1" - Then the field "id_surveypro_field_rate_3_1_5" matches value "0" + Then the field "id_field_rate_3_1_0" matches value "0" + Then the field "id_field_rate_3_1_1" matches value "0" + Then the field "id_field_rate_3_1_2" matches value "0" + Then the field "id_field_rate_3_1_3" matches value "0" + Then the field "id_field_rate_3_1_4" matches value "1" + Then the field "id_field_rate_3_1_5" matches value "0" - Then the field "id_surveypro_field_rate_3_2_0" matches value "0" - Then the field "id_surveypro_field_rate_3_2_1" matches value "0" - Then the field "id_surveypro_field_rate_3_2_2" matches value "0" - Then the field "id_surveypro_field_rate_3_2_3" matches value "1" - Then the field "id_surveypro_field_rate_3_2_4" matches value "0" - Then the field "id_surveypro_field_rate_3_2_5" matches value "0" + Then the field "id_field_rate_3_2_0" matches value "0" + Then the field "id_field_rate_3_2_1" matches value "0" + Then the field "id_field_rate_3_2_2" matches value "0" + Then the field "id_field_rate_3_2_3" matches value "1" + Then the field "id_field_rate_3_2_4" matches value "0" + Then the field "id_field_rate_3_2_5" matches value "0" - Then the field "id_surveypro_field_rate_3_3_0" matches value "0" - Then the field "id_surveypro_field_rate_3_3_1" matches value "0" - Then the field "id_surveypro_field_rate_3_3_2" matches value "1" - Then the field "id_surveypro_field_rate_3_3_3" matches value "0" - Then the field "id_surveypro_field_rate_3_3_4" matches value "0" - Then the field "id_surveypro_field_rate_3_3_5" matches value "0" + Then the field "id_field_rate_3_3_0" matches value "0" + Then the field "id_field_rate_3_3_1" matches value "0" + Then the field "id_field_rate_3_3_2" matches value "1" + Then the field "id_field_rate_3_3_3" matches value "0" + Then the field "id_field_rate_3_3_4" matches value "0" + Then the field "id_field_rate_3_3_5" matches value "0" - Then the field "id_surveypro_field_rate_3_4_0" matches value "0" - Then the field "id_surveypro_field_rate_3_4_1" matches value "1" - Then the field "id_surveypro_field_rate_3_4_2" matches value "0" - Then the field "id_surveypro_field_rate_3_4_3" matches value "0" - Then the field "id_surveypro_field_rate_3_4_4" matches value "0" - Then the field "id_surveypro_field_rate_3_4_5" matches value "0" + Then the field "id_field_rate_3_4_0" matches value "0" + Then the field "id_field_rate_3_4_1" matches value "1" + Then the field "id_field_rate_3_4_2" matches value "0" + Then the field "id_field_rate_3_4_3" matches value "0" + Then the field "id_field_rate_3_4_4" matches value "0" + Then the field "id_field_rate_3_4_5" matches value "0" - Then the field "id_surveypro_field_rate_3_5_0" matches value "1" - Then the field "id_surveypro_field_rate_3_5_1" matches value "0" - Then the field "id_surveypro_field_rate_3_5_2" matches value "0" - Then the field "id_surveypro_field_rate_3_5_3" matches value "0" - Then the field "id_surveypro_field_rate_3_5_4" matches value "0" - Then the field "id_surveypro_field_rate_3_5_5" matches value "0" + Then the field "id_field_rate_3_5_0" matches value "1" + Then the field "id_field_rate_3_5_1" matches value "0" + Then the field "id_field_rate_3_5_2" matches value "0" + Then the field "id_field_rate_3_5_3" matches value "0" + Then the field "id_field_rate_3_5_4" matches value "0" + Then the field "id_field_rate_3_5_5" matches value "0" Then I should see "One more additional note" diff --git a/field/rate/tests/behat/submit_rate.feature b/field/rate/tests/behat/submit_rate.feature index b09630f98e1..b9856b7998e 100644 --- a/field/rate/tests/behat/submit_rate.feature +++ b/field/rate/tests/behat/submit_rate.feature @@ -33,7 +33,7 @@ Feature: Submit using a rate item | Element number | 13a | | Element style | radio buttons | And I set the multiline field "Options" to " Italian\nSpanish\n\n\n English\n\n\nFrench\n\nGerman\n\n\n" - And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nNot enought\n\nCompletely unknown\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nSomewhat confident\n\nNot confident at all\n" And I press "Add" And I set the field "typeplugin" to "Rate" @@ -47,7 +47,7 @@ Feature: Submit using a rate item | Element number | 13b | | Element style | dropdown menu | And I set the multiline field "Options" to " Italian\nSpanish\n\n\n English\n\n\nFrench\n\nGerman\n\n\n" - And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nNot enought\n\nCompletely unknown\n" + And I set the multiline field "Rates" to "\n\n Mother tongue\n Very confident\nSomewhat confident\n\nNot confident at all\n" And I press "Add" And I log out @@ -58,16 +58,16 @@ Feature: Submit using a rate item # student1 submits And I set the following fields to these values: - | id_surveypro_field_rate_1_0_0 | 1 | - | id_surveypro_field_rate_1_1_1 | 1 | - | id_surveypro_field_rate_1_2_2 | 1 | - | id_surveypro_field_rate_1_3_3 | 1 | - | id_surveypro_field_rate_1_4_2 | 1 | - | id_surveypro_field_rate_2_0 | Mother tongue | - | id_surveypro_field_rate_2_1 | Very confident | - | id_surveypro_field_rate_2_2 | Not enought | - | id_surveypro_field_rate_2_3 | Completely unknown | - | id_surveypro_field_rate_2_4 | Not enought | + | id_field_rate_1_0_0 | 1 | + | id_field_rate_1_1_1 | 1 | + | id_field_rate_1_2_2 | 1 | + | id_field_rate_1_3_3 | 1 | + | id_field_rate_1_4_2 | 1 | + | id_field_rate_2_0 | Mother tongue | + | id_field_rate_2_1 | Very confident | + | id_field_rate_2_2 | Somewhat confident | + | id_field_rate_2_3 | Not confident at all | + | id_field_rate_2_4 | Somewhat confident | And I press "Submit" And I press "Continue to responses list" diff --git a/field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml b/field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml similarity index 89% rename from field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml rename to field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml index b7516012abe..dd56a35bfc0 100644 --- a/field/rate/tests/fixtures/usertemplate/rate_only_2015123000.xml +++ b/field/rate/tests/fixtures/usertemplate/rate_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>RATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>rate</b><b> specific setting</b>:</p><ol><li>Element style</li><li>Options</li><li>Rates</li><li>Default</li><li>Download format</li></ol><p>and one <b>validaion option</b></p><ol><li>Force different rate</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>rate</b><b> specific setting</b>:</p><ol><li>Element style</li><li>Options</li><li>Rates</li><li>Default</li><li>Download format</li></ol><p>and one <b>validaion option</b></p><ol><li>Force different rate</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 @@ -42,6 +37,10 @@ 1 1 rate_001 + 0 + 0 + + EN ES IT @@ -56,35 +55,34 @@ unknown 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 2 + 1 1 rate_002 + 0 + 0 + + EN ES IT @@ -99,35 +97,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 3 + 1 1 rate_003 + 0 + 0 + + EN ES IT @@ -146,35 +143,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 4 + 1 1 rate_004 + 0 + 0 + + EN ES IT @@ -193,35 +189,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "radio buttons"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 5 + 1 1 rate_005 + 0 + 0 + + EN ES IT @@ -236,35 +231,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 6 + 1 1 rate_006 + 0 + 0 + + EN ES IT @@ -279,35 +273,34 @@ unknown 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to tick the "No answer" checkbox.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 7 + 1 1 rate_007 + 0 + 0 + + EN ES IT @@ -322,35 +315,34 @@ unknown 0 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 0 1 - 8 + 1 1 rate_008 + 0 + 0 + + EN ES IT @@ -369,35 +361,34 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox.</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 0 1 - 9 + 1 1 rate_009 + 0 + 0 + + EN ES IT @@ -416,27 +407,22 @@ mother tongue 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>element style is set to "drop down menu"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -445,6 +431,10 @@ mother tongue 10 1 rate_010 + 0 + 0 + + EN ES IT diff --git a/field/rate/version.php b/field/rate/version.php index 40f60ada718..fee628b60b8 100644 --- a/field/rate/version.php +++ b/field/rate/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_rate'; // Full name of the plugin (used for diagnostics). diff --git a/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php b/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php index 34ff862d34a..75e9db5bedc 100644 --- a/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php +++ b/field/recurrence/backup/moodle2/backup_surveyprofield_recurrence_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'recurrence'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginrecurrence = new backup_nested_element('surveyprofield_recurrence', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/recurrence/classes/item.php b/field/recurrence/classes/item.php index 3bdcab9ba2c..57c40608745 100644 --- a/field/recurrence/classes/item.php +++ b/field/recurrence/classes/item.php @@ -40,67 +40,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; + // Itembase properties. /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var string Format of the content once downloaded */ - protected $indent; + protected $downloadformat; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the recurrence in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Upperbound for the recurrence in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the recurrence in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Month of the defaultvalue for the recurrence @@ -112,11 +79,6 @@ class item extends itembase { */ protected $defaultvalueday; - /** - * @var int Lowerbound for the recurrence in unixtime - */ - protected $lowerbound; - /** * @var int Month of the lowerbound for the recurrence */ @@ -127,11 +89,6 @@ class item extends itembase { */ protected $lowerboundday; - /** - * @var int Upperbound for the recurrence in unixtime - */ - protected $upperbound; - /** * @var int Month of the upperbound for the recurrence */ @@ -142,6 +99,13 @@ class item extends itembase { */ protected $upperboundday; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -176,7 +140,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -208,14 +174,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -228,16 +190,9 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Recurrence [dd/mm]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'recurrence_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; - $record->defaultvalue = 43200; + // $record->defaultvalue $record->downloadformat = 'strftime03'; $record->lowerbound = 43200; $record->upperbound = 31492800; @@ -251,7 +206,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_recurrence_to_unix_time($month, $day) { - return (mktime(12, 0, 0, $month, $day, SURVEYPROFIELD_RECURRENCE_YEAROFFSET)); + return (gmmktime(12, 0, 0, $month, $day, SURVEYPROFIELD_RECURRENCE_YEAROFFSET)); } /** @@ -280,7 +235,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -303,15 +258,217 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueday. + * + * @param string $defaultvalueday + * @return void + */ + public function set_defaultvalueday($defaultvalueday) { + $this->defaultvalueday = $defaultvalueday; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundday. + * + * @param string $lowerboundday + * @return void + */ + public function set_lowerboundday($lowerboundday) { + $this->lowerboundday = $lowerboundday; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundday. + * + * @param string $upperboundday + * @return void + */ + public function set_upperboundday($upperboundday) { + $this->upperboundday = $upperboundday; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueday. + * + * @return $this->defaultvalueday + */ + public function get_defaultvalueday() { + return $this->defaultvalueday; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundday. + * + * @return $this->lowerboundday + */ + public function get_lowerboundday() { + return $this->lowerboundday; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundday. + * + * @return $this->upperboundday + */ + public function get_upperboundday() { + return $this->upperboundday; } /** @@ -350,14 +507,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvaluemonth', 'defaultvalueday', 'lowerboundmonth', 'lowerboundday', 'upperboundmonth', 'upperboundday', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_recurrence'] = []; return $fieldlist; } @@ -374,30 +547,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -431,8 +585,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_recurrence_'.$this->sortindex; - // Begin of: element values. $days = []; $months = []; @@ -466,60 +618,50 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $baseid = 'id_field_recurrence_'.$this->sortindex; + $class = ['class' => 'indent-'.$this->indent]; + $basename = $this->itemname; - $itemname = $this->itemname.'_day'; - $attributes['id'] = $idprefix.'_day'; - $attributes['class'] = 'indent-'.$this->indent.' recurrence_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $days, $attributes); - - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'recurrence_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); + $attributes['id'] = $baseid.'_day'; + $elementgroup[] = $mform->createElement('select', $basename.'_day', '', $days, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'recurrence_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -532,7 +674,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $recurrencearray['mon'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -568,12 +710,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_day', $recurrencearray['mday']); - $mform->setDefault($this->itemname.'_month', $recurrencearray['mon']); + $mform->setDefault($basename.'_day', $recurrencearray['mday']); + $mform->setDefault($basename.'_month', $recurrencearray['mon']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -592,13 +734,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -625,18 +767,18 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_recurrencenotset', 'surveyprofield_recurrence', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if (!utility_item::date_is_valid($data[$this->itemname.'_day'], $data[$this->itemname.'_month'])) { $errors[$errorkey] = get_string('ierr_invalidinput', 'mod_surveypro'); - return; + return $errors; } if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_recurrence_to_unix_time(1, 1)); @@ -670,6 +812,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_recurrence'); } } + + return $errors; } /** diff --git a/field/recurrence/db/install.xml b/field/recurrence/db/install.xml index 8c6b86abc60..6bd334cb249 100644 --- a/field/recurrence/db/install.xml +++ b/field/recurrence/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/recurrence/db/upgrade.php b/field/recurrence/db/upgrade.php index 70d6109dea4..640c8ac4384 100644 --- a/field/recurrence/db/upgrade.php +++ b/field/recurrence/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_recurrence_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Recurrence savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'recurrence'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_recurrence. + $table = new xmldb_table('surveyprofield_recurrence'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_recurrence} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Recurrence savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'recurrence'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_recurrence'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_recurrence. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_recurrence} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Recurrence savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'recurrence'); + } + return true; } diff --git a/field/recurrence/lang/en/surveyprofield_recurrence.php b/field/recurrence/lang/en/surveyprofield_recurrence.php index 0ecebbb9c2b..0d3ca93dd68 100644 --- a/field/recurrence/lang/en/surveyprofield_recurrence.php +++ b/field/recurrence/lang/en/surveyprofield_recurrence.php @@ -25,19 +25,20 @@ $string['currentrecurrencedefault'] = 'Current date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the recurrence the remote user will find answered by default. The default for this type of question is mandatory. If "Current recurrence" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the recurrence the remote user will find answered by default. The default for this type of question is mandatory. If "Current recurrence" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; -$string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['ierr_outofexternalrangedefault'] = 'Default does not fall within the specified range (see "{$a}" help)'; +$string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['inviteday'] = 'Choose a day'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest recurrence the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest recurrence the user is allowed to enter'; $string['pluginname'] = 'Recurrence'; +$string['privacy:metadata'] = 'The "Recurrence" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed be lower-equal than {$a}'; @@ -50,7 +51,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_recurrencenotset'] = 'Please choose a recurrence or select the "{$a}" checkbox'; $string['uerr_recurrencenotsetrequired'] = 'Recurrence is not correctly defined'; -$string['upperbound_help'] = 'The biggest recurrence the user is allowed to enter.

Maximum and minimum values define a range.
If "minimum value" is lower than "maximum value" the user is forced to enter a value falling into the range.
If "minimum value" is greater than "maximum value" the user input is forced out from the range. i.e. the user input is supposed to be lower-equal than the minimum value OR grater-equal than the maximum value.'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest recurrence the user is allowed to enter.

Maximum and minimum values define a range.
If "minimum value" is lower than "maximum value" the user is forced to enter a value falling into the range.
If "minimum value" is greater than "maximum value" the user input is forced out from the range. i.e. the user input is supposed to be lower-equal than the minimum value OR grater-equal than the maximum value.'; $string['userfriendlypluginname'] = 'Recurrence [dd/mm]'; -$string['privacy:metadata'] = 'The "Recurrence" field plugin does not store any personal data.'; diff --git a/field/recurrence/tests/behat/itemform.feature b/field/recurrence/tests/behat/itemform.feature index f139e899940..d76bfa2b3b1 100644 --- a/field/recurrence/tests/behat/itemform.feature +++ b/field/recurrence/tests/behat/itemform.feature @@ -102,6 +102,6 @@ Feature: Create a recurrence item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When do you usually celebrate your name-day?" - Then the field "id_surveypro_field_recurrence_2_day" matches value "1" - Then the field "id_surveypro_field_recurrence_2_month" matches value "February" + Then the field "id_field_recurrence_2_day" matches value "1" + Then the field "id_field_recurrence_2_month" matches value "February" Then I should see "Additional note" diff --git a/field/recurrence/tests/behat/submit_recurrence.feature b/field/recurrence/tests/behat/submit_recurrence.feature index 7d360e06711..2e52d47493c 100644 --- a/field/recurrence/tests/behat/submit_recurrence.feature +++ b/field/recurrence/tests/behat/submit_recurrence.feature @@ -43,8 +43,8 @@ Feature: Submit using a recurrence item # student1 submits And I set the following fields to these values: - | id_surveypro_field_recurrence_1_day | 7 | - | id_surveypro_field_recurrence_1_month | June | + | id_field_recurrence_1_day | 7 | + | id_field_recurrence_1_month | June | And I press "Submit" diff --git a/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml b/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml similarity index 87% rename from field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml rename to field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml index bea3e273d7d..f66e90a2bf8 100644 --- a/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2023103100.xml +++ b/field/recurrence/tests/fixtures/usertemplate/recurrence_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>RECURRENCE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>and two <b>validaion option</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>RECURRENCE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>and two <b>validaion option</b></p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different drecurrenceate or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different drecurrenceate or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 1 - 0 + 1 recurrence_001 + 0 + 0 + 0 + + 2 39600 strftime03 @@ -49,35 +48,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 2 - 0 + 1 recurrence_002 + 0 + 0 + 0 + + 1 13600800 strftime03 @@ -85,35 +83,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 3 - 0 + 1 recurrence_003 + 0 + 0 + 0 + + 4 39600 strftime03 @@ -121,35 +118,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 4 - 0 + 1 recurrence_004 + 0 + 0 + 0 + + 5 39600 strftime03 @@ -157,35 +153,34 @@ 31489200 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 0 0 0 - 5 - 0 + 1 recurrence_005 + 0 + 0 + 0 + + 3 39600 strftime03 @@ -193,35 +188,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 6 - 0 + 1 recurrence_006 + 0 + 0 + 0 + + 2 39600 strftime03 @@ -229,35 +223,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 7 - 0 + 1 recurrence_007 + 0 + 0 + 0 + + 1 13600800 strftime03 @@ -265,35 +258,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 8 - 0 + 1 recurrence_008 + 0 + 0 + 0 + + 4 39600 strftime03 @@ -301,35 +293,34 @@ 31489200 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When do you usually celebrate your name-day? 1 1 0 0 - 9 - 0 + 1 recurrence_009 + 0 + 0 + 0 + + 5 39600 strftime03 diff --git a/field/recurrence/version.php b/field/recurrence/version.php index cef76cac69a..39718c4f71a 100644 --- a/field/recurrence/version.php +++ b/field/recurrence/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_recurrence'; // Full name of the plugin (used for diagnostics). diff --git a/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php b/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php index 5fa2e88fcb0..f653fd22f26 100644 --- a/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php +++ b/field/select/backup/moodle2/backup_surveyprofield_select_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'select'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginselect = new backup_nested_element('surveyprofield_select', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'variable', 'extranote', - 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', ]); + 'options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/select/classes/item.php b/field/select/classes/item.php index 5a6191a9f87..f6155a9efdf 100644 --- a/field/select/classes/item.php +++ b/field/select/classes/item.php @@ -40,47 +40,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var string List of options in the form of "$value SURVEYPRO_VALUELABELSEPARATOR $label" @@ -98,7 +58,7 @@ class item extends itembase { protected $defaultoption; /** - * @var string Value of the field when the form is initially displayed + * @var int Defaultvalue for the item answer */ protected $defaultvalue; @@ -107,6 +67,13 @@ class item extends itembase { */ protected $downloadformat; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -139,7 +106,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['hideinstructions'] = false; if (!empty($itemid)) { @@ -171,18 +140,14 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). // Drop empty rows and trim edging rows spaces from each textarea field. $fieldlist = ['options']; $this->item_clean_textarea_fields($record, $fieldlist); - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -195,15 +160,11 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Select'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->variable = 'select_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->options = "first\nsecond"; + // $record->labelother $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = SURVEYPRO_ITEMRETURNSLABELS; } @@ -223,7 +184,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -247,7 +208,7 @@ public function item_list_constraints() { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $constraints = []; - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $optionstr = get_string('option', 'surveyprofield_select'); foreach ($values as $value) { $constraints[] = $optionstr.$labelsep.$value; @@ -261,15 +222,103 @@ public function item_list_constraints() { return implode('
', $constraints); } + // MARK set. + + /** + * Set options. + * + * @param string $options + * @return void + */ + public function set_options($options) { + $this->options = $options; + } + + /** + * Set labelother. + * + * @param string $labelother + * @return void + */ + public function set_labelother($labelother) { + $this->labelother = $labelother; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + // MARK get. /** - * Is this item available as a parent? + * Get options. + * + * @return $this->options + */ + public function get_options() { + return $this->options; + } + + /** + * Get labelother. * - * @return the content of the static property "canbeparent" + * @return $this->labelother */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_labelother() { + return $this->labelother; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; } /** @@ -296,14 +345,27 @@ public function get_friendlyformat() { return SURVEYPRO_ITEMRETURNSLABELS; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['options', 'labelother', 'defaultoption', 'defaultvalue', 'downloadformat']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote', 'options', 'labelother', 'defaultvalue']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_select'] = ['options', 'labelother', 'defaultvalue']; return $fieldlist; } @@ -329,30 +391,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + - + @@ -373,7 +416,7 @@ public static function get_plugin_schema() { public function parent_encode_child_parentcontent($childparentcontent) { $utilityitemman = new utility_item($this->cm, $this->surveypro); $parentcontents = array_unique($utilityitemman->multilinetext_to_array($childparentcontent)); - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $childparentvalue = []; $labels = []; @@ -411,7 +454,7 @@ public function parent_encode_child_parentcontent($childparentcontent) { */ public function parent_decode_child_parentvalue($childparentvalue) { - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -457,7 +500,7 @@ public function parent_decode_child_parentvalue($childparentvalue) { public function parent_validate_child_constraints($childparentvalue) { // See parent method for explanation. - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); $parentvalues = explode(SURVEYPRO_DBMULTICONTENTSEPARATOR, $childparentvalue); $actualcount = count($parentvalues); @@ -497,10 +540,14 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_select_'.$this->sortindex; + $attributes = []; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_select_'.$this->sortindex; + $basename = $this->itemname; // Begin of: element values. - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (!$searchform) { if ($this->defaultoption == SURVEYPRO_INVITEDEFAULT) { $labels = [SURVEYPRO_INVITEVALUE => get_string('choosedots')] + $labels; @@ -517,16 +564,15 @@ public function userform_mform_element($mform, $searchform, $readonly) { } // End of: element values. - $elementgroup = []; - $attributes = ['id' => $idprefix, 'class' => 'indent-'.$this->indent.' select_select']; - $elementgroup[] = $mform->createElement('select', $this->itemname, '', $labels, $attributes); + $attributes = ['id' => $baseid, 'class' => 'indent-'.$this->indent.' select_select']; + $elementgroup[] = $mform->createElement('select', $basename, '', $labels, $attributes); if ($this->labelother) { - $attributes = ['id' => $idprefix.'_text', 'class' => 'select_select']; - $elementgroup[] = $mform->createElement('text', $this->itemname.'_text', '', $attributes); - $mform->setType($this->itemname.'_text', PARAM_RAW); - $mform->disabledIf($this->itemname.'_text', $this->itemname, 'neq', 'other'); + $attributes = ['id' => $baseid.'_text']; + $elementgroup[] = $mform->createElement('text', $basename.'_text', '', $attributes); + $mform->setType($basename.'_text', PARAM_RAW); + $mform->disabledIf($basename.'_text', $basename, 'neq', 'other'); } - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); if (!$searchform) { if ($this->required) { @@ -534,11 +580,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - if ($this->position == SURVEYPRO_POSITIONTOP) { - $starplace = $this->itemname.'_extrarow'; - } else { - $starplace = ($this->labelother) ? $this->itemname.'_group' : $this->itemname; - } + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } @@ -546,27 +588,27 @@ public function userform_mform_element($mform, $searchform, $readonly) { switch ($this->defaultoption) { case SURVEYPRO_CUSTOMDEFAULT: if ($key = array_search($this->defaultvalue, $labels)) { - $mform->setDefault($this->itemname, "$key"); + $mform->setDefault($basename, "$key"); } else { - $mform->setDefault($this->itemname, 'other'); + $mform->setDefault($basename, 'other'); } break; case SURVEYPRO_INVITEDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_INVITEVALUE); + $mform->setDefault($basename, SURVEYPRO_INVITEVALUE); break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname, SURVEYPRO_NOANSWERVALUE); + $mform->setDefault($basename, SURVEYPRO_NOANSWERVALUE); break; default: $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } } else { - $mform->setDefault($this->itemname, SURVEYPRO_IGNOREMEVALUE); + $mform->setDefault($basename, SURVEYPRO_IGNOREMEVALUE); } - // Note: $this->itemname.'_text' has to ALWAYS get a default (if required) even if it is not selected. + // Note: $basename.'_text' has to ALWAYS get a default (if required) even if it is not selected. if (!empty($this->labelother)) { - $mform->setDefault($this->itemname.'_text', $othervalue); + $mform->setDefault($basename.'_text', $othervalue); } } @@ -583,14 +625,14 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if ($searchform) { - return; + return $errors; } $errorkey = $this->itemname.'_group'; if ($data[$this->itemname] == SURVEYPRO_INVITEVALUE) { $errors[$errorkey] = get_string('uerr_optionnotset', 'surveyprofield_select'); - return; + return $errors; } if (!empty($this->labelother)) { @@ -598,6 +640,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_missingothertext', 'surveyprofield_select'); } } + + return $errors; } /** @@ -702,7 +746,7 @@ public function userform_get_prefill($fromdb) { } if (isset($fromdb->content)) { - $labels = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $labels = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($fromdb->content, $labels)) { $prefill[$this->itemname] = $fromdb->content; } else { @@ -747,7 +791,7 @@ public function userform_db_to_export($answer, $format='') { // Output. switch ($format) { case SURVEYPRO_ITEMSRETURNSVALUES: - $values = $this->get_content_array(SURVEYPRO_VALUES, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_VALUES, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -755,7 +799,7 @@ public function userform_db_to_export($answer, $format='') { } break; case SURVEYPRO_ITEMRETURNSLABELS: - $values = $this->get_content_array(SURVEYPRO_LABELS, 'options'); + $values = $this->get_textarea_content(SURVEYPRO_LABELS, 'options'); if (array_key_exists($content, $values)) { $return = $values[$content]; } else { @@ -783,4 +827,24 @@ public function userform_get_root_elements_name() { return $elementnames; } + + // MARK other. + + /** + * Divide $this->labelother in $value and $label. + * + * @return $value + * @return $label + */ + protected function get_other() { + if (preg_match('~^(.*)'.SURVEYPRO_OTHERSEPARATOR.'(.*)$~', $this->labelother, $match)) { + $label = trim($match[1]); + $value = trim($match[2]); + } else { + $label = trim($this->labelother); + $value = ''; + } + + return [$value, $label]; + } } diff --git a/field/select/classes/itemsetupform.php b/field/select/classes/itemsetupform.php index ad8c80f8745..d9107836237 100644 --- a/field/select/classes/itemsetupform.php +++ b/field/select/classes/itemsetupform.php @@ -86,7 +86,6 @@ public function definition() { // Item: defaultvalue. $fieldname = 'defaultvalue'; - $elementgroup = []; $mform->addElement('text', $fieldname, null); $mform->setType($fieldname, PARAM_RAW); $mform->disabledIf($fieldname, 'defaultoption', 'neq', SURVEYPRO_CUSTOMDEFAULT); diff --git a/field/select/db/install.xml b/field/select/db/install.xml index be54e5716cc..53513e8c414 100644 --- a/field/select/db/install.xml +++ b/field/select/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/select/db/upgrade.php b/field/select/db/upgrade.php index 7ab7ec5911c..e525d1251f3 100644 --- a/field/select/db/upgrade.php +++ b/field/select/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_select_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Select savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'select'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_select. + $table = new xmldb_table('surveyprofield_select'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_select} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Select savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'select'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_select'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_select. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_select} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Select savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'select'); + } + return true; } diff --git a/field/select/lang/en/surveyprofield_select.php b/field/select/lang/en/surveyprofield_select.php index e765a16e140..6ed5dff5f27 100644 --- a/field/select/lang/en/surveyprofield_select.php +++ b/field/select/lang/en/surveyprofield_select.php @@ -25,25 +25,25 @@ $string['allowed'] = 'allowed'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the value the remote user will find answered by default. The default for this type of question is mandatory so, whether not specified, it will be "Choose...".'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_foreigndefaultvalue'] = 'The default item "{$a}" was not found among options'; -$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_labelsduplicated'] = 'Labels must be different each other'; +$string['ierr_missingdefault'] = 'Custom default is missing. You may like to choose the "{$a}" one.'; $string['ierr_valuesduplicated'] = 'Values must be different each other'; -$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['labelother'] = 'Option "other"'; +$string['labelother_help'] = 'If this question is equipped with the option "other" followed by a text field, enter here the label for that option. You can choose to write this option with the format: label->value. The label will be displayed on the screen, the value will be used as default for the text field. If you only specify one word, the field default will be neglected. (Take care: the separator "->" is defined in lib.php and can be changed by a developer)'; $string['option'] = 'Option'; -$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the drop down menu, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['options'] = 'Options'; +$string['options_help'] = 'The list of the options for this item. You are allowed to write them as: value::label in order to define value and label both. The label will be displayed in the drop down menu, the value will be stored in the db. If you only specify one word per line (without separator), value and label will both be set to that word. (Take care: the separator "::" is defined in lib.php and can be changed by a developer)'; $string['parentformat'] = '[label]'; $string['pluginname'] = 'Select'; +$string['privacy:metadata'] = 'The "Select" field plugin does not store any personal data.'; $string['returnlabels'] = 'label of selected item'; $string['returnposition'] = 'positional answer'; $string['returnvalues'] = 'value of selected item'; $string['uerr_missingothertext'] = 'Please add the text required by your selection'; $string['uerr_optionnotset'] = 'Please choose an option'; $string['userfriendlypluginname'] = 'Select'; -$string['privacy:metadata'] = 'The "Select" field plugin does not store any personal data.'; diff --git a/field/select/lang/it/surveyprofield_select.php b/field/select/lang/it/surveyprofield_select.php index 75e650b7755..c1a08f58d2d 100644 --- a/field/select/lang/it/surveyprofield_select.php +++ b/field/select/lang/it/surveyprofield_select.php @@ -23,5 +23,5 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['uerr_optionnotset'] = 'Si selezioni una opzione'; $string['uerr_missingothertext'] = 'Si aggiunga un contenuto al campo corrispondente alla selezione'; +$string['uerr_optionnotset'] = 'Si selezioni una opzione'; diff --git a/field/select/tests/behat/itemform.feature b/field/select/tests/behat/itemform.feature index 5293a317c04..0873a1f1090 100644 --- a/field/select/tests/behat/itemform.feature +++ b/field/select/tests/behat/itemform.feature @@ -83,6 +83,6 @@ Feature: Create a select item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a Which summer holidays place do you prefer?" - Then the field "id_surveypro_field_select_2" matches value "other" - Then the field "id_surveypro_field_select_2_text" matches value "specify" + Then the field "id_field_select_2" matches value "other" + Then the field "id_field_select_2_text" matches value "specify" Then I should see "Additional note" diff --git a/field/select/tests/behat/submit_select.feature b/field/select/tests/behat/submit_select.feature index a2446591428..90857352654 100644 --- a/field/select/tests/behat/submit_select.feature +++ b/field/select/tests/behat/submit_select.feature @@ -40,17 +40,17 @@ Feature: Submit using a select item And I press "New response" # student1 submits - And I set the field "id_surveypro_field_select_1" to "hills" + And I set the field "id_field_select_1" to "hills" And I press "Submit" And I press "Continue to responses list" Then I should see "1" submissions # student1 submits And I press "New response" - And I set the field "id_surveypro_field_select_1" to "other (specify)" + And I set the field "id_field_select_1" to "other (specify)" And I press "Submit" Then I should see "Please add the text required by your selection" - And I set the field "id_surveypro_field_select_1_text" to "flying in the sky" + And I set the field "id_field_select_1_text" to "flying in the sky" And I press "Submit" And I press "Continue to responses list" diff --git a/field/select/tests/fixtures/usertemplate/select_only_2015123000.xml b/field/select/tests/fixtures/usertemplate/select_only_2024032800.xml similarity index 92% rename from field/select/tests/fixtures/usertemplate/select_only_2015123000.xml rename to field/select/tests/fixtures/usertemplate/select_only_2024032800.xml index 0dea9b2573f..c5e85aed1d0 100644 --- a/field/select/tests/fixtures/usertemplate/select_only_2015123000.xml +++ b/field/select/tests/fixtures/usertemplate/select_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>SELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>select specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SELECT</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro plugins.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with some <b>select specific setting</b>:</p><ol><li>Options</li><li>Option "other"</li><li>Default</li><li>Download format</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -41,6 +36,11 @@ 0 1 select_001 + 0 + 0 + 0 + + sea mountain lake @@ -50,27 +50,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -78,6 +73,11 @@ desert 0 2 select_002 + 0 + 0 + 0 + + sea mountain lake @@ -87,27 +87,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -115,6 +110,11 @@ desert 0 3 select_003 + 0 + 0 + 0 + + sea mountain lake @@ -124,27 +124,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -152,6 +147,11 @@ desert 0 4 select_004 + 0 + 0 + 0 + + sea mountain lake @@ -162,27 +162,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 5 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -190,6 +185,11 @@ desert 0 5 select_005 + 0 + 0 + 0 + + sea mountain lake @@ -200,27 +200,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> + 1 + 0 + 6 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a valid option or to select the "No answer" value.</p> - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -228,6 +223,11 @@ desert 0 6 select_006 + 0 + 0 + 0 + + sea mountain lake @@ -238,27 +238,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default invites the user to choose a value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a valid option.</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -266,6 +261,11 @@ desert 0 7 select_007 + 0 + 0 + 0 + + sea mountain lake @@ -276,27 +276,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 8 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to "No answer"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -304,6 +299,11 @@ desert 0 8 select_008 + 0 + 0 + 0 + + sea mountain lake @@ -314,27 +314,22 @@ desert 1 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 @@ -342,6 +337,11 @@ desert 0 9 select_009 + 0 + 0 + 0 + + sea mountain lake @@ -353,27 +353,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 10 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 10 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -381,6 +376,11 @@ desert 0 10 select_010 + 0 + 0 + 0 + + sea mountain lake @@ -392,27 +392,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 11 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to a valid value</li><li>"option other" is set to "other, please specify" and has a default</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 11 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -420,6 +415,11 @@ desert 0 11 select_011 + 0 + 0 + 0 + + sea mountain lake @@ -431,27 +431,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 12 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of the "option other"</li><li>"option other" is set to "other, please specify"</li></ul><p>Behaviour: The item is mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 12 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -459,6 +454,11 @@ desert 0 12 select_012 + 0 + 0 + 0 + + sea mountain lake @@ -470,27 +470,22 @@ desert 1 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> + 1 + 0 + 13 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>the default is set to the label of "option other"</li><li>custom value is not set</li></ul><p>Behaviour: The item is mandatory and the default is set to an invalid value so the user is forced to choose a valid option or to write a custom value.</p> - 1 - 0 - 13 intro 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 @@ -498,6 +493,11 @@ desert 0 13 select_013 + 0 + 0 + 0 + + sea mountain lake diff --git a/field/select/version.php b/field/select/version.php index 454fef755dc..a2d42aeac1c 100644 --- a/field/select/version.php +++ b/field/select/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_select'; // Full name of the plugin (used for diagnostics). diff --git a/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php b/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php index f048d5661a4..881b383561a 100644 --- a/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php +++ b/field/shortdate/backup/moodle2/backup_surveyprofield_shortdate_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'shortdate'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subpluginshortdate = new backup_nested_element('surveyprofield_shortdate', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/shortdate/classes/item.php b/field/shortdate/classes/item.php index bbee1ac61a5..babedfaafd0 100644 --- a/field/shortdate/classes/item.php +++ b/field/shortdate/classes/item.php @@ -39,67 +39,34 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; + // Itembase properties. /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise + * @var string Value of the default setting (invite, custom...) */ - protected $hideinstructions; + protected $defaultoption; /** - * @var string Name of the field storing data in the db table + * @var int Defaultvalue for the item answer */ - protected $variable; + protected $defaultvalue; /** - * @var int Indent of the item in the form page + * @var string Format of the content once downloaded */ - protected $indent; + protected $downloadformat; /** - * @var string Value of the default setting (invite, custom...) + * @var int Lowerbound for the shortdate in unixtime */ - protected $defaultoption; + protected $lowerbound; /** - * @var string Format of the content once downloaded + * @var int Lowerbound for the shortdate in unixtime */ - protected $downloadformat; + protected $upperbound; - /** - * @var int Defaultvalue for the shortdate in unixtime - */ - protected $defaultvalue; + // Service variables. /** * @var int Month of the defaultvalue for the shortdate @@ -111,11 +78,6 @@ class item extends itembase { */ protected $defaultvalueyear; - /** - * @var int Lowerbound for the shortdate in unixtime - */ - protected $lowerbound; - /** * @var int Month of the lowerbound for the shortdate */ @@ -126,11 +88,6 @@ class item extends itembase { */ protected $lowerboundyear; - /** - * @var int Lowerbound for the shortdate in unixtime - */ - protected $upperbound; - /** * @var int Month of the upperbound for the shortdate */ @@ -141,6 +98,13 @@ class item extends itembase { */ protected $upperboundyear; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -177,7 +141,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->upperbound = $this->item_shortdate_to_unix_time(12, $this->surveypro->stopyear); $this->defaultvalue = $this->lowerbound; - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -209,14 +175,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -229,15 +191,9 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Date (short) [mm/yyyy]'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'shortdate_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->defaultoption = SURVEYPRO_INVITEDEFAULT; + // $record->defaultvalue $record->downloadformat = 'strftime01'; $record->lowerbound = 43200; $record->upperbound = 1606824000; @@ -251,7 +207,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_shortdate_to_unix_time($month, $year) { - return (mktime(12, 0, 0, $month, 1, $year)); + return (gmmktime(12, 0, 0, $month, 1, $year)); } /** @@ -278,7 +234,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -300,15 +256,217 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set defaultvaluemonth. + * + * @param string $defaultvaluemonth + * @return void + */ + public function set_defaultvaluemonth($defaultvaluemonth) { + $this->defaultvaluemonth = $defaultvaluemonth; + } + + /** + * Set defaultvalueyear. + * + * @param string $defaultvalueyear + * @return void + */ + public function set_defaultvalueyear($defaultvalueyear) { + $this->defaultvalueyear = $defaultvalueyear; + } + + /** + * Set lowerboundmonth. + * + * @param string $lowerboundmonth + * @return void + */ + public function set_lowerboundmonth($lowerboundmonth) { + $this->lowerboundmonth = $lowerboundmonth; + } + + /** + * Set lowerboundyear. + * + * @param string $lowerboundyear + * @return void + */ + public function set_lowerboundyear($lowerboundyear) { + $this->lowerboundyear = $lowerboundyear; + } + + /** + * Set upperboundmonth. + * + * @param string $upperboundmonth + * @return void + */ + public function set_upperboundmonth($upperboundmonth) { + $this->upperboundmonth = $upperboundmonth; + } + + /** + * Set upperboundyear. + * + * @param string $upperboundyear + * @return void + */ + public function set_upperboundyear($upperboundyear) { + $this->upperboundyear = $upperboundyear; + } + // MARK get. /** - * Is this item available as a parent? + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get downloadformat. * - * @return the content of the static property "canbeparent" + * @return $this->downloadformat */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get defaultvaluemonth. + * + * @return $this->defaultvaluemonth + */ + public function get_defaultvaluemonth() { + return $this->defaultvaluemonth; + } + + /** + * Get defaultvalueyear. + * + * @return $this->defaultvalueyear + */ + public function get_defaultvalueyear() { + return $this->defaultvalueyear; + } + + /** + * Get lowerboundmonth. + * + * @return $this->lowerboundmonth + */ + public function get_lowerboundmonth() { + return $this->lowerboundmonth; + } + + /** + * Get lowerboundyear. + * + * @return $this->lowerboundyear + */ + public function get_lowerboundyear() { + return $this->lowerboundyear; + } + + /** + * Get upperboundmonth. + * + * @return $this->upperboundmonth + */ + public function get_upperboundmonth() { + return $this->upperboundmonth; + } + + /** + * Get upperboundyear. + * + * @return $this->upperboundyear + */ + public function get_upperboundyear() { + return $this->upperboundyear; } /** @@ -347,14 +505,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvalueyear', 'defaultvaluemonth', 'lowerboundyear', 'lowerboundmonth', 'upperboundyear', 'upperboundmonth', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_shortdate'] = []; return $fieldlist; } @@ -371,30 +545,11 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - + + + @@ -428,8 +583,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_shortdate_'.$this->sortindex; - // Begin of: element values. $months = []; $years = []; @@ -455,60 +608,50 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_shortdate_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_month'; - $attributes['id'] = $idprefix.'_month'; - $attributes['class'] = 'indent-'.$this->indent.' shortdate_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $months, $attributes); - - $itemname = $this->itemname.'_year'; - $attributes['id'] = $idprefix.'_year'; - $attributes['class'] = 'shortdate_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $years, $attributes); + $attributes['id'] = $baseid.'_month'; + $elementgroup[] = $mform->createElement('select', $basename.'_month', '', $months, $attributes); + $attributes['id'] = $baseid.'_year'; + $elementgroup[] = $mform->createElement('select', $basename.'_year', '', $years, $attributes); if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'shortdate_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -521,7 +664,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $shortdatearray['year'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -557,12 +700,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_month', $shortdatearray['mon']); - $mform->setDefault($this->itemname.'_year', $shortdatearray['year']); + $mform->setDefault($basename.'_month', $shortdatearray['mon']); + $mform->setDefault($basename.'_year', $shortdatearray['year']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -581,13 +724,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { // If ($this->required) { if (empty($data[$this->itemname])) { is useless. if (isset($data[$this->itemname.'_noanswer'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -614,13 +757,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_shortdatenotset', 'surveyprofield_shortdate', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_shortdate_to_unix_time(1, $this->surveypro->startyear)); @@ -641,6 +784,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_shortdate'); } } + + return $errors; } /** diff --git a/field/shortdate/classes/itemsetupform.php b/field/shortdate/classes/itemsetupform.php index fc41dcedec6..602da7881fa 100644 --- a/field/shortdate/classes/itemsetupform.php +++ b/field/shortdate/classes/itemsetupform.php @@ -61,7 +61,7 @@ public function definition() { $fieldname = 'defaultoption'; $months = []; for ($i = 1; $i <= 12; $i++) { - $months[$i] = userdate(mktime(12, 0, 0, $i, 1, 2000), "%B", 0); + $months[$i] = userdate(gmmktime(12, 0, 0, $i, 1, 2000), "%B", 0); } $yearsrange = range($startyear, $stopyear); $years = array_combine($yearsrange, $yearsrange); diff --git a/field/shortdate/db/install.xml b/field/shortdate/db/install.xml index fab3dad8a14..8e088206483 100644 --- a/field/shortdate/db/install.xml +++ b/field/shortdate/db/install.xml @@ -1,34 +1,18 @@ -
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/field/shortdate/db/upgrade.php b/field/shortdate/db/upgrade.php index e9dd82e7c9d..2be5f2c3ae2 100644 --- a/field/shortdate/db/upgrade.php +++ b/field/shortdate/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_shortdate_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Shortdate savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'shortdate'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_shortdate. + $table = new xmldb_table('surveyprofield_shortdate'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_shortdate} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Shortdate savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'shortdate'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_shortdate'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_shortdate. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_shortdate} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Shortdate savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'shortdate'); + } + return true; } diff --git a/field/shortdate/lang/en/surveyprofield_shortdate.php b/field/shortdate/lang/en/surveyprofield_shortdate.php index b308f625025..75c54889b8b 100644 --- a/field/shortdate/lang/en/surveyprofield_shortdate.php +++ b/field/shortdate/lang/en/surveyprofield_shortdate.php @@ -25,18 +25,19 @@ $string['currentshortdatedefault'] = 'Current short date'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the short date the remote user will find answered by default. The default for this type of question is mandatory. If "Current short date" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the short date the remote user will find answered by default. The default for this type of question is mandatory. If "Current short date" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; $string['ierr_lowergreaterthanupper'] = 'Lower bound must be lower than upper bound'; $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitemonth'] = 'Choose a month'; $string['inviteyear'] = 'Choose a year'; -$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest date the user is allowed to enter'; $string['pluginname'] = 'Short date'; +$string['privacy:metadata'] = 'The "Short date" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; @@ -51,7 +52,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_shortdatenotset'] = 'Please choose a short date or select "{$a}" checkbox'; $string['uerr_shortdatenotsetrequired'] = 'Short date is not correctly defined'; -$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest date the user is allowed to enter'; $string['userfriendlypluginname'] = 'Date (short) [mm/yyyy]'; -$string['privacy:metadata'] = 'The "Short date" field plugin does not store any personal data.'; diff --git a/field/shortdate/tests/behat/itemform.feature b/field/shortdate/tests/behat/itemform.feature index 2e09e715814..95791b8304d 100644 --- a/field/shortdate/tests/behat/itemform.feature +++ b/field/shortdate/tests/behat/itemform.feature @@ -102,6 +102,6 @@ Feature: Create a shortdate item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a When did you buy your current car?" - Then the field "id_surveypro_field_shortdate_2_month" matches value "January" - Then the field "id_surveypro_field_shortdate_2_year" matches value "2014" + Then the field "id_field_shortdate_2_month" matches value "January" + Then the field "id_field_shortdate_2_year" matches value "2014" Then I should see "Additional note" diff --git a/field/shortdate/tests/behat/submit_shortdate.feature b/field/shortdate/tests/behat/submit_shortdate.feature index 55f758150fd..e2685a74433 100644 --- a/field/shortdate/tests/behat/submit_shortdate.feature +++ b/field/shortdate/tests/behat/submit_shortdate.feature @@ -43,8 +43,8 @@ Feature: Submit using a shortdate item # student1 submits And I set the following fields to these values: - | id_surveypro_field_shortdate_1_month | March | - | id_surveypro_field_shortdate_1_year | 2005 | + | id_field_shortdate_1_month | March | + | id_field_shortdate_1_year | 2005 | And I press "Submit" diff --git a/field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml b/field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml similarity index 88% rename from field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml rename to field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml index 9d64f2c3353..55a1e4d9b23 100644 --- a/field/shortdate/tests/fixtures/usertemplate/dateshort_only_2023103100.xml +++ b/field/shortdate/tests/fixtures/usertemplate/date_(short)_only_2024032800.xml @@ -1,39 +1,34 @@ - + + <h5>SHORT DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>shortdate specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>SHORT DATE</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>shortdate specific setting</b>:</p><ol><li>Default</li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 @@ -42,6 +37,11 @@ 1 0 shortdate_001 + 0 + 0 + 0 + + 2 39600 strftime01 @@ -49,35 +49,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 2 - 0 + 1 shortdate_002 + 0 + 0 + 0 + + 1 1254391200 strftime01 @@ -85,35 +84,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 3 - 0 + 1 shortdate_003 + 0 + 0 + 0 + + 4 39600 strftime01 @@ -121,35 +119,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 4 - 0 + 1 shortdate_004 + 0 + 0 + 0 + + 5 39600 strftime01 @@ -157,35 +154,34 @@ 1417431600 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 0 0 0 - 5 - 0 + 1 shortdate_005 + 0 + 0 + 0 + + 3 39600 strftime01 @@ -193,35 +189,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 6 - 0 + 1 shortdate_006 + 0 + 0 + 0 + + 2 39600 strftime01 @@ -229,35 +224,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to a valid value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read). - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 7 - 0 + 1 shortdate_007 + 0 + 0 + 0 + + 1 1254391200 strftime01 @@ -265,35 +259,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 8 - 0 + 1 shortdate_008 + 0 + 0 + 0 + + 4 39600 strftime01 @@ -301,35 +294,34 @@ 1417431600 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>input is forced in the time window 1990-2014</li><li>the default is set to the current date</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) otherwise he/she is forced to choose a different date. - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - When did you buy your current car? 1 1 0 0 - 9 - 0 + 1 shortdate_009 + 0 + 0 + 0 + + 5 39600 strftime01 diff --git a/field/shortdate/version.php b/field/shortdate/version.php index 955149762a8..6d18f22132b 100644 --- a/field/shortdate/version.php +++ b/field/shortdate/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_shortdate'; // Full name of the plugin (used for diagnostics). diff --git a/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php b/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php index 1a2e20fea00..8d9b7f4da53 100644 --- a/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php +++ b/field/textarea/backup/moodle2/backup_surveyprofield_textarea_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'textarea'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugintextarea = new backup_nested_element('surveyprofield_textarea', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', 'trimonsave', - 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength', ]); + 'trimonsave', 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/textarea/classes/item.php b/field/textarea/classes/item.php index e9c52182c0e..f67d1800c87 100644 --- a/field/textarea/classes/item.php +++ b/field/textarea/classes/item.php @@ -40,58 +40,13 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; + // Itembase properties. /** - * @var boolean True if the user input will be trimmed at save time + * @var bool True if the user input will be trimmed at save time */ protected $trimonsave; - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; - /** * @var bool Does the item use html editor? */ @@ -117,6 +72,13 @@ class item extends itembase { */ protected $maxlength; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -149,7 +111,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -181,14 +145,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. + // Set properties at plugin level and then continue to base level. - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -201,18 +161,13 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Text (long)'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'textarea_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { + // $record->trimonsave $record->useeditor = 0; $record->arearows = 10; $record->areacols = 60; $record->minlength = 0; + // $record->maxlength } /** @@ -231,7 +186,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. if (!core_text::strlen($record->minlength)) { @@ -262,47 +217,149 @@ public function item_custom_fields_to_db($record) { // 4. Other. } - // MARK get. + // MARK set. /** - * Is this item available as a parent? + * Set trimonsave. * - * @return the content of the static property "canbeparent" + * @param string $trimonsave + * @return void */ - public static function get_canbeparent() { - return self::$canbeparent; + public function set_trimonsave($trimonsave) { + $this->trimonsave = $trimonsave; } /** - * Make the list of the fields using multilang + * Set useeditor. * - * @return array of felds + * @param string $useeditor + * @return void */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function set_useeditor($useeditor) { + $this->useeditor = $useeditor; + } - return $fieldlist; + /** + * Set arearows. + * + * @param string $arearows + * @return void + */ + public function set_arearows($arearows) { + $this->arearows = $arearows; + } + + /** + * Set areacols. + * + * @param string $areacols + * @return void + */ + public function set_areacols($areacols) { + $this->areacols = $areacols; + } + + /** + * Set minlength. + * + * @param string $minlength + * @return void + */ + public function set_minlength($minlength) { + $this->minlength = $minlength; + } + + /** + * Set maxlength. + * + * @param string $maxlength + * @return void + */ + public function set_maxlength($maxlength) { + $this->maxlength = $maxlength; } + // MARK get. + /** - * Does the user input need trim? + * Get trimonsave. * - * @return if this plugin requires a user input trim + * @return $this->trimonsave */ public function get_trimonsave() { return $this->trimonsave; } /** - * Get use editor. + * Get useeditor. * - * @return the content of $useeditor property + * @return $this->useeditor */ - public function get_useseditor() { + public function get_useeditor() { return $this->useeditor; } + /** + * Get arearows. + * + * @return $this->arearows + */ + public function get_arearows() { + return $this->arearows; + } + + /** + * Get areacols. + * + * @return $this->areacols + */ + public function get_areacols() { + return $this->areacols; + } + + /** + * Get minlength. + * + * @return $this->minlength + */ + public function get_minlength() { + return $this->minlength; + } + + /** + * Get maxlength. + * + * @return $this->maxlength + */ + public function get_maxlength() { + return $this->maxlength; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['trimonsave', 'useeditor', 'arearows', 'areacols', 'minlength', 'maxlength']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + + /** + * Make the list of the fields using multilang + * + * @param boolean $includemetafields + * @return array of fields + */ + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_textarea'] = []; + + return $fieldlist; + } + /** * Return the xml schema for surveypro_<> table. * @@ -315,29 +372,10 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -393,41 +431,38 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_textarea_'.$this->sortindex; - $attributes = []; - $attributes['id'] = $idprefix; + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_textarea_'.$this->sortindex; + $basename = $this->itemname; + + $attributes['id'] = $baseid; $attributes['rows'] = $this->arearows; $attributes['cols'] = $this->areacols; if (empty($this->useeditor) || ($searchform)) { - $fieldname = $this->itemname; - $attributes['class'] = 'indent-'.$this->indent.' textarea_textarea'; $attributes['wrap'] = 'virtual'; if (!$searchform) { - $mform->addElement('mod_surveypro_textarea_plain', $fieldname, $elementlabel, $attributes); - $mform->setType($fieldname, PARAM_TEXT); + $elementgroup[] = $mform->createElement('textarea', $basename, $elementlabel, $attributes); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename, PARAM_TEXT); } else { - $elementgroup = []; - $elementgroup[] = $mform->createElement('mod_surveypro_textarea_plain', $fieldname, $elementlabel, $attributes); + $elementgroup[] = $mform->createElement('textarea', $basename, $elementlabel, $attributes); - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'textarea_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - // Note: $attributes['class'] and $attributes['id'] do not work: MDL_28194. - $attributes['class'] = 'indent-'.$this->indent.' textarea_editor'; - $fieldname = $this->itemname.'_editor'; + $fieldname = $basename.'_editor'; $editoroptions = ['trusttext' => true, 'subdirs' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES]; - $mform->addElement('mod_surveypro_textarea_editor', $fieldname, $elementlabel, $attributes, $editoroptions); - $mform->setType($fieldname, PARAM_CLEANHTML); + $elementgroup[] = $mform->createElement('editor', $basename.'_editor', $elementlabel, $attributes, $editoroptions); + $mform->addGroup($elementgroup, $basename.'_editor'.'_group', $elementlabel, ' ', false, $class); + $mform->setType($basename.'_editor', PARAM_CLEANHTML); } if (!$searchform) { @@ -436,7 +471,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $fieldname; + if ($this->position == SURVEYPRO_POSITIONTOP) { + $starplace = $basename.'_extrarow_group'; + } else { + $starplace = empty($this->useeditor) ? $basename.'_group' : $basename.'_editor_group'; + } $mform->_required[] = $starplace; } } @@ -452,38 +491,52 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { if ($searchform) { - return; + return $errors; } if (!empty($this->useeditor)) { - $errorkey = $this->itemname.'_editor'; + $errorkey = $this->itemname.'_editor_group'; $fieldname = $this->itemname.'_editor'; - $itemcontent = $data[$fieldname]['text']; + $userinput = $data[$fieldname]['text']; } else { - $errorkey = $this->itemname; + $errorkey = $this->itemname.'_group'; $fieldname = $this->itemname; - $itemcontent = $data[$fieldname]; + $userinput = $data[$fieldname]; } + // If trimonsave is asked, make the validation on trimmed text. if ($this->trimonsave) { - $itemcontent = trim($itemcontent); + if (trim($userinput) != $userinput) { + $warnings[$errorkey] = get_string('uerr_willbetrimmed', 'mod_surveypro'); + } + + // The variable $userinput is not going to be saved. I can freely modify it. + $userinput = trim($userinput); } - if (empty($itemcontent)) { + // If $userinput is empty the story stops here. It doesn't matter if there were requirements on the answer. + if (empty($userinput)) { if ($this->required) { $errors[$errorkey] = get_string('required'); } - return; + return $errors; } // I don't care if this element is required or not. - // If the user provides an answer, it has to be compliant with the field validation rules. - if ( $this->maxlength && (\core_text::strlen($itemcontent) > $this->maxlength) ) { + // If the user provided an answer, it has to be compliant with the field validation rules. + if ( $this->maxlength && (\core_text::strlen($userinput) > $this->maxlength) ) { $errors[$errorkey] = get_string('uerr_texttoolong', 'surveyprofield_textarea'); } - if (\core_text::strlen($itemcontent) < $this->minlength) { + if (\core_text::strlen($userinput) < $this->minlength) { $errors[$errorkey] = get_string('uerr_texttooshort', 'surveyprofield_textarea'); } + + if ( $errors && isset($warnings) ) { + // Always sum $warnings to $errors so if an element has a warning and an error too, the error it will be preferred. + $errors = array_merge($warnings, $errors); + } + + return $errors; } /** @@ -595,15 +648,6 @@ public function userform_get_root_elements_name() { return $elementnames; } - /** - * Does the user input need trim? - * - * @return if this plugin requires a user input trim - */ - public static function userform_input_needs_trim() { - return true; - } - /** * Starting from the info stored into $answer, this function returns the corresponding content for the export file. * diff --git a/field/textarea/classes/itemsetupform.php b/field/textarea/classes/itemsetupform.php index febd3f624bc..457151b5fe0 100644 --- a/field/textarea/classes/itemsetupform.php +++ b/field/textarea/classes/itemsetupform.php @@ -77,7 +77,7 @@ public function definition() { $mform->setType($fieldname, PARAM_INT); $mform->setDefault($fieldname, SURVEYPROFIELD_TEXTAREA_DEFAULTCOLS); - // Item: trimonsave. + // Itembase: trimonsave. $fieldname = 'trimonsave'; $mform->addElement('checkbox', $fieldname, get_string($fieldname, 'surveyprofield_textarea')); $mform->addHelpButton($fieldname, $fieldname, 'surveyprofield_textarea'); diff --git a/field/textarea/db/install.xml b/field/textarea/db/install.xml index 17a8f159aa6..e46b6b6a62f 100644 --- a/field/textarea/db/install.xml +++ b/field/textarea/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/textarea/db/upgrade.php b/field/textarea/db/upgrade.php index 8df9df5789f..89ceab7550d 100644 --- a/field/textarea/db/upgrade.php +++ b/field/textarea/db/upgrade.php @@ -100,9 +100,70 @@ function xmldb_surveyprofield_textarea_upgrade($oldversion) { // Launch rename field nexttrimonsave to trimonsave. $dbman->rename_field($table, $newfield, 'trimonsave'); - // Character savepoint reached. + // Textarea savepoint reached. upgrade_plugin_savepoint(true, 2024020700, 'surveyprofield', 'textarea'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_textarea. + $table = new xmldb_table('surveyprofield_textarea'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_textarea} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Textarea savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'textarea'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_textarea'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_textarea. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_textarea} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Textarea savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'textarea'); + } + return true; } diff --git a/field/textarea/lang/en/surveyprofield_textarea.php b/field/textarea/lang/en/surveyprofield_textarea.php index 0a29a76bd8b..01efe9af029 100644 --- a/field/textarea/lang/en/surveyprofield_textarea.php +++ b/field/textarea/lang/en/surveyprofield_textarea.php @@ -23,27 +23,27 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['areacols_help'] = 'Define a custom width for the text area (This option is not applied in conjunction with "Use html editor")'; $string['areacols'] = 'Area width in columns'; -$string['arearows_help'] = 'Define a custom height for the text area'; +$string['areacols_help'] = 'Define a custom width for the text area (This option is not applied in conjunction with "Use html editor")'; $string['arearows'] = 'Area height in rows'; +$string['arearows_help'] = 'Define a custom height for the text area'; $string['hasmaxlength'] = 'Text is supposed to be shorter or equal than {$a} characters'; $string['hasminlength'] = 'Text is supposed to be longer or equal than {$a} characters'; $string['hasminmaxlength'] = 'Text is supposed to fit between {$a->minlength} and {$a->maxlength} characters'; -$string['ierr_maxlengthlowerthanminlength'] = 'Maximum length can not be lowwer-equal than minimum length'; +$string['ierr_maxlengthlowerthanminlength'] = 'Maximum length can not be lower-equal than minimum length'; $string['ierr_maxlengthnotinteger'] = 'Maximum length must be integer'; $string['ierr_minlengthnotinteger'] = 'Minimum length must be integer'; $string['ierr_requirednozerolength'] = 'Required item can not allow a zero length test'; -$string['maxlength_help'] = 'The maximun number of allowed characters for the answer. Empty for unlimited length.'; $string['maxlength'] = 'Maximum length (in characters)'; -$string['minlength_help'] = 'The minimun number of allowed characters for the answer to this question'; +$string['maxlength_help'] = 'The maximun number of allowed characters for the answer. Empty for unlimited length.'; $string['minlength'] = 'Minimum length (in characters)'; +$string['minlength_help'] = 'The minimun number of allowed characters for the answer to this question'; $string['pluginname'] = 'Text area'; $string['privacy:metadata'] = 'The "Textarea" field plugin does not store any personal data.'; -$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['trimonsave'] = 'Clean answer at save time'; +$string['trimonsave_help'] = 'Delete trailing spaces at the beginning and at the end of the user input.'; $string['uerr_texttoolong'] = 'Text is too long'; $string['uerr_texttooshort'] = 'Text is too short'; -$string['useeditor_help'] = 'Is the answer supposed to be in plain text or in html?'; $string['useeditor'] = 'Use html editor'; +$string['useeditor_help'] = 'Is the answer supposed to be in plain text or in html?'; $string['userfriendlypluginname'] = 'Text (long)'; diff --git a/field/textarea/lang/es_mx/surveyprofield_textarea.php b/field/textarea/lang/es_mx/surveyprofield_textarea.php index f2af6c380ea..cd55364bbe8 100644 --- a/field/textarea/lang/es_mx/surveyprofield_textarea.php +++ b/field/textarea/lang/es_mx/surveyprofield_textarea.php @@ -25,24 +25,24 @@ defined('MOODLE_INTERNAL') || die(); -$string['areacols_help'] = 'Definir un ancho personalizado para el área de texto'; $string['areacols'] = 'Ancho del área en columnas'; -$string['arearows_help'] = 'Definir un ancho personalizado para el área de texto'; +$string['areacols_help'] = 'Definir un ancho personalizado para el área de texto'; $string['arearows'] = 'Altura del área en filas'; +$string['arearows_help'] = 'Definir un ancho personalizado para el área de texto'; $string['hasmaxlength'] = 'Se supone que el texto sea menor o igual a {$a} caracteres'; $string['hasminlength'] = 'Se supone que el texto sea mayor o igual a {$a} caracteres'; $string['hasminmaxlength'] = 'Se supone que el texto tenga entre {$a->minlength} y {$a->maxlength} caracteres'; $string['ierr_maxlengthlowerthanminlength'] = 'La longitud máxima no puede ser menor o igual a la longitud mínima'; $string['ierr_maxlengthnotinteger'] = 'La longitud máxima debe ser un número entero'; -$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación. Dejar vacío para longitud ilimitada.'; $string['maxlength'] = 'Longitud máxima (en caracteres)'; -$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; +$string['maxlength_help'] = 'El número máximo de caracteres permitidos para la contestación. Dejar vacío para longitud ilimitada.'; $string['minlength'] = 'Longitud mínima (en caracteres)'; +$string['minlength_help'] = 'El número mínimo de caracteres permitidos para la contestación a esta pregunta'; $string['pluginname'] = 'Área de texto'; -$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['trimonsave'] = 'Contestación limpia al momento de guardar'; +$string['trimonsave_help'] = 'Eliminar espacios sobrantes al principio y final de la entrada del usuario.'; $string['uerr_texttoolong'] = 'El texto es demasiado largo'; $string['uerr_texttooshort'] = 'El texto es demasiado corto'; -$string['useeditor_help'] = '¿Se supone que la contestación sea en texto simple o HTML?'; $string['useeditor'] = 'Usar editor HTML'; +$string['useeditor_help'] = '¿Se supone que la contestación sea en texto simple o HTML?'; $string['userfriendlypluginname'] = 'Texto (largo)'; diff --git a/field/textarea/lang/it/surveyprofield_textarea.php b/field/textarea/lang/it/surveyprofield_textarea.php index e6508ae3a35..ed61278a8c2 100644 --- a/field/textarea/lang/it/surveyprofield_textarea.php +++ b/field/textarea/lang/it/surveyprofield_textarea.php @@ -23,23 +23,23 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['areacols_help'] = 'Larghezza dell\'area di testo (verrà trascurato se si sceglie di usare l\'editor html)'; $string['areacols'] = 'Larghezza dell\'area in colonne'; -$string['arearows_help'] = 'Altezza dell\'area di testo'; +$string['areacols_help'] = 'Larghezza dell\'area di testo (verrà trascurato se si sceglie di usare l\'editor html)'; $string['arearows'] = 'Altezza dell\'area in righe'; +$string['arearows_help'] = 'Altezza dell\'area di testo'; $string['hasmaxlength'] = 'Il testo deve essere al massimo di {$a} caratteri'; $string['hasminlength'] = 'Il testo deve essere almeno di {$a} caratteri'; $string['hasminmaxlength'] = 'Il testo deve avere un numero di caratteri compreso fra {$a->minlength} e {$a->maxlength}'; $string['ierr_maxlengthlowerthanminlength'] = 'La lunghezza massima del testo non può essere inferiore alla lunghezza minima'; $string['ierr_maxlengthnotinteger'] = 'La lunghezza massima deve essere un numero intero'; -$string['maxlength_help'] = 'Il massimo numero di caratteri di una risposta. Lasciare vuoto per consentite una lunghezza illimitata.'; $string['maxlength'] = 'Lunghezza massima (in caratteri)'; -$string['minlength_help'] = 'Il minimo numero di caratteri di una risposta'; +$string['maxlength_help'] = 'Il massimo numero di caratteri di una risposta. Lasciare vuoto per consentite una lunghezza illimitata.'; $string['minlength'] = 'Lunghezza minima (in caratteri)'; +$string['minlength_help'] = 'Il minimo numero di caratteri di una risposta'; $string['pluginname'] = 'Regione di testo'; $string['privacy:metadata'] = 'La plugin "Testo (lungo)" con contiene alcun dato personale.'; $string['uerr_texttoolong'] = 'Il testo è troppo lungo'; $string['uerr_texttooshort'] = 'Il testo è troppo corto'; -$string['useeditor_help'] = 'La risposta deve essere in testo privo di formattazione o arricchita da tag html?'; $string['useeditor'] = 'Usa l\'editor html'; +$string['useeditor_help'] = 'La risposta deve essere in testo privo di formattazione o arricchita da tag html?'; $string['userfriendlypluginname'] = 'Testo (lungo)'; diff --git a/field/textarea/mform/textarea_editor.php b/field/textarea/mform/textarea_editor.php deleted file mode 100644 index dcc5d5e48b1..00000000000 --- a/field/textarea/mform/textarea_editor.php +++ /dev/null @@ -1,119 +0,0 @@ -. - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/editor.php'); - -// @codingStandardsIgnoreFile - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_textarea_editor extends \MoodleQuickForm_editor { - - /** - * Constructor. - * - * @param string $elementName Optional name of the editor - * @param string $elementLabel Optional editor label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filepicker - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * My intervention only replaces
with
AT THE BEGINNING of $output - * I use the output of parent::toHtml() to get advantages of future updates to core mform class - * I search for simple
without attributes so that if moodle HQ will ever fix this issue in the core code, - * my intervention will result in nothing without adding useless or dangerous modifications - * - * @return string - */ - public function toHtml() { - // The core code is ONLY MISSING the class in the first
. - // I add it with a simple replace. - $output = parent::toHtml(); // Core code. - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
~'; - $class = empty($this->_attributes['class']) ? 'indent-0' : $this->_attributes['class']; - $replacement = $tabs.'
'; - $output = preg_replace($pattern, $replacement, $output); - - return $output; - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml(): string { - $complexvalue = $this->getValue(); - $value = core_text::strlen($complexvalue['text']) ? $complexvalue['text'] : ' '; - - $class = array(); - $class['id'] = $this->getAttribute('id'); - $class['name'] = $this->getAttribute('name'); - if (empty($this->_attributes['class'])) { - $class['class'] = 'indent-0 '; - } else { - $class['class'] = $this->_attributes['class']; - } - $class['readonly'] = 'true'; - - $output = $this->_getTabs(); - $output .= \html_writer::start_tag('textarea', $class); - $output .= $value; - $output .= \html_writer::end_tag('textarea'); - $output .= $this->_getPersistantData(); - - return $output; - } -} diff --git a/field/textarea/mform/textarea_plain.php b/field/textarea/mform/textarea_plain.php deleted file mode 100644 index c30904f8311..00000000000 --- a/field/textarea/mform/textarea_plain.php +++ /dev/null @@ -1,120 +0,0 @@ -. - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/textarea.php'); - -// @codingStandardsIgnoreFile - -/** - * editor form element - * - * HTML class for a editor type element - * - * @package surveyprofield_textarea - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_textarea_plain extends \MoodleQuickForm_textarea { - - /** - * Constructor. - * - * @param string $elementName Optional name of the editor - * @param string $elementLabel Optional editor label - * @param array $attributes Optional either a typical HTML attribute string - * or an associative array - * @param array $options set of options to initalize filepicker - */ - public function __construct($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - parent::__construct($elementName, $elementLabel, $attributes, $options); - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * My intervention only replaces
with
AT THE BEGINNING of $output - * I use the output of parent::toHtml() to get advantages of future updates to core mform class - * I search for simple
without attributes so that if moodle HQ will ever fix this issue in the core code, - * my intervention will result in nothing without adding useless or dangerous modifications - * - * @return string - */ - public function toHtml() { - // The core code is ONLY MISSING the class in the first
. - // I add it with a simple replace. - $output = parent::toHtml(); // Core code. - - $tabs = $this->_getTabs(); - $pattern = '~^'.$tabs.'
~'; - $class = empty($this->_attributes['class']) ? 'indent-0' : $this->_attributes['class']; - $replacement = $tabs.'
'; - $output = preg_replace($pattern, $replacement, $output); - return $output; - } - - /** - * What to display when element is frozen. - * - * @return html of the frozen element - */ - public function getFrozenHtml() { - $value = htmlspecialchars($this->getValue()); - $value = nl2br($value); - $value = core_text::strlen($value) ? $value : ' '; - - $class = array(); - $class['id'] = $this->getAttribute('id'); - $class['name'] = $this->getAttribute('name'); - if (empty($this->_attributes['class'])) { - $class['class'] = 'indent-0 '; - } else { - $class['class'] = $this->_attributes['class']; - } - $class['readonly'] = 'true'; - - $output = $this->_getTabs(); - // $output .= \html_writer::tag('div', $value, $class); - $output .= \html_writer::start_tag('textarea', $class); - $output .= $value; - $output .= \html_writer::end_tag('textarea'); - $output .= $this->_getPersistantData(); - - return $output; - } -} diff --git a/field/textarea/tests/behat/itemform.feature b/field/textarea/tests/behat/itemform.feature index 90280df01f3..4511c2c7031 100644 --- a/field/textarea/tests/behat/itemform.feature +++ b/field/textarea/tests/behat/itemform.feature @@ -50,7 +50,7 @@ Feature: Create a textarea item | Maximum length (in characters) | 4 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" And I set the field "Maximum length (in characters)" to "40" And I press "Add" @@ -94,4 +94,4 @@ Feature: Create a textarea item And I select "Preview" from the "jump" singleselect Then I should see "II.b Write a short description of yourself" Then I should see "One more additional note" - Then "//textarea[contains(@id, 'id_surveypro_field_textarea_3')]" "xpath_element" should exist + Then "//textarea[contains(@id, 'id_field_textarea_3')]" "xpath_element" should exist diff --git a/field/textarea/tests/behat/settings_configuration.feature b/field/textarea/tests/behat/settings_configuration.feature index f09874a7964..b6c72ff43e3 100644 --- a/field/textarea/tests/behat/settings_configuration.feature +++ b/field/textarea/tests/behat/settings_configuration.feature @@ -42,7 +42,7 @@ Feature: Submit using textarea item and check form validation | Minimum length (in characters) | 20 | | Maximum length (in characters) | 1 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" And I set the field "Maximum length (in characters)" to "" And I press "Add" # End of test number 1 @@ -123,7 +123,7 @@ Feature: Submit using textarea item and check form validation | Minimum length (in characters) | 20 | | Maximum length (in characters) | 1 | And I press "Add" - Then I should see "Maximum length can not be lowwer-equal than minimum length" + Then I should see "Maximum length can not be lower-equal than minimum length" # End of test number 8 # if the corresponding field is submitted when still empty diff --git a/field/textarea/tests/behat/trim.feature b/field/textarea/tests/behat/trim.feature index 908ba2300f8..ddfcff78a86 100644 --- a/field/textarea/tests/behat/trim.feature +++ b/field/textarea/tests/behat/trim.feature @@ -61,6 +61,7 @@ Feature: Trim textarea content And I press "New response" And I set the field "This is a standard text" to " false long text " And I set the field "Text to trim" to " false long text " + And I press "Submit" Then I should see "Text is too short" @@ -75,5 +76,5 @@ Feature: Trim textarea content And I press "Continue to responses list" And I follow "edit_submission_row_1" - Then the field "id_surveypro_field_textarea_1" matches value " false long text " - Then the field "id_surveypro_field_textarea_2" matches value "text correctly trimmed" + Then the field "id_field_textarea_1" matches value " false long text " + Then the field "id_field_textarea_2" matches value "text correctly trimmed" diff --git a/field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml b/field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml similarity index 87% rename from field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml rename to field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml index 77e50f56b8f..55c92e1b9d3 100644 --- a/field/textarea/tests/fixtures/usertemplate/textarea_only_2015123000.xml +++ b/field/textarea/tests/fixtures/usertemplate/textarea_only_2024032800.xml @@ -1,159 +1,155 @@ - + + <h5>TEXTAREA<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Use html editor</li><li>Area heigh in rows</li><li>Area width in columns<br /></li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>TEXTAREA<br /></h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only two <b>date specific setting</b>:</p><ol><li>Use html editor</li><li>Area heigh in rows</li><li>Area width in columns<br /></li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Minimum length (in characters)</li><li>Maximum length (in characters)<br /></li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> + 1 + 0 + 1 intro 0 0 0 - <ul><li>mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 1 0 0 - 1 - 0 + 1 textarea_001 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 - + + <ul><li>not mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>use html editor<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 0 0 0 - 2 - 0 + 1 textarea_002 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 - + + <ul><li>mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> + 1 + 0 + 3 intro 0 0 0 - <ul><li>mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is mandatory and the user is supposed to enter a text.</p> - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 1 0 0 - 3 - 0 + 1 textarea_003 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 - + + <ul><li>not mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory<br /></li><li>use simple text area<br /></li></ul><p>Behaviour: The item is not mandatory and the user is supposed to enter a text or to leave the textarea blank.</p> - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - Write a short description of yourself 1 0 0 0 - 4 - 0 + 1 textarea_004 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 diff --git a/field/textarea/version.php b/field/textarea/version.php index ec4cc0feccd..4643454e457 100644 --- a/field/textarea/version.php +++ b/field/textarea/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024020700; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_textarea'; // Full name of the plugin (used for diagnostics). diff --git a/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php b/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php index 2e5d1447098..879ee4be640 100644 --- a/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php +++ b/field/time/backup/moodle2/backup_surveyprofield_time_subplugin.class.php @@ -40,9 +40,8 @@ protected function define_item_subplugin_structure() { $subplugin = $this->get_subplugin_element(null, '../../plugin', 'time'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); $subplugintime = new backup_nested_element('surveyprofield_time', ['id'], [ - 'content', 'contentformat', - 'required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote', - 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', ]); + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + ]); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/field/time/classes/item.php b/field/time/classes/item.php index be43e0bb242..e185ca6198d 100644 --- a/field/time/classes/item.php +++ b/field/time/classes/item.php @@ -39,52 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; - - /** - * @var int SURVEYPRO_POSITIONLEFT, SURVEYPRO_POSITIONTOP or SURVEYPRO_POSITIONFULLWIDTH - */ - protected $position; - - /** - * @var string Optional text with item custom note - */ - protected $extranote; - - /** - * @var bool 0 => optional item; 1 => mandatory item; - */ - protected $required; - - /** - * @var boolean True if the instructions are going to be shown in the form; false otherwise - */ - protected $hideinstructions; - - /** - * @var string Name of the field storing data in the db table - */ - protected $variable; - - /** - * @var int Indent of the item in the form page - */ - protected $indent; + // Itembase properties. /** * @var int Step for minutes drop down menu @@ -96,30 +51,37 @@ class item extends itembase { */ protected $defaultoption; + /** + * @var int Defaultvalue for the item answer + */ + protected $defaultvalue; + /** * @var string Format of the content once downloaded */ protected $downloadformat; /** - * @var int Defaultvalue for the time in unixtime + * @var int Lowerbound for the shortdate in unixtime */ - protected $defaultvalue; + protected $lowerbound; /** - * @var int Hour of the defaultvalue for the time + * @var int Upperbound for the shortdate in unixtime */ - protected $defaultvaluehour; + protected $upperbound; /** - * @var int Minute of the defaultvalue for the time + * @var int defaultvaluehour hours of defaultvalue */ - protected $defaultvalueminute; + protected $defaultvaluehour; /** - * @var int Lowerbound for the shortdate in unixtime + * @var int defaultvalueminute minutes of defaultvalue */ - protected $lowerbound; + protected $defaultvalueminute; + + // Service variables. /** * @var int Hour of the lowerbound for the time @@ -131,21 +93,23 @@ class item extends itembase { */ protected $lowerboundminute; - /** - * @var int Upperbound for the shortdate in unixtime - */ - protected $upperbound; - /** * @var int Hour of the upperbound for the time */ protected $upperboundhour; + // Service variables. + /** * @var int Minute of the upperbound for the time */ protected $upperboundminute; + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -178,7 +142,9 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. // Empty list. if (!empty($itemid)) { @@ -210,14 +176,10 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // Set custom fields value as defined for this question plugin. - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -230,14 +192,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Time'; - $record->contentformat = 1; - $record->position = 0; - $record->required = 0; - $record->hideinstructions = 0; - $record->variable = 'time_001'; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->step = 1; $record->defaultoption = SURVEYPRO_INVITEDEFAULT; $record->defaultvalue = 0; @@ -254,7 +209,7 @@ public function item_add_mandatory_plugin_fields(&$record) { * @return int unixtime */ public function item_time_to_unix_time($hour, $minute) { - $unixtime = mktime( + $unixtime = gmmktime( $hour, $minute, 0, SURVEYPROFIELD_TIME_MONTHOFFSET, SURVEYPROFIELD_TIME_DAYOFFSET, SURVEYPROFIELD_TIME_YEAROFFSET ); @@ -284,7 +239,7 @@ public function item_custom_fields_to_form() { * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. $fieldlist = $this->get_composite_fields(); foreach ($fieldlist as $field) { @@ -322,15 +277,216 @@ public function item_custom_fields_to_db($record) { // 4. Other. } + // MARK set. + + /** + * Set step. + * + * @param string $step + * @return void + */ + public function set_step($step) { + $this->step = $step; + } + + /** + * Set defaultoption. + * + * @param string $defaultoption + * @return void + */ + public function set_defaultoption($defaultoption) { + $this->defaultoption = $defaultoption; + } + + /** + * Set defaultvalue. + * + * @param string $defaultvalue + * @return void + */ + public function set_defaultvalue($defaultvalue) { + $this->defaultvalue = $defaultvalue; + } + + /** + * Set downloadformat. + * + * @param string $downloadformat + * @return void + */ + public function set_downloadformat($downloadformat) { + $this->downloadformat = $downloadformat; + } + + /** + * Set lowerbound. + * + * @param string $lowerbound + * @return void + */ + public function set_lowerbound($lowerbound) { + $this->lowerbound = $lowerbound; + } + + /** + * Set upperbound. + * + * @param string $upperbound + * @return void + */ + public function set_upperbound($upperbound) { + $this->upperbound = $upperbound; + } + + /** + * Set lowerboundhour. + * + * @param string $lowerboundhour + * @return void + */ + public function set_lowerboundhour($lowerboundhour) { + $this->lowerboundhour = $lowerboundhour; + } + + /** + * Set lowerboundminute. + * + * @param string $lowerboundminute + * @return void + */ + public function set_lowerboundminute($lowerboundminute) { + $this->lowerboundminute = $lowerboundminute; + } + + /** + * Set upperboundhour. + * + * @param string $upperboundhour + * @return void + */ + public function set_upperboundhour($upperboundhour) { + $this->upperboundhour = $upperboundhour; + } + + /** + * Set upperboundminute. + * + * @param string $upperboundminute + * @return void + */ + public function set_upperboundminute($upperboundminute) { + $this->upperboundminute = $upperboundminute; + } + // MARK get. /** - * Is this item available as a parent? + * Get step. + * + * @return $this->step + */ + public function get_step() { + return $this->step; + } + + /** + * Get defaultoption. + * + * @return $this->defaultoption + */ + public function get_defaultoption() { + return $this->defaultoption; + } + + /** + * Get defaultvalue. + * + * @return $this->defaultvalue + */ + public function get_defaultvalue() { + return $this->defaultvalue; + } + + /** + * Get defaultvaluehour. + * + * @return $this->defaultvaluehour + */ + public function get_defaultvaluehour() { + return $this->defaultvaluehour; + } + + /** + * Get defaultvalueminute. + * + * @return $this->defaultvalueminute + */ + public function get_defaultvalueminute() { + return $this->defaultvalueminute; + } + + /** + * Get downloadformat. + * + * @return $this->downloadformat + */ + public function get_downloadformat() { + return $this->downloadformat; + } + + /** + * Get lowerbound. + * + * @return $this->lowerbound + */ + public function get_lowerbound() { + return $this->lowerbound; + } + + /** + * Get upperbound. + * + * @return $this->upperbound + */ + public function get_upperbound() { + return $this->upperbound; + } + + /** + * Get lowerboundhour. + * + * @return $this->lowerboundhour + */ + public function get_lowerboundhour() { + return $this->lowerboundhour; + } + + /** + * Get lowerboundminute. * - * @return the content of the static property "canbeparent" + * @return $this->lowerboundminute */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_lowerboundminute() { + return $this->lowerboundminute; + } + + /** + * Get upperboundhour. + * + * @return $this->upperboundhour + */ + public function get_upperboundhour() { + return $this->upperboundhour; + } + + /** + * Get upperboundminute. + * + * @return $this->upperboundminute + */ + public function get_upperboundminute() { + return $this->upperboundminute; } /** @@ -369,14 +525,30 @@ public function get_friendlyformat() { return 'strftime01'; } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = [ + 'step', 'defaultoption', 'defaultvalue', 'downloadformat', 'lowerbound', 'upperbound', + 'defaultvaluehour', 'defaultvalueminute', 'lowerboundhour', 'lowerboundminute', 'upperboundhour', 'upperboundminute', + ]; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'extranote']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = $this->get_base_multilang_fields($includemetafields); + $fieldlist['surveyprofield_time'] = []; return $fieldlist; } @@ -393,31 +565,12 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - - + + - - - + + + @@ -446,8 +599,6 @@ public function userform_mform_element($mform, $searchform, $readonly) { $elementlabel = ' '; } - $idprefix = 'id_surveypro_field_time_'.$this->sortindex; - // Begin of: element values. $hours = []; $minutes = []; @@ -484,62 +635,52 @@ public function userform_mform_element($mform, $searchform, $readonly) { // Begin of: mform element. $attributes = []; $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $baseid = 'id_field_time_'.$this->sortindex; + $basename = $this->itemname; - $itemname = $this->itemname.'_hour'; - $attributes['id'] = $idprefix.'_hour'; - $attributes['class'] = 'indent-'.$this->indent.' time_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $hours, $attributes); - - $itemname = $this->itemname.'_minute'; - $attributes['id'] = $idprefix.'_minute'; - $attributes['class'] = 'time_select'; - $elementgroup[] = $mform->createElement('select', $itemname, '', $minutes, $attributes); + $attributes['id'] = $baseid.'_hour'; + $elementgroup[] = $mform->createElement('select', $basename.'_hour', '', $hours, $attributes); + $attributes['id'] = $baseid.'_minute'; + $elementgroup[] = $mform->createElement('select', $basename.'_minute', '', $minutes, $attributes); $separator = [':']; if ($this->required) { if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false); // Even if the item is required I CAN NOT ADD ANY RULE HERE because... // I do not want JS form validation if the page is submitted through the "previous" button. // I do not want JS field validation even if this item is required BUT disabled. See: MDL-34815. // Because of this, I simply add a dummy star to the item and the footer note about mandatory fields. - $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $this->itemname.'_extrarow' : $this->itemname.'_group'; + $starplace = ($this->position == SURVEYPRO_POSITIONTOP) ? $basename.'_extrarow_group' : $basename.'_group'; $mform->_required[] = $starplace; } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } else { - $itemname = $this->itemname.'_noanswer'; - $attributes['id'] = $idprefix.'_noanswer'; - $attributes['class'] = 'time_check'; + $attributes['id'] = $baseid.'_noanswer'; $noanswerstr = get_string('noanswer', 'mod_surveypro'); - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $noanswerstr, $attributes); + $elementgroup[] = $mform->createElement('checkbox', $basename.'_noanswer', '', $noanswerstr, $attributes); $separator[] = ' '; if (!$searchform) { - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, $separator, false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_noanswer', 'checked'); + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, $separator, false, $class); + $mform->disabledIf($basename.'_group', $basename.'_noanswer', 'checked'); } else { - $itemname = $this->itemname.'_ignoreme'; $starstr = get_string('star', 'mod_surveypro'); - $attributes['id'] = $idprefix.'_ignoreme'; - $attributes['class'] = 'character_check'; - $elementgroup[] = $mform->createElement('mod_surveypro_checkbox', $itemname, '', $starstr, $attributes); - $mform->setType($this->itemname, PARAM_RAW); - - $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, ' ', false); - $mform->disabledIf($this->itemname.'_group', $this->itemname.'_ignoreme', 'checked'); - $mform->setDefault($this->itemname.'_ignoreme', '1'); + $attributes['id'] = $baseid.'_ignoreme'; + $elementgroup[] = $mform->createElement('checkbox', $basename.'_ignoreme', '', $starstr, $attributes); + + $mform->addGroup($elementgroup, $basename.'_group', $elementlabel, ' ', false, $class); + $mform->disabledIf($basename.'_group', $basename.'_ignoreme', 'checked'); + $mform->setDefault($basename.'_ignoreme', '1'); } } // End of: mform element. @@ -552,7 +693,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { $timearray['minutes'] = SURVEYPRO_INVITEVALUE; break; case SURVEYPRO_NOANSWERDEFAULT: - $mform->setDefault($this->itemname.'_noanswer', '1'); + $mform->setDefault($basename.'_noanswer', '1'); // No break here. SURVEYPRO_CUSTOMDEFAULT case is a subset of the SURVEYPRO_NOANSWERDEFAULT case. case SURVEYPRO_CUSTOMDEFAULT: // I need to set a value for the default field even if it disabled. @@ -588,12 +729,12 @@ public function userform_mform_element($mform, $searchform, $readonly) { $message = 'Unexpected $this->defaultoption = '.$this->defaultoption; debugging('Error at line '.__LINE__.' of '.__FILE__.'. '.$message , DEBUG_DEVELOPER); } - $mform->setDefault($this->itemname.'_hour', $timearray['hours']); - $mform->setDefault($this->itemname.'_minute', $timearray['minutes']); + $mform->setDefault($basename.'_hour', $timearray['hours']); + $mform->setDefault($basename.'_minute', $timearray['minutes']); } if ($searchform) { if (!$this->required) { - $mform->setDefault($this->itemname.'_noanswer', '0'); + $mform->setDefault($basename.'_noanswer', '0'); } } // End of: default section. @@ -618,7 +759,7 @@ public function userform_mform_validation($data, &$errors, $searchform) { // Make validation in the search form too. // I can not use if ($searchform) { return; because I still need to validate the correcteness of the date. if (isset($data[$this->itemname.'_ignoreme'])) { - return; // Nothing to validate. + return $errors; // Nothing to validate. } $errorkey = $this->itemname.'_group'; @@ -645,13 +786,13 @@ public function userform_mform_validation($data, &$errors, $searchform) { $a = get_string('noanswer', 'mod_surveypro'); $errors[$errorkey] = get_string('uerr_timenotset', 'surveyprofield_time', $a); } - return; + return $errors; } // End of: verify the content of each drop down menu. if ($searchform) { // Stop here your investigation. I don't need further validations. - return; + return $errors; } $haslowerbound = ($this->lowerbound != $this->item_time_to_unix_time(0, 0)); @@ -685,6 +826,8 @@ public function userform_mform_validation($data, &$errors, $searchform) { $errors[$errorkey] = get_string('uerr_greaterthanmaximum', 'surveyprofield_time'); } } + + return $errors; } /** @@ -779,9 +922,9 @@ public function userform_get_prefill($fromdb) { return $prefill; } - $datearray = $this->item_split_unix_time($fromdb->content); - $prefill[$this->itemname.'_hour'] = $datearray['hours']; - $prefill[$this->itemname.'_minute'] = $datearray['minutes']; + $timearray = $this->item_split_unix_time($fromdb->content); + $prefill[$this->itemname.'_hour'] = $timearray['hours']; + $prefill[$this->itemname.'_minute'] = $timearray['minutes']; } // If the "No answer" checkbox is part of the element GUI... diff --git a/field/time/db/install.xml b/field/time/db/install.xml index 19e0cdb00f1..9374f7e5412 100644 --- a/field/time/db/install.xml +++ b/field/time/db/install.xml @@ -1,35 +1,19 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/field/time/db/upgrade.php b/field/time/db/upgrade.php index 1059375b9ec..4179aeadb6c 100644 --- a/field/time/db/upgrade.php +++ b/field/time/db/upgrade.php @@ -50,9 +50,70 @@ function xmldb_surveyprofield_time_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Time savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyprofield', 'time'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyprofield_time. + $table = new xmldb_table('surveyprofield_time'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_time} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Time savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyprofield', 'time'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyprofield_time'); + + $fieldnames = ['required', 'indent', 'position', 'customnumber', 'hideinstructions', 'variable', 'extranote']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyprofield_time. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyprofield_time} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Time savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyprofield', 'time'); + } + return true; } diff --git a/field/time/lang/en/surveyprofield_time.php b/field/time/lang/en/surveyprofield_time.php index 4952ed79b45..2dedd69bcf4 100644 --- a/field/time/lang/en/surveyprofield_time.php +++ b/field/time/lang/en/surveyprofield_time.php @@ -25,10 +25,10 @@ $string['currenttimedefault'] = 'Current time'; $string['customdefault'] = 'Custom'; -$string['defaultoption_help'] = 'This is the time the remote user will find answered by default. The default for this type of question is mandatory. If "Current time" is choosed as default, boundaries are not supposed to apply.'; $string['defaultoption'] = 'Default'; -$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; +$string['defaultoption_help'] = 'This is the time the remote user will find answered by default. The default for this type of question is mandatory. If "Current time" is choosed as default, boundaries are not supposed to apply.'; $string['downloadformat'] = 'Download format'; +$string['downloadformat_help'] = 'Choose the format of the answer as it appear once user attempts are downloaded'; $string['fifteenminutes'] = 'fifteen minutes'; $string['fiveminutes'] = 'five minutes'; $string['ierr_lowerequaltoupper'] = 'Lower and upper bounds must be different'; @@ -36,16 +36,17 @@ $string['ierr_outofrangedefault'] = 'Default does not fall within the specified range'; $string['invitehour'] = 'Choose an hour'; $string['inviteminute'] = 'Choose a minute'; -$string['lowerbound_help'] = 'The lowest time the user is allowed to enter'; $string['lowerbound'] = 'Lower bound'; +$string['lowerbound_help'] = 'The lowest time the user is allowed to enter'; $string['oneminute'] = 'One minute'; $string['pluginname'] = 'Time'; +$string['privacy:metadata'] = 'The "Time" field plugin does not store any personal data.'; $string['restriction_lower'] = 'Answer is supposed to be greater-equal than {$a}'; $string['restriction_lowerupper'] = 'Answer is supposed to fit between {$a->lowerbound} and {$a->upperbound}'; $string['restriction_upper'] = 'Answer is supposed to be lower-equal than {$a}'; $string['restriction_upperlower'] = 'Answer is supposed to be greater-equal than {$a->lowerbound} or lower-equal than {$a->upperbound}'; -$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['step'] = 'Step'; +$string['step_help'] = 'Step of the minute drop down menu as it appear in the attemp form'; $string['strftime01'] = '%H:%M'; $string['strftime02'] = '%I:%M %p'; $string['tenminutes'] = 'ten minutes'; @@ -57,7 +58,6 @@ $string['uerr_outofinternalrange'] = 'Provided value does not fall within the specified range'; $string['uerr_timenotset'] = 'Please choose a time or select the "{$a}" checkbox'; $string['uerr_timenotsetrequired'] = 'Time is not correctly defined'; -$string['upperbound_help'] = 'The biggest time the user is allowed to enter.

Upper and lower bound define a range.
If "lower bound" is lower than "upper bound" the user is forced to enter a value falling into the range.
If "lower bound" is greater than "upper bound" the user input is forced out from the range. i.e. the user input is supposed to be greater-equal than the lower bound OR lower-equal than the upper bound.

Example: By setting "lower bound" to 22 and "upper bound" to 1, the user input is supposed to fall in the three hours long range between 22 in the night and 1 in the morning.'; $string['upperbound'] = 'Upper bound'; +$string['upperbound_help'] = 'The biggest time the user is allowed to enter.

Upper and lower bound define a range.
If "lower bound" is lower than "upper bound" the user is forced to enter a value falling into the range.
If "lower bound" is greater than "upper bound" the user input is forced out from the range. i.e. the user input is supposed to be greater-equal than the lower bound OR lower-equal than the upper bound.

Example: By setting "lower bound" to 22 and "upper bound" to 1, the user input is supposed to fall in the three hours long range between 22 in the night and 1 in the morning.'; $string['userfriendlypluginname'] = 'Time'; -$string['privacy:metadata'] = 'The "Time" field plugin does not store any personal data.'; diff --git a/field/time/tests/behat/itemform.feature b/field/time/tests/behat/itemform.feature index 4f5347da105..f9289a5f619 100644 --- a/field/time/tests/behat/itemform.feature +++ b/field/time/tests/behat/itemform.feature @@ -54,18 +54,18 @@ Feature: Create a time item Then I should see "Lower and upper bounds must be different" And I set the following fields to these values: - | id_lowerboundhour | 10 | - | id_lowerboundminute | 0 | - | id_upperboundhour | 7 | - | id_upperboundminute | 0 | + | id_lowerboundhour | 10 | + | id_lowerboundminute | 0 | + | id_upperboundhour | 7 | + | id_upperboundminute | 0 | And I press "Add" Then I should see "Default does not fall within the specified range (see \"Upper bound\" help)" And I set the following fields to these values: - | id_lowerboundhour | 7 | - | id_lowerboundminute | 0 | - | id_upperboundhour | 10 | - | id_upperboundminute | 0 | + | id_lowerboundhour | 7 | + | id_lowerboundminute | 0 | + | id_upperboundhour | 10 | + | id_upperboundminute | 0 | And I press "Add" And I follow "edit_item_2" @@ -99,6 +99,6 @@ Feature: Create a time item And I follow "show_item_2" And I select "Preview" from the "jump" singleselect Then I should see "II.a At what time do you usually get up in the morning in a working day?" - Then the field "id_surveypro_field_time_2_hour" matches value "7" - Then the field "id_surveypro_field_time_2_minute" matches value "40" + Then the field "id_field_time_2_hour" matches value "7" + Then the field "id_field_time_2_minute" matches value "40" Then I should see "Additional note" diff --git a/field/time/tests/behat/submit_time.feature b/field/time/tests/behat/submit_time.feature index 688bad2ed5d..896e377207f 100644 --- a/field/time/tests/behat/submit_time.feature +++ b/field/time/tests/behat/submit_time.feature @@ -40,8 +40,8 @@ Feature: Submit using a time item # student1 submits And I press "New response" And I set the following fields to these values: - | id_surveypro_field_time_1_hour | 7 | - | id_surveypro_field_time_1_minute | 15 | + | id_field_time_1_hour | 7 | + | id_field_time_1_minute | 15 | And I press "Submit" diff --git a/field/time/tests/fixtures/usertemplate/time_only_2023103100.xml b/field/time/tests/fixtures/usertemplate/time_only_2024032800.xml similarity index 89% rename from field/time/tests/fixtures/usertemplate/time_only_2023103100.xml rename to field/time/tests/fixtures/usertemplate/time_only_2024032800.xml index cf097e9f465..8abe5850af4 100644 --- a/field/time/tests/fixtures/usertemplate/time_only_2023103100.xml +++ b/field/time/tests/fixtures/usertemplate/time_only_2024032800.xml @@ -1,47 +1,46 @@ - + + <h5>TIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only three <b>time specific setting</b>:</p><ol><li>Step</li><li>Default<br></li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> + 1 + 0 0 0 0 - <h5>TIME</h5><p>This plugin, like all the others provided by surveypro core, is equipped with a set of common settings shared with all the other surveypro elements.</p><p>The <b>common settings</b> set is done by:</p><ol><li>Required</li><li>Indent</li><li>Question position</li><li>Element number</li><li>Hide filling instruction</li><li>Variable</li><li>Additional note</li></ol><p>This plugin is equipped with only three <b>time specific setting</b>:</p><ol><li>Step</li><li>Default<br></li><li>Download format</li></ol><p>and with two more <b>validation options</b>:</p><ol><li>Lower bound</li><li>Upper bound</li></ol><p>The cartesian product of all these settings makes a very long list of possible implementations of this element. In this usertemplate few use cases are described.</p> - 1 - 0 0 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. + 1 + 0 + 1 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is not mandatory and the default is set to a not valid value so the user is forced to choose a different date and time or tick the "No answer" checkbox. - 1 - 0 - 1 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 1 - 0 + 1 time_001 + 0 + 0 + 0 + + 15 2 -3600 @@ -50,35 +49,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid static value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 2 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid static value</li></ul>Behaviour: the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 2 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 2 - 0 + 1 time_002 + 0 + 0 + 0 + + 15 1 26100 @@ -87,35 +85,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. + 1 + 0 + 3 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is not mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox. - 1 - 0 - 3 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 3 - 0 + 1 time_003 + 0 + 0 + 0 + + 15 4 -3600 @@ -124,35 +121,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. + 1 + 0 + 4 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time</li></ul>Behaviour: If the default is valid the user can "fly" over this element leaving the proposed default untouched (and the question not read) or to tick the "No answer" checkbox. - 1 - 0 - 4 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 4 - 0 + 1 time_004 + 0 + 0 + 0 + + 15 5 -3600 @@ -161,35 +157,34 @@ 28740 - + + <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. + 1 + 0 + 5 intro 0 0 0 - <ul><li>not mandatory (so: "No answer" is expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to "No answer"</li></ul>Behaviour: The item is not mandatory and the default is set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) or tick the "No answer" checkbox and setting a different date and time. - 1 - 0 - 5 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 0 0 0 - 5 - 0 + 1 time_005 + 0 + 0 + 0 + + 15 3 -3600 @@ -198,35 +193,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. + 1 + 0 + 6 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default invites the user to choose a value</li></ul>Behaviour: The item is mandatory and the default is set to a not valid value so the user is forced to choose a different date. - 1 - 0 - 6 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 6 - 0 + 1 time_006 + 0 + 0 + 0 + + 15 2 -3600 @@ -235,35 +229,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 7 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to a valid value</li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 7 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 7 - 0 + 1 time_007 + 0 + 0 + 0 + + 15 1 26100 @@ -272,35 +265,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) + 1 + 0 + 8 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)</li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the last input</li></ul>Behaviour: The item is mandatory and the default is probably set to a valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read) - 1 - 0 - 8 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 8 - 0 + 1 time_008 + 0 + 0 + 0 + + 15 4 -3600 @@ -309,35 +301,34 @@ 28740 - + + <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time<br /></li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> + 1 + 0 + 9 intro 0 0 0 - <ul><li>mandatory (so: "No answer" is not expected)<br /></li><li>step is set to 15 minutes<br /></li><li>input is limited between 4 am to 8:59 am</li><li>the default is set to the current time<br /></li></ul><p>Behaviour: The item is mandatory and the default is set to an valid value so the user can "fly" over this element leaving the proposed default untouched (and the question not read).</p> - 1 - 0 - 9 intro 0 - + - 0 - 0 - 0 - - At what time do you usually get up in the morning in a working day? 1 1 0 0 - 9 - 0 + 1 time_009 + 0 + 0 + 0 + + 15 5 -3600 diff --git a/field/time/version.php b/field/time/version.php index 945e0d9bc85..cd028656b02 100644 --- a/field/time/version.php +++ b/field/time/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprofield_time'; // Full name of the plugin (used for diagnostics). diff --git a/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php b/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php index f2170a51641..2d5cdc7727c 100644 --- a/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php +++ b/format/fieldset/backup/moodle2/backup_surveyproformat_fieldset_subplugin.class.php @@ -39,7 +39,7 @@ protected function define_item_subplugin_structure() { // XML nodes declaration. $subplugin = $this->get_subplugin_element(null, '../../plugin', 'fieldset'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); - $subpluginfieldset = new backup_nested_element('surveyproformat_fieldset', ['id'], ['content', 'defaultstatus']); + $subpluginfieldset = new backup_nested_element('surveyproformat_fieldset', ['id'], ['defaultstatus']); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/format/fieldset/classes/item.php b/format/fieldset/classes/item.php index f87222999cd..155520e39c0 100644 --- a/format/fieldset/classes/item.php +++ b/format/fieldset/classes/item.php @@ -39,10 +39,19 @@ */ class item extends itembase { + // Itembase properties. + + /** + * @var int defaultstatus + */ + protected $defaultstatus; + + // Service variables. + /** - * @var string Label of the fieldset + * @var bool Does this item use the child table surveypro(field|format)_plugin? */ - protected $content; + protected static $usesplugintable = true; /** * @var bool Can this item be parent? @@ -67,24 +76,27 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'fieldset'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. + $this->insetupform['common_fs'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -113,24 +125,19 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } /** - * Get content. + * Returns if this item has the mandatory attribute. * - * @return the content of $content property + * @return bool */ - public function get_content() { - return s($this->content); + public static function has_mandatoryattribute() { + return false; } /** @@ -140,29 +147,65 @@ public function get_content() { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Fieldset'; + public function item_add_fields_default_to_child_table(&$record) { + // $record->defaultstatus + + return; + } + + // MARK set. + + /** + * Set defaultstatus. + * + * @param string $defaultstatus + * @return void + */ + public function set_defaultstatus($defaultstatus) { + $this->defaultstatus = $defaultstatus; } // MARK get. /** - * Is this item available as a parent? + * Get content. * - * @return the content of the static property "canbeparent" + * @return the content of $content property */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_content() { + return s($this->content); + } + + /** + * Get defaultstatus. + * + * @return $this->defaultstatus + */ + public function get_defaultstatus() { + return $this->defaultstatus; + } + + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['defaultstatus']; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content']; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = ['content', 'extranote']; + $fieldlist['surveyprofield_time'] = []; return $fieldlist; } @@ -188,7 +231,6 @@ public static function get_plugin_schema() { - @@ -228,6 +270,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/fieldset/classes/itemsetupform.php b/format/fieldset/classes/itemsetupform.php index 50964839cb4..ade6ee9be49 100644 --- a/format/fieldset/classes/itemsetupform.php +++ b/format/fieldset/classes/itemsetupform.php @@ -57,7 +57,7 @@ public function definition() { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyproformat_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); // Item: defaultstatus. diff --git a/format/fieldset/db/install.xml b/format/fieldset/db/install.xml index 93376c95260..80c691d4e8a 100644 --- a/format/fieldset/db/install.xml +++ b/format/fieldset/db/install.xml @@ -1,30 +1,14 @@ -
- - - - - - - - - - - - - - - - - - - + + + diff --git a/format/fieldset/db/upgrade.php b/format/fieldset/db/upgrade.php index f0525362def..15c51143ced 100644 --- a/format/fieldset/db/upgrade.php +++ b/format/fieldset/db/upgrade.php @@ -81,5 +81,25 @@ function xmldb_surveyproformat_fieldset_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024011101, 'surveyproformat', 'fieldset'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyproformat_fieldset. + $table = new xmldb_table('surveyproformat_fieldset'); + $field = new xmldb_field('content'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + if ($dbman->field_exists($table, $field)) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_fieldset} f ON f.itemid = i.id + SET i.content = f.content'; + $DB->execute($sql); + + $dbman->drop_field($table, $field); + } + + // Age savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyproformat', 'fieldset'); + } + return true; } diff --git a/format/fieldset/lang/en/surveyproformat_fieldset.php b/format/fieldset/lang/en/surveyproformat_fieldset.php index b94fc43fe35..04aaca5233c 100644 --- a/format/fieldset/lang/en/surveyproformat_fieldset.php +++ b/format/fieldset/lang/en/surveyproformat_fieldset.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['defaultstatus_help'] = 'The status of this fieldset at page load time.'; $string['defaultstatus'] = 'Status at page load'; +$string['defaultstatus_help'] = 'The status of this fieldset at page load time.'; $string['forceclosed'] = 'Force closed'; $string['forceopened'] = 'Force opened'; $string['ierr_contenttoolong'] = 'The fieldset label is supposed to be shorter than 128 characters'; diff --git a/format/fieldset/version.php b/format/fieldset/version.php index 18aa98b2687..9895ff2faeb 100644 --- a/format/fieldset/version.php +++ b/format/fieldset/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_fieldset'; // Full name of the plugin (used for diagnostics). diff --git a/format/fieldsetend/classes/item.php b/format/fieldsetend/classes/item.php index 49ede40b38a..edff532257f 100644 --- a/format/fieldsetend/classes/item.php +++ b/format/fieldsetend/classes/item.php @@ -39,6 +39,15 @@ */ class item extends itembase { + // Itembase properties. + + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = false; + /** * @var bool Can this item be parent? */ @@ -62,26 +71,28 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'fieldsetend'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['common_fs'] = false; $this->insetupform['content'] = false; - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -114,6 +125,15 @@ public function get_content() { return $this->content; } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Item save. * @@ -121,12 +141,7 @@ public function get_content() { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); @@ -139,37 +154,44 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { + public function item_add_fields_default_to_child_table(&$record) { return; } // MARK get. /** - * Is this item available as a parent? + * get_pdf_template. * - * @return the content of the static property "canbeparent" + * @return the template to use at response report creation */ - public static function get_canbeparent() { - return self::$canbeparent; + public static function get_pdf_template() { + return 0; } /** - * get_pdf_template. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return the template to use at response report creation + * @return array $data */ - public static function get_pdf_template() { - return 0; + public function get_plugin_presets() { + $pluginproperties = []; + $data = $this->get_base_presets($pluginproperties); + + return $data; } /** - * Get if the plugin uses a table into the db. + * Make the list of the fields using multilang * - * @return if the plugin uses a personal table in the db. + * @param boolean $includemetafields + * @return array of fields */ - public function uses_db_table() { - return false; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = []; + $fieldlist['surveyprofield_time'] = []; + + return $fieldlist; } /** @@ -177,8 +199,8 @@ public function uses_db_table() { * * @return string $schema */ - public static function item_get_plugin_schema() { - return; + public static function get_plugin_schema() { + return ''; } // MARK userform. @@ -213,6 +235,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php b/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php index 112bf8115ae..1d271151f77 100644 --- a/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php +++ b/format/fieldsetend/lang/en/surveyproformat_fieldsetend.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Fieldsetend'; -$string['userfriendlypluginname'] = 'Fieldset closure'; $string['privacy:metadata'] = 'The "Fieldset end" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Fieldset closure'; diff --git a/format/fieldsetend/version.php b/format/fieldsetend/version.php index cb30671f171..ea9e8448e64 100644 --- a/format/fieldsetend/version.php +++ b/format/fieldsetend/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_fieldsetend'; // Full name of the plugin (used for diagnostics). diff --git a/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php b/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php index c47f896ceee..bd8bc466a83 100644 --- a/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php +++ b/format/label/backup/moodle2/backup_surveyproformat_label_subplugin.class.php @@ -39,10 +39,7 @@ protected function define_item_subplugin_structure() { // XML nodes declaration. $subplugin = $this->get_subplugin_element(null, '../../plugin', 'label'); // Virtual optigroup element. $wrapper = new backup_nested_element($this->get_recommended_name()); - $subpluginlabel = new backup_nested_element('surveyproformat_label', ['id'], [ - 'content', 'contentformat', - 'indent', 'customnumber', - 'fullwidth', 'leftlabel', ]); + $subpluginlabel = new backup_nested_element('surveyproformat_label', ['id'], ['fullwidth', 'leftlabel']); // Connect XML elements into the tree. $subplugin->add_child($wrapper); diff --git a/format/label/classes/item.php b/format/label/classes/item.php index 5f7b1a1169b..19ba690ec3d 100644 --- a/format/label/classes/item.php +++ b/format/label/classes/item.php @@ -39,22 +39,7 @@ */ class item extends itembase { - /** - * @var string $content - */ - public $content = ''; - - /** - * @var string $contentformat - */ - public $contentformat = ''; - - /** - * @var string Custom number of the item - * - * It usually is 1, 1.1, a, 2.1.a.. - */ - protected $customnumber; + // Itembase properties. /** * @var int The label has a dedicated row @@ -66,6 +51,13 @@ class item extends itembase { */ protected $leftlabel; + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = true; + /** * @var bool Can this item be parent? */ @@ -98,13 +90,18 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. + $this->insetupform['required'] = false; $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; $this->insetupform['required'] = false; + $this->insetupform['position'] = false; $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; $this->insetupform['hideinstructions'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -133,25 +130,31 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); + // Set properties at plugin level and then continue to base level. - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - $this->item_custom_fields_to_db($record); - // End of: plugin specific settings (eventually overriding general ones). + // Set custom fields values as defined by this specific plugin. + $this->add_plugin_properties_to_record($record); // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Traslate values from the mform of this item to values for corresponding properties. * * @param object $record * @return void */ - public function item_custom_fields_to_db($record) { + public function add_plugin_properties_to_record($record) { // 1. Special management for composite fields. // Nothing to do: they don't exist in this plugin. @@ -175,22 +178,51 @@ public function item_custom_fields_to_db($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { - $record->content = 'Label'; - $record->contentformat = 1; - $record->indent = 0; + public function item_add_fields_default_to_child_table(&$record) { $record->fullwidth = 0; + // $record->leftlabel + } + + // MARK set. + + /** + * Set fullwidth. + * + * @param string $fullwidth + * @return void + */ + public function set_fullwidth($fullwidth) { + $this->fullwidth = $fullwidth; + } + + /** + * Set leftlabel. + * + * @param string $leftlabel + * @return void + */ + public function set_leftlabel($leftlabel) { + $this->leftlabel = $leftlabel; } // MARK get. /** - * Is this item available as a parent? + * Get fullwidth. + * + * @return $this->fullwidth + */ + public function get_fullwidth() { + return $this->fullwidth; + } + + /** + * Get leftlabel. * - * @return the content of the static property "canbeparent" + * @return $this->leftlabel */ - public static function get_canbeparent() { - return self::$canbeparent; + public function get_leftlabel() { + return $this->leftlabel; } /** @@ -206,14 +238,31 @@ public function get_indent() { } } + /** + * Prepare presets for itemsetuprform with the help of the parent class too. + * + * @return array $data + */ + public function get_plugin_presets() { + $pluginproperties = ['fullwidth', 'leftlabel']; + $data = $this->get_base_presets($pluginproperties); + + return $data; + } + /** * Make the list of the fields using multilang * - * @return array of felds + * @param boolean $includemetafields + * @return array of fields */ - public function get_multilang_fields() { - $fieldlist = []; - $fieldlist[$this->plugin] = ['content', 'leftlabel']; + public function get_multilang_fields($includemetafields=true) { + if ($includemetafields) { + $fieldlist['surveypro_item'] = ['content', 'filename', 'filecontent']; + } else { + $fieldlist['surveypro_item'] = ['content']; + } + $fieldlist['surveyproformat_label'] = ['leftlabel']; return $fieldlist; } @@ -239,26 +288,7 @@ public static function get_plugin_schema() { - - - - - - - - - - - - - - - - - - - - + @@ -294,9 +324,11 @@ public function userform_mform_element($mform, $searchform, $readonly) { $labelsep = get_string('labelsep', 'langconfig'); // Separator usually is ': '. $elementnumber = $this->customnumber ? $this->customnumber.$labelsep : ''; $elementlabel = $elementnumber.$this->leftlabel; - $attributes = []; - $attributes['class'] = 'indent-'.$this->indent.' label_static'; - $mform->addElement('mod_surveypro_label', $this->itemname, $elementlabel, $this->get_content(), $attributes); + + $elementgroup = []; + $class = ['class' => 'indent-'.$this->indent]; + $elementgroup[] = $mform->createElement('static', $this->itemname, $elementlabel, $this->get_content()); + $mform->addGroup($elementgroup, $this->itemname.'_group', $elementlabel, '', false, $class); } } @@ -310,6 +342,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** @@ -341,11 +374,7 @@ public function userform_db_to_export($answer, $format='') { * @return array */ public function userform_get_root_elements_name() { - if (empty($this->fullwidth)) { - $elementnames = [$this->itemname]; - } else { - $elementnames = []; - } + $elementnames = []; return $elementnames; } diff --git a/format/label/classes/itemsetupform.php b/format/label/classes/itemsetupform.php index a0364d6a0e8..8d9cfa4161b 100644 --- a/format/label/classes/itemsetupform.php +++ b/format/label/classes/itemsetupform.php @@ -56,7 +56,7 @@ public function definition() { // Here I open a new fieldset. $fieldname = 'specializations'; - $typename = get_string('pluginname', 'surveyproformat_'.$item->get_plugin()); + $typename = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$item->get_plugin()); $mform->addElement('header', $fieldname, get_string($fieldname, 'mod_surveypro', $typename)); // Item: fullwidth. diff --git a/format/label/db/install.xml b/format/label/db/install.xml index 856a975bd93..caf6dffa3fc 100644 --- a/format/label/db/install.xml +++ b/format/label/db/install.xml @@ -1,31 +1,15 @@ -
- - - - - - - - - - - - - - - - - - - - + + + + diff --git a/format/label/db/upgrade.php b/format/label/db/upgrade.php index a540bb92415..4a725a33ba3 100644 --- a/format/label/db/upgrade.php +++ b/format/label/db/upgrade.php @@ -50,7 +50,7 @@ function xmldb_surveyproformat_label_upgrade($oldversion) { $dbman->drop_field($table, $field); } - // Surveypro savepoint reached. + // Label savepoint reached. upgrade_plugin_savepoint(true, 2014051701, 'surveyproformat', 'label'); } @@ -63,9 +63,70 @@ function xmldb_surveyproformat_label_upgrade($oldversion) { $whereparams = ['parentid' => null, 'parentvalue' => null, 'plugin' => 'label']; $DB->execute($sql, $whereparams); - // Surveypro savepoint reached. + // Label savepoint reached. upgrade_plugin_savepoint(true, 2024011101, 'surveyproformat', 'label'); } + if ($oldversion < 2024022701) { + + // Define field content to be dropped from surveyproformat_label. + $table = new xmldb_table('surveyproformat_label'); + $field1 = new xmldb_field('content'); + $field2 = new xmldb_field('contentformat'); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field1); + $condition = $condition && $dbman->field_exists($table, $field2); + if ($condition) { + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_label} f ON f.itemid = i.id + SET i.content = f.content, + i.contentformat = f.contentformat'; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field1)) { + $dbman->drop_field($table, $field1); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field2)) { + $dbman->drop_field($table, $field2); + } + + // Label savepoint reached. + upgrade_plugin_savepoint(true, 2024022701, 'surveyproformat', 'label'); + } + + if ($oldversion < 2024032800) { + + $table = new xmldb_table('surveyproformat_label'); + + $fieldnames = ['indent', 'customnumber']; + foreach ($fieldnames as $fieldname) { + // Define field content to be dropped from surveyproformat_label. + $field = new xmldb_field($fieldname); + + // Copy the content of the dropping fields to the new corresponding fields in surveypro_item. + $condition = $dbman->field_exists($table, $field); + if ($dbman->field_exists($table, $field)) { + // Copy the content of the dieing column to the new corresponding column in surveypro_item. + $sql = 'UPDATE {surveypro_item} i + JOIN {surveyproformat_label} f ON f.itemid = i.id + SET i.'.$fieldname.' = f.'.$fieldname; + $DB->execute($sql); + } + + // Conditionally launch drop field content. + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + } + + // Label savepoint reached. + upgrade_plugin_savepoint(true, 2024032800, 'surveyproformat', 'label'); + } + return true; } diff --git a/format/label/lang/en/surveyproformat_label.php b/format/label/lang/en/surveyproformat_label.php index 57fcac60a5a..34a543ae1cc 100644 --- a/format/label/lang/en/surveyproformat_label.php +++ b/format/label/lang/en/surveyproformat_label.php @@ -22,10 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['fullwidth_help'] = 'Use full screen width to display the label using as much space as possible starting from the left of the screen. When this option is used the element label and the element number will not be displayed.
As opposite alternative, the element will be drawn on the right side of the row leaving to its label the room on the left.'; $string['fullwidth'] = 'Full width'; -$string['leftlabel_help'] = 'The text that will be shown on the left of the label in the form'; +$string['fullwidth_help'] = 'Use full screen width to display the label using as much space as possible starting from the left of the screen. When this option is used the element label and the element number will not be displayed.
As opposite alternative, the element will be drawn on the right side of the row leaving to its label the room on the left.'; $string['leftlabel'] = 'Label'; +$string['leftlabel_help'] = 'The text that will be shown on the left of the label in the form'; $string['pluginname'] = 'Label'; -$string['userfriendlypluginname'] = 'Label'; $string['privacy:metadata'] = 'The "Label" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Label'; diff --git a/format/label/mform/label.php b/format/label/mform/label.php deleted file mode 100644 index c4b6c43fe10..00000000000 --- a/format/label/mform/label.php +++ /dev/null @@ -1,86 +0,0 @@ -. - -/** - * static form element - * - * HTML class for a static type element - * - * @package surveyproformat_label - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->libdir.'/form/static.php'); - -// @codingStandardsIgnoreFile - -/** - * static form element - * - * HTML class for a static type element - * - * @package surveyproformat_label - * @copyright 2013 onwards kordan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class surveypromform_label extends \MoodleQuickForm_static { - - /** - * Class constructor. - * - * @param string $elementName Select name attribute - * @param mixed $elementLabel Label(s) for the select - * @param mixed $options Data to be used to populate options - * @param mixed $attributes Either a typical HTML attribute string - * or an associative array - */ - public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null) { - parent::__construct($elementName, $elementLabel, $options); - $this->_options['class'] = !isset($attributes['class']) ? 'indent-0' : $attributes['class']; - } - - /** - * Returns type of editor element. - * - * @return string - */ - public function getElementTemplateType() { - return 'default'; - } - - /** - * Returns HTML for editor form element. - * - * @return string - */ - public function toHtml() { - $output = parent::toHtml(); // Core code. - - // Even if the simpler way to pass the class is: - // $output = \html_writer::tag('div', $output, $this->_options); - // I create the array from scratch in order to - // drop any other potentially dangerous element of the original $this->_options array. - $class = ['class' => $this->_options['class']]; - $output = \html_writer::tag('div', $output, $class); - - return $output; - } -} diff --git a/format/label/version.php b/format/label/version.php index c7abe1c8304..7b73f748351 100644 --- a/format/label/version.php +++ b/format/label/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024011101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_label'; // Full name of the plugin (used for diagnostics). diff --git a/format/pagebreak/classes/item.php b/format/pagebreak/classes/item.php index 532c79df8f2..cd6947103f8 100644 --- a/format/pagebreak/classes/item.php +++ b/format/pagebreak/classes/item.php @@ -39,6 +39,15 @@ */ class item extends itembase { + // Itembase properties. + + // Service variables. + + /** + * @var bool Does this item use the child table surveypro(field|format)_plugin? + */ + protected static $usesplugintable = false; + /** * @var bool Can this item be parent? */ @@ -62,28 +71,28 @@ public function __construct($cm, $surveypro, $itemid, $getparentcontent) { $this->type = SURVEYPRO_TYPEFORMAT; $this->plugin = 'pagebreak'; - // Override the list of fields using format, whether needed. - $this->fieldsusingformat = []; - // Other element specific properties. // No properties here. // Override properties depending from $surveypro settings. // No properties here. - // List of fields I do not want to have in the item definition form. + // List of fields of the base form I do not want to have in the item definition. + // Each (field|format) plugin receive a list of fields (quite) common to each (field|format) plugin. + // This is the list of the elements of the itembase form fields that this (field|format) plugin does not use. $this->insetupform['common_fs'] = false; $this->insetupform['content'] = false; - $this->insetupform['customnumber'] = false; - $this->insetupform['position'] = false; - $this->insetupform['extranote'] = false; + $this->insetupform['contentformat'] = false; $this->insetupform['required'] = false; - $this->insetupform['variable'] = false; - $this->insetupform['insearchform'] = false; - $this->insetupform['reserved'] = false; $this->insetupform['indent'] = false; + $this->insetupform['position'] = false; + $this->insetupform['variable'] = false; + $this->insetupform['extranote'] = false; + $this->insetupform['customnumber'] = false; $this->insetupform['hideinstructions'] = false; + $this->insetupform['insearchform'] = false; $this->insetupform['parentid'] = false; + $this->insetupform['parentvalue'] = false; if (!empty($itemid)) { $this->item_load($itemid, $getparentcontent); @@ -114,17 +123,21 @@ public function item_load($itemid, $getparentcontent) { * @return void */ public function item_save($record) { - $this->get_common_settings($record); - - // Now execute very specific plugin level actions. - - // Begin of: plugin specific settings (eventually overriding general ones). - // End of: plugin specific settings (eventually overriding general ones). + // Set properties at plugin level and then continue to base level. // Do parent item saving stuff here (mod_surveypro_itembase::item_save($record))). return parent::item_save($record); } + /** + * Returns if this item has the mandatory attribute. + * + * @return bool + */ + public static function has_mandatoryattribute() { + return false; + } + /** * Item add mandatory plugin fields * Copy mandatory fields to $record @@ -132,7 +145,7 @@ public function item_save($record) { * @param \stdClass $record * @return void */ - public function item_add_mandatory_plugin_fields(&$record) { + public function item_add_fields_default_to_child_table(&$record) { return; } @@ -146,45 +159,52 @@ public function item_uses_form_page() { } /** - * Return the xml schema for surveypro_<> table. + * Prepare presets for itemsetuprform with the help of the parent class too. * - * @return string $schema + * @return array $data */ - public static function item_get_plugin_schema() { - return; - } + public function get_plugin_presets() { + $pluginproperties = []; + $data = $this->get_base_presets($pluginproperties); - // MARK get. + return $data; + } /** - * Get content. + * Make the list of the fields using multilang * - * @return the content of $content property + * @param boolean $includemetafields + * @return array of fields */ - public function get_content() { - return $this->content; + public function get_multilang_fields($includemetafields=true) { + $fieldlist['surveypro_item'] = []; + $fieldlist['surveyprofield_time'] = []; + + return $fieldlist; } /** - * Is this item available as a parent? + * Return the xml schema for surveypro_<> table. * - * @return the content of the static property "canbeparent" + * @return string $schema */ - public static function get_canbeparent() { - return self::$canbeparent; + public static function get_plugin_schema() { + return ''; } - // MARK userform. + // MARK get. /** - * Get if the plugin uses a table into the db. + * Get content. * - * @return if the plugin uses a personal table in the db. + * @return the content of $content property */ - public function uses_db_table() { - return false; + public function get_content() { + return $this->content; } + // MARK userform. + /** * Define the mform element for the userform and the searchform. * @@ -210,6 +230,7 @@ public function userform_mform_element($mform, $searchform, $readonly) { */ public function userform_mform_validation($data, &$errors, $searchform) { // Nothing to do here. + return $errors; } /** diff --git a/format/pagebreak/lang/en/surveyproformat_pagebreak.php b/format/pagebreak/lang/en/surveyproformat_pagebreak.php index f60c43ef716..bc0bd3ce6b3 100644 --- a/format/pagebreak/lang/en/surveyproformat_pagebreak.php +++ b/format/pagebreak/lang/en/surveyproformat_pagebreak.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Page break'; -$string['userfriendlypluginname'] = 'Page break'; $string['privacy:metadata'] = 'The "Page break" format plugin does not store any personal data.'; +$string['userfriendlypluginname'] = 'Page break'; diff --git a/format/pagebreak/version.php b/format/pagebreak/version.php index 8368f4f4c24..931577d957b 100644 --- a/format/pagebreak/version.php +++ b/format/pagebreak/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019031901; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproformat_pagebreak'; // Full name of the plugin (used for diagnostics). diff --git a/index.php b/index.php index c14202f5774..dbde3626a73 100644 --- a/index.php +++ b/index.php @@ -31,6 +31,13 @@ require_course_login($course, true); +$context = context_course::instance($course->id); + +$params = ['context' => context_course::instance($course->id)]; +$event = \mod_surveypro\event\course_module_instance_list_viewed::create($params); +$event->add_record_snapshot('course', $course); +$event->trigger(); + // Get all required strings. $strname = get_string('name'); $strsurveypro = get_string('modulename', 'mod_surveypro'); @@ -41,8 +48,9 @@ $PAGE->set_pagelayout('incourse'); $PAGE->set_url('/mod/surveypro/index.php', ['id' => $id]); -$PAGE->navbar->add($strsurveypro, new \moodle_url('/mod/data/index.php', ['id' => $id])); -$PAGE->set_title($strsurveypro); +$PAGE->navbar->add($strsurveypro, new \moodle_url('/mod/surveypro/index.php', ['id' => $course->id])); +$titleparts = [$strdataplural, format_string($course->fullname)]; +$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); $PAGE->set_heading($course->fullname); // Is it useful? $PAGE->add_body_class('mediumwidth');. @@ -50,8 +58,6 @@ echo $OUTPUT->header(); echo $OUTPUT->heading($strdataplural, 2); -\mod_surveypro\event\course_module_instance_list_viewed::create_from_course($course)->trigger(); - // Get all the appropriate data. if (!$surveypros = get_all_instances_in_course('surveypro', $course)) { $url = new \moodle_url('/course/view.php', ['id' => $course->id]); @@ -74,7 +80,6 @@ } $table->colclasses = ['col1', 'col2', 'col3', 'col4', 'col5']; -$currentsection = -1; $sectionvisible = $DB->get_records_menu('course_sections', ['course' => $course->id], '', 'section, visible'); $sql = 'SELECT surveyproid, COUNT(id) as responses @@ -87,19 +92,24 @@ $whereparams = ['status' => SURVEYPRO_STATUSCLOSED]; $closedsubmissions = $DB->get_records_sql_menu($sql, $whereparams); +$currentsection = -1; foreach ($surveypros as $surveypro) { if ($surveypro->section != $currentsection) { if ($surveypro->section) { $printsection = get_section_name($course, $surveypro->section); - $sectionclass = $sectionvisible[$surveypro->section] ? null : ['class' => 'dimmed']; + $sectionclass = $sectionvisible[$surveypro->section] ? [] : ['class' => 'dimmed']; + } else { + $printsection = $surveypro->section; + $sectionclass = []; } $currentsection = $surveypro->section; } else { $printsection = ''; + $sectionclass = []; } if (empty($sectionclass)) { // The section is visible. - $cellclass = $surveypro->visible ? null : ['class' => 'dimmed']; + $cellclass = $surveypro->visible ? [] : ['class' => 'dimmed']; } else { $cellclass = ['class' => 'dimmed']; } @@ -108,7 +118,8 @@ $inprogressresp = isset($inprogresssubmissions[$surveypro->id]) ? $inprogresssubmissions[$surveypro->id] : 0; $closedresp = isset($closedsubmissions[$surveypro->id]) ? $closedsubmissions[$surveypro->id] : 0; - $content = [html_writer::tag('span', $printsection, $sectionclass), + $content = [ + \html_writer::tag('span', $printsection, $sectionclass), \html_writer::link($url, format_string($surveypro->name), $cellclass), \html_writer::tag('span', format_module_intro('surveypro', $surveypro, $surveypro->coursemodule), $cellclass), \html_writer::tag('span', $inprogressresp, $cellclass), diff --git a/lang/en/surveypro.php b/lang/en/surveypro.php index b7c51b99160..459134ffd89 100644 --- a/lang/en/surveypro.php +++ b/lang/en/surveypro.php @@ -25,11 +25,11 @@ defined('MOODLE_INTERNAL') || die(); $string['abandoned_submission_deleted'] = 'Deleted abandoned response'; -$string['action_help'] = 'Operate on elements already present in the survey with the following action.'; $string['action'] = 'Preexisting elements'; +$string['action_help'] = 'Operate on elements already present in the survey with the following action.'; $string['addnewsubmission'] = 'New response'; -$string['anonymous_help'] = 'The responses management table will not show the owner of the responses and reports and export will be anonymous.'; $string['anonymous'] = 'Anonymous responses'; +$string['anonymous_help'] = 'The responses management table will not show the owner of the responses and reports and export will be anonymous.'; $string['answerisnoanswer'] = 'Answer refused'; $string['answernotsubmitted'] = 'Answer not submitted'; $string['apply'] = 'Apply'; @@ -39,16 +39,16 @@ $string['applyusertemplates'] = 'Apply user templates'; $string['arrayexpected'] = 'Array is expected in {$a}'; $string['attemptinfo'] = 'Survey and responses information'; -$string['availability_fs'] = 'Availability'; $string['availability'] = 'Availability'; +$string['availability_fs'] = 'Availability'; $string['available_title'] = 'Available element. Click to make it reserved.'; $string['badchildparentvalue'] = 'Malformed condition: "{$a}".
It might never be verified.'; $string['badtablenamefound'] = 'Parse error reading xml. "{$a}" has been found as table name and, most probably, is invalid.'; $string['basic_editthanks'] = 'Thank you. Your response has been successfully modified!'; $string['basic_submitthanks'] = 'Thank you. Your response has been successfully submitted!'; $string['branching'] = 'Branching'; -$string['bulkaction_help'] = 'Use this menu to perform actions against elements as described by labels.'; $string['bulkaction'] = 'Bulk actions'; +$string['bulkaction_help'] = 'Use this menu to perform actions against elements as described by labels.'; $string['calendar_close_description'] = 'Surveypro "{$a}" closed.'; $string['calendar_close_time'] = 'Surveypro "{$a}" is no longer available.'; $string['calendar_open_description'] = 'Fill surveypro "{$a}", please.'; @@ -56,8 +56,8 @@ $string['canneversubmit'] = 'You are not allowed to submit a response'; $string['cannotsubmittooearly'] = 'The survey is still not open. You have to wait until {$a}'; $string['cannotsubmittoolate'] = 'This survey has been closed on {$a}'; -$string['captcha_help'] = 'Add to this collectoin the captcha to increase the security.'; $string['captcha'] = 'Add captcha'; +$string['captcha_help'] = 'Add to this collectoin the captcha to increase the security.'; $string['category'] = 'Course category'; $string['changeorder_title'] = 'Reorder'; $string['closed'] = 'This survey closed at'; @@ -66,11 +66,12 @@ $string['collespreferred'] = 'COLLES (Preferred)'; $string['common_fs'] = 'General settings'; $string['completiondetail:entries'] = 'Make entries: {$a}'; +$string['completionsubmit'] = 'this is the title of the \'help\'. Where does it appear?'; $string['completionsubmit_check'] = 'Student must submit the survey at least '; -$string['completionsubmit_group_help'] = 'This survey is considered completed when the student submit it at least as much as times how it is written here.'; $string['completionsubmit_group'] = 'Require submission'; -$string['completionsubmit'] = 'this is the title of the \'help\'. Where does it appear?'; +$string['completionsubmit_group_help'] = 'This survey is considered completed when the student submit it at least as much as times how it is written here.'; $string['completionsubmitdesc'] = 'Minimum number of submissions required: {$a}'; +$string['confirm_applyutemplate'] = 'Are you sure you want to apply the usertemplate adding all its item to the current surveypro?'; $string['confirm_delete1item'] = 'Are you sure you want to delete the \'{$a->pluginname}\' element: {$a->content}'; $string['confirm_delete1utemplate'] = 'Are you sure you want to delete the user template "{$a}"'; $string['confirm_deleteallitems'] = 'Do you confirm you want to delete EACH element?'; @@ -88,23 +89,23 @@ $string['confirm_duplicateotherresponse_modified'] = 'Are you sure you want to duplicate the response owned by {$a->fullname}, created on {$a->timecreated} and modified on {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = 'Are you sure you want to duplicate the response owned by {$a->fullname}, created on {$a->timecreated} and never modified?'; $string['confirm_free1item'] = 'Making available the element "{$a->itemcontent}" you are going to make available its ancestor.
Ancestor is the element in position: {$a->ancestors}.
Do you confirm this action?'; -$string['confirm_freechainitems_newparent'] = 'Making available the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be made available too.
So, in addition to the chosen element, you are going to make available the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_freechainitems'] = 'Making available the element "{$a->itemcontent}" you are going to make available all its dependencies.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; +$string['confirm_freechainitems_newparent'] = 'Making available the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be made available too.
So, in addition to the chosen element, you are going to make available the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_hide1item'] = 'Hiding the element "{$a->itemcontent}" its dependency will be hidden too.
Dependency is the element in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_hideallitems'] = 'Do you confirm you want to hide EACH element?'; $string['confirm_hidechainitems'] = 'Hiding the element "{$a->itemcontent}" all its dependencies will be hidden too.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_reserve1item'] = 'Reserving the element "{$a->itemcontent}" you are going to reserve its dependency too.
Dependency is the element in position: {$a->dependencies}.
Do you confirm this action?'; -$string['confirm_reservechainitems_newparent'] = 'Reserving the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be reserved too.
So, in addition to the chosen element, you are going to reserve the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_reservechainitems'] = 'Reserving the element "{$a->itemcontent}" you are going to reserve all its dependencies too.
Dependencies are the elements in position: {$a->dependencies}.
Do you confirm this action?'; +$string['confirm_reservechainitems_newparent'] = 'Reserving the element "{$a->itemcontent}", all the dependencies of element "{$a->parentcontent}" will be reserved too.
So, in addition to the chosen element, you are going to reserve the elements in position: {$a->dependencies}.
Do you confirm this action?'; $string['confirm_show1item'] = 'Showing the element {$a->lastitem} you are going to show its ancestor(s).
Ancestor(s) is(are) the element(s) in position: {$a->ancestors}.
Do you confirm this action?'; $string['confirm_showallitems'] = 'Do you confirm you want to show EACH element?'; $string['confirm_showchainitems'] = 'Showing the element {$a->lastitem} you are going to show all its ancestors.
Ancestors are the elements in position: {$a->ancestors}.
Do you confirm this action?'; +$string['content'] = 'Content'; +$string['content_editor'] = 'Content'; $string['content_editor_err'] = 'The content is mandatory'; $string['content_editor_help'] = 'The content of the element as it will be shown to remote user.'; -$string['content_editor'] = 'Content'; $string['content_err'] = 'The content is mandatory'; $string['content_help'] = 'The content of the element as it will be shown to remote user.'; -$string['content'] = 'Content'; $string['count_allitems'] = 'Survey built on {$a} elements.'; $string['count_hiddenitems'] = '({$a} hidden)'; $string['count_pages'] = 'Divided into {$a} pages.'; @@ -113,9 +114,9 @@ $string['currentcategory'] = 'This course category'; $string['currentcourse'] = 'This course'; $string['currenttotemplate'] = 'Save current survey as master template in zip format.
To install a master template, unzip it to mod/surveypro/template/ and visit the notification page.'; +$string['customnumber'] = 'Element number'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use this field to give a custom number to the element. It may be a natural number like 1 or whatever you may need: 1a, A, 1.1.a, #1, A, A.1... Take in mind that you are responsible for the coherence of that numbers. Because of this take care if you plan to change the order of the elements.'; -$string['customnumber'] = 'Element number'; $string['dataimport'] = 'Import data'; $string['deleteabandoned_task'] = 'Deleting uncompleted submissions'; $string['deleteallitems'] = 'Delete all elements'; @@ -164,10 +165,11 @@ $string['event_usertemplate_imported'] = 'A user template has been imported'; $string['event_usertemplate_saved'] = 'A user template has been saved'; $string['exporttemplate'] = 'export template'; -$string['extranote_help'] = 'Write here a description/note about extra informations the user is supposed to know about this element.'; $string['extranote'] = 'Additional note'; -$string['extranoteinsearch_descr'] = 'Are user notes needed in the search form?'; +$string['extranote_help'] = 'Write here a description/note about extra informations the user is supposed to know about this element.'; $string['extranoteinsearch'] = 'Extra note in search form'; +$string['extranoteinsearch_descr'] = 'Are user notes needed in the search form?'; +$string['feedback_applyutemplate'] = 'The usertemplate has been applied successfully'; $string['feedback_delete1item'] = 'The \'{$a->pluginname}\' element: {$a->content} has been successfully deleted'; $string['feedback_delete1response'] = 'User response has been successfully deleted'; $string['feedback_delete1utemplate'] = 'Usertemplate "{$a}" was successfully deleted'; @@ -190,27 +192,27 @@ $string['feedback_showallitems'] = 'All the elements were successfully shown'; $string['field'] = 'field element'; $string['fieldplugin'] = 'Element plugin'; -$string['fillinginstructioninsearch_descr'] = 'Are filling instructions needed in the search form?'; $string['fillinginstructioninsearch'] = 'Filling instruction in search form'; +$string['fillinginstructioninsearch_descr'] = 'Are filling instructions needed in the search form?'; $string['forcedoptionalitem_title'] = 'Forced optional element because of default value.'; $string['format'] = 'format element'; $string['formatplugin'] = 'Format plugin'; $string['free'] = 'free'; $string['fullwidth'] = 'top left (full width)'; $string['gotolist'] = 'Continue to responses list'; -$string['hassubmissions_alert_activitycompletion'] = '
With items modification the activity completion status will change too.
You have been warned.'; $string['hassubmissions_alert'] = 'This survey has already been answered at least once.
Please proceed with extreme caution and make only neutral changes to not compromise the validity of the whole survey.

BE WARNED: Adding a new item the status of each already submitted response will be forced to "in progress".'; +$string['hassubmissions_alert_activitycompletion'] = '
With items modification the activity completion status will change too.
You have been warned.'; $string['hassubmissions_danger'] = '
"In progress" responses...
  • are subject to deletion in 4 hours if pause/resume is not allowed;
  • are subject to deletion in the number of hours set into surveypro settings page if pause/resume is allowed.
'; -$string['hidden_help'] = 'Use this option to hide the element. Hided elements will not be available to anyone. You can consider these elements as not part of the survey.'; $string['hidden'] = 'Hidden'; +$string['hidden_help'] = 'Use this option to hide the element. Hided elements will not be available to anyone. You can consider these elements as not part of the survey.'; $string['hideallitems'] = 'Hide all elements'; $string['hidefield_title'] = 'Visible element. Click to hide.'; -$string['hideinstructions_help'] = 'Use this checkbox to show/hide filling instruction for this element.'; $string['hideinstructions'] = 'Hide filling instruction'; +$string['hideinstructions_help'] = 'Use this checkbox to show/hide filling instruction for this element.'; $string['hideitems'] = 'Hide'; $string['hideshow'] = 'Hide/Show'; -$string['history_help'] = 'Preserving history, users will no longer be able to directly modify a closed response. Modification to closed responses will be saved as a new copy, leaving the original one untouched and the history preserved.'; $string['history'] = 'Preserve history'; +$string['history_help'] = 'Preserving history, users will no longer be able to directly modify a closed response. Modification to closed responses will be saved as a new copy, leaving the original one untouched and the history preserved.'; $string['ierr_invalidinput'] = 'Incorrect value entered'; $string['ierr_missingparentcontent'] = 'You need to specify a parent content otherwise clear the "{$a}" field'; $string['ierr_missingparentid'] = 'You need to select a element to branch the survey. Otherwise clear the "{$a}" field'; @@ -243,50 +245,50 @@ $string['includenames'] = 'Include owner name'; $string['includereserved'] = 'Include reserved elements'; $string['incorrectaccessdetected'] = 'Incorrect access detected'; -$string['indent_help'] = 'The indent of the element alias the left margin the element will respect once drawn.'; $string['indent'] = 'Indent'; +$string['indent_help'] = 'The indent of the element alias the left margin the element will respect once drawn.'; $string['inprogresssubmissions'] = 'In progress responses'; $string['inputclean'] = 'Input will be cleaned up from trailing spaces at save time'; +$string['insearchform'] = 'Search form'; $string['insearchform_help'] = 'Is this element going to be used in the search form?'; $string['insearchform_title'] = 'Searchable item. Click to make it not searchable.'; -$string['insearchform'] = 'Search form'; $string['invalidtypeorplugin'] = 'Invalid type or plugin were provided as item properties in the template'; $string['invitedefault'] = 'Invite'; $string['item'] = 'Element'; $string['itemcontentfilearea'] = 'Item content'; $string['itemlist'] = 'Elements list'; -$string['keepinprogress_help'] = 'Do not delete "in progress" responses in spite of module policy. "In progress" responses are supposed to be dropped to always guarantee a good reliability to the final database. If, for any reason, you need to collect also the "in progress" responses, check this box.'; $string['keepinprogress'] = 'Keep "in progress" responses'; +$string['keepinprogress_help'] = 'Do not delete "in progress" responses in spite of module policy. "In progress" responses are supposed to be dropped to always guarantee a good reliability to the final database. If, for any reason, you need to collect also the "in progress" responses, check this box.'; +$string['layout'] = 'Layout'; $string['layout_branchingvalidation'] = 'Branching validation'; $string['layout_edititem'] = 'Edit element'; $string['layout_items'] = 'Elements'; $string['layout_itemsetup'] = 'Element setup'; $string['layout_preview'] = 'Preview'; -$string['layout'] = 'Layout'; $string['left'] = 'left'; $string['likelast'] = 'Like last response'; $string['mailcontentdefault'] = 'User {FULLNAME} added a response to "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'The content of the custom message that will be sent at user response submission time. If a notification mail is requested at response submission time and this message is not provided, the default email content is used.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
to get
  • the user first name
  • the user last name
  • the user full name
  • the name of the course
  • the name of this surveypro
  • the url of this surveypro
Take care: default message is multilanguage, your custom message is going to be used as you write it and never translated.'; $string['mailcontenteditor'] = 'Notification message'; -$string['mailextraaddresses_help'] = 'Some additional email addresses to notify about new responses. Addresses are supposed to be one per row.'; +$string['mailcontenteditor_help'] = 'The content of the custom message that will be sent at user response submission time. If a notification mail is requested at response submission time and this message is not provided, the default email content is used.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
to get
  • the user first name
  • the user last name
  • the user full name
  • the name of the course
  • the name of this surveypro
  • the url of this surveypro
Take care: default message is multilanguage, your custom message is going to be used as you write it and never translated.'; $string['mailextraaddresses'] = 'More addresses'; -$string['mailroles_help'] = 'Send an email to each component of the selected roles at each response. Roles are intended at course level therefore any division into groups is neglected. The email will only advise about response from the user, not about its content and without sender details.'; +$string['mailextraaddresses_help'] = 'Some additional email addresses to notify about new responses. Addresses are supposed to be one per row.'; $string['mailroles'] = 'Roles to notify'; +$string['mailroles_help'] = 'Send an email to each component of the selected roles at each response. Roles are intended at course level therefore any division into groups is neglected. The email will only advise about response from the user, not about its content and without sender details.'; $string['managesurveyprofieldplugins'] = 'Manage field plugins'; $string['managesurveyproformatplugins'] = 'Manage format plugins'; $string['managesurveyproreportplugins'] = 'Manage report plugins'; $string['managesurveyprotemplateplugins'] = 'Manage template plugins'; $string['manageusertemplates'] = 'Manage user templates'; -$string['mastertemplate_help'] = 'Choose a master template like one of the classical ones provided by default or a custom one added to this instance of surveypro. The classical survey types are:
  • ATTLS: Attitudes To Thinking and Learning Survey.
    For more details, see the documentation on ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey.
    For more details, see the documentation on COLLES.
  • CRITICAL INCIDENTS.
    For more details, see the documentation on Critical incidents
'; $string['mastertemplate'] = 'Master templates'; +$string['mastertemplate_help'] = 'Choose a master template like one of the classical ones provided by default or a custom one added to this instance of surveypro. The classical survey types are:
  • ATTLS: Attitudes To Thinking and Learning Survey.
    For more details, see the documentation on ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey.
    For more details, see the documentation on COLLES.
  • CRITICAL INCIDENTS.
    For more details, see the documentation on Critical incidents
'; $string['mastertemplateaddendum'] = '
You can not apply this mastertemplate until you uninstall it, fix all the issues and reinstall it.'; -$string['mastertemplatename_help'] = 'Choose the name of the master template name that is going to be downloaded in zip format.'; $string['mastertemplatename'] = 'Master template name'; +$string['mastertemplatename_help'] = 'Choose the name of the master template name that is going to be downloaded in zip format.'; $string['mastertemplateplugin'] = 'Master template plugin'; -$string['maxentries_help'] = 'The maximum number of responses a student is allowed to submit for this activity.'; $string['maxentries'] = 'Maximum allowed attempts'; -$string['maxinputdelay_descr'] = 'The maximum allowed delay in hours for users to submit a survey. Even if the user is allowed to pause the data entry and restart it later, after the time defined here partial responses will be deleted. Default of 168 hours is equivalent to a week. Set this to 0 (zero) if you really want to allow partial responses (not recommended).'; +$string['maxentries_help'] = 'The maximum number of responses a student is allowed to submit for this activity.'; $string['maxinputdelay'] = 'Max input delay'; +$string['maxinputdelay_descr'] = 'The maximum allowed delay in hours for users to submit a survey. Even if the user is allowed to pause the data entry and restart it later, after the time defined here partial responses will be deleted. Default of 168 hours is equivalent to a week. Set this to 0 (zero) if you really want to allow partial responses (not recommended).'; $string['missingfile'] = 'It seems no file was selected'; $string['missingitemplugin'] = 'One or more items of the template are missing the plugin'; $string['missingitemtype'] = 'One or more items of the template are missing the type'; @@ -294,19 +296,19 @@ $string['missingmandatory'] = 'Some mandatory answer of this response has not been found. Because of this, the overall response has been marked as "{$a}".
To fix this issue, please edit the response and review item contents page per page.'; $string['missingvalidation'] = 'Some answers of this response have been found as unverified. Because of this, the overall response has been marked as "{$a}".
Your data is not necessarily incorrect but needs validation before definitive storage.
To fix this issue, please edit the response and review item contents page per page.'; $string['module'] = 'This instance of survey'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro allows the creation of custom surveys as far as built in surveys like ATTLS, COLLES and CRITICAL INCIDENTS. You can also save and reuse parts or whole of your own custom survey.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Surveypro settings'; +$string['mtemplate'] = 'Master templates'; $string['mtemplate_apply'] = 'Apply'; $string['mtemplate_save'] = 'Save'; -$string['mtemplate'] = 'Master templates'; $string['mtemplatessection'] = 'Master templates section'; -$string['neverstartedemail_help'] = 'Send a reminder email to users not starting their first submission'; $string['neverstartedemail'] = 'Email for not started survey'; -$string['newpageforchild_help'] = 'Use this option to force a new page after each branching element.'; +$string['neverstartedemail_help'] = 'Send a reminder email to users not starting their first submission'; $string['newpageforchild'] = 'Branches increase pages'; +$string['newpageforchild_help'] = 'Use this option to force a new page after each branching element.'; $string['newsubmissionbody'] = '{$a->username} submitted a new response in "{$a->surveyproname}". You can review it here'; $string['newsubmissionsubject'] = 'New response'; $string['nextformpage'] = 'Next page >>'; @@ -316,9 +318,9 @@ $string['noitemsfoundadmin'] = 'This survey has no elements. Please add them from "{$a}".'; $string['nomoreitems'] = 'On the basis of the answers provided, no more elements remain to display.
Your survey is over. You only need to submit{$a}.'; $string['nomoresubmissionsallowed'] = 'The maximun number of {$a} responses has already been reached.
No new responses are allowed'; +$string['nomtemplates'] = 'Missing master templates'; $string['nomtemplates_help'] = 'Course creator probably denied the instantiation of each master tempalte. Contact your course creator for further details.'; $string['nomtemplates_message'] = 'Sorry. Not any master template seems available in this moodle site instance.'; -$string['nomtemplates'] = 'Missing master templates'; $string['noreportsfound'] = 'There are no reports in this surveypro instillation.'; $string['nosubmissionsforenrolled'] = 'No responses were found in this survey for enrolled students.'; $string['note'] = 'Note:'; @@ -333,41 +335,41 @@ $string['opened'] = 'Opening time'; $string['optionalitem_title'] = 'Optional element. Click to make the element mandatory.'; $string['outputstyle'] = 'Output style'; -$string['overwrite_help'] = 'Selecting this checkbox you will overwrite an older template with the same name. If you leave this checkbox unselected, in case of conflicts, you will be asked for a new unique name.'; $string['overwrite'] = 'Replace older template'; +$string['overwrite_help'] = 'Selecting this checkbox you will overwrite an older template with the same name. If you leave this checkbox unselected, in case of conflicts, you will be asked for a new unique name.'; $string['pagexofy'] = 'Page {$a->formpage} of {$a->userformpagecount}'; $string['parentconstraints'] = 'Parent constraints'; -$string['parentcontent_help'] = 'This is what the user is supposed to answer to the parent element in order to enable/display this element.'; $string['parentcontent'] = 'Parent content'; +$string['parentcontent_help'] = 'This is what the user is supposed to answer to the parent element in order to enable/display this element.'; $string['parentelement_help'] = 'The element whose answer, during the compilation of the questionnaire, determines the access to the current element.'; $string['parentelement_title'] = 'Parent element'; $string['parentformat'] = 'Define the "{$a->fieldname}" format as shown here: {$a->examples}'; +$string['parentid'] = 'Parent element'; $string['parentid_header'] = 'Relation'; $string['parentid_help'] = 'Parent elements allows you to create conditional branching. Dimmed elements in the list identify hidden parent elments. Show them to have them available in this list.
Elements marked with an asterisk are reserved.'; -$string['parentid'] = 'Parent element'; $string['pause'] = 'Pause'; -$string['pauseresume_help'] = 'Allow to pause a survey in order to resume and submit it later on. You can also email users to remind their uncompleted job.'; $string['pauseresume'] = 'Allow Pause/Resume'; +$string['pauseresume_help'] = 'Allow to pause a survey in order to resume and submit it later on. You can also email users to remind their uncompleted job.'; $string['pauseresumeemail'] = 'Allow pause/resume with reminder email'; $string['pauseresumenoemail'] = 'Allow pause/resume without reminder email'; $string['pdfsubject'] = 'Single response in PDF'; $string['plugin'] = 'Element'; $string['pluginadministration'] = 'Surveypro administration'; -$string['pluginname_help'] = 'Write here the name of the survey plugin you are going to save.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Write here the name of the survey plugin you are going to save.'; $string['plugintype'] = 'Plugin type'; -$string['position_help'] = 'Use this option to choose the position of the content of the element. It can be to the left of the user interface, in a dedicated row just upper the interface to enter the answer or in a dedicated row just upper the interface spanning all the row.
Note: The left position forces the element contents to plain text without images.
The two \'top\' positions are usually needed for contents longer than few words and are required for questions containing images!'; $string['position'] = 'Question position'; -$string['previewmode'] = 'You are in \'{$a}\': buttons to save data are not supposed to display'; +$string['position_help'] = 'Use this option to choose the position of the content of the element. It can be to the left of the user interface, in a dedicated row just upper the interface to enter the answer or in a dedicated row just upper the interface spanning all the row.
Note: The left position forces the element contents to plain text without images.
The two \'top\' positions are usually needed for contents longer than few words and are required for questions containing images!'; +$string['previewmode'] = 'You are in \'{$a}\': buttons to save data are not expected'; $string['previousformpage'] = '<< Previous page'; +$string['privacy:metadata:answer'] = 'Answers to items of surveypros.'; $string['privacy:metadata:answer:content'] = 'Field where the answers to items are stored.'; $string['privacy:metadata:answer:contentformat'] = 'Field storing the format of the answers to items.'; -$string['privacy:metadata:answer'] = 'Answers to items of surveypros.'; +$string['privacy:metadata:submission'] = 'Responses to surveypros.'; $string['privacy:metadata:submission:status'] = 'The overall status of the response provided by the user.'; $string['privacy:metadata:submission:timecreated'] = 'The time when the response was posted.'; $string['privacy:metadata:submission:timemodified'] = 'The time when the response was modified.'; $string['privacy:metadata:submission:userid'] = 'The ID of the user who submitted his/her answer.'; -$string['privacy:metadata:submission'] = 'Responses to surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Field data for the surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Format data for the surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Report data for the surveypro.'; @@ -394,12 +396,12 @@ $string['reportplugin'] = 'Report plugin'; $string['reports'] = 'Reports'; $string['reportsection'] = 'Reports section'; -$string['required_help'] = 'Will the user be forced to answer this element?'; $string['required'] = 'Required'; +$string['required_help'] = 'Will the user be forced to answer this element?'; $string['requireditem_title'] = 'Mandatory element. Click to make it optional.'; +$string['reserved'] = 'Reserved'; $string['reserved_help'] = 'Is this element going to be available only to users equipped with a special permission or generally available to each user?'; $string['reserved_title'] = 'Reserved element. Click make it available.'; -$string['reserved'] = 'Reserved'; $string['response'] = 'response'; $string['responseauthor'] = 'Author: '; $string['responses'] = 'responses'; @@ -407,8 +409,8 @@ $string['responsetimemodified'] = ', Last modified on: '; $string['revieworpause'] = ', review or pause'; $string['reviewsubmissions'] = 'review surveypro submissions'; -$string['riskyeditdeadline_help'] = 'Allow users permitted to manage survey elements to force modifications of this survey even once already answered.'; $string['riskyeditdeadline'] = 'Deadline of risky modification session'; +$string['riskyeditdeadline_help'] = 'Allow users permitted to manage survey elements to force modifications of this survey even once already answered.'; $string['runreport'] = 'Run {$a->reportname} report'; $string['save'] = 'Save'; $string['saveasnew'] = 'Save as new'; @@ -416,23 +418,24 @@ $string['saveusertemplates'] = 'Save user templates'; $string['schemavalidationfailed'] = 'The template uses an invalid xml file. Please verify it'; $string['settings'] = 'Surveypro'; -$string['sharinglevel_help'] = 'Choose at which level your template will be shared with other courses. If you choose "course" this template will be available in this course ONLY, if you choose course category this template will be available ONLY to courses sharing the same course "category" with this course, if you choose "site" this template will be available to each other courses in this platform.'; $string['sharinglevel'] = 'Sharing level'; +$string['sharinglevel_help'] = 'Choose at which level your template will be shared with other courses. If you choose "course" this template will be available in this course ONLY, if you choose course category this template will be available ONLY to courses sharing the same course "category" with this course, if you choose "site" this template will be available to each other courses in this platform.'; $string['showallitems'] = 'Show all elements'; $string['showallsubmissions'] = 'Show all responses'; $string['showfield_title'] = 'Hidden element. Click to show.'; $string['sortindex'] = 'Order'; $string['specializations'] = '{$a} specific settings'; $string['star'] = '*'; -$string['startyear_help'] = 'Define the lower year that each question will require.'; $string['startyear'] = 'Minimum allowed year'; +$string['startyear_help'] = 'Define the lower year that each question will require.'; $string['status'] = 'Responses status'; $string['statusboth'] = 'closed and in progress both'; $string['statusclosed'] = 'closed'; $string['statusinprogress'] = 'in progress'; -$string['stopyear_help'] = 'Define the upper year that each question will require.'; $string['stopyear'] = 'Maximum allowed year'; +$string['stopyear_help'] = 'Define the upper year that each question will require.'; $string['submission'] = 'Attempt'; +$string['submissions'] = 'Responses'; $string['submissions_all_1_1'] = '1 response submitted by 1 user'; $string['submissions_all_1_many'] = '1 response submitted by {$a->usercount} users'; $string['submissions_all_many_1'] = '{$a->submissions} responses submitted by 1 user'; @@ -442,11 +445,14 @@ $string['submissions_detail_many_1'] = '{$a->submissions} \'{$a->status}\' responses submitted by 1 user'; $string['submissions_detail_many_many'] = '{$a->submissions} \'{$a->status}\' responses submitted by {$a->usercount} users'; $string['submissions_welcome'] = 'Responses overview'; -$string['submissions'] = 'Responses'; $string['submissionslist'] = 'Responses list'; +$string['subplugintype_surveyprofield'] = 'Surveypro field plugin'; $string['subplugintype_surveyprofield_plural'] = 'Surveypro fields plugins'; +$string['subplugintype_surveyproformat'] = 'Surveypro format plugin'; $string['subplugintype_surveyproformat_plural'] = 'Surveypro formats plugins'; +$string['subplugintype_surveyproreport'] = 'Surveypro report plugin'; $string['subplugintype_surveyproreport_plural'] = 'Surveypro reports plugins'; +$string['subplugintype_surveyprotemplate'] = 'Surveypro template plugin'; $string['subplugintype_surveyprotemplate_plural'] = 'Surveypro templates plugins'; $string['surveypro_dashboard'] = 'Dashboard'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Edit response'; @@ -471,6 +477,7 @@ $string['surveypro:duplicateownsubmissions'] = 'Duplicate own responses'; $string['surveypro:editotherssubmissions'] = 'Edit responses from other users'; $string['surveypro:editownsubmissions'] = 'Edit own responses'; +$string['surveypro:enjoydeleteallsubmissionsbutton'] = 'Enjoy the "Delete all submissions" button'; $string['surveypro:exportresponses'] = 'Export collected responses'; $string['surveypro:ignoremaxentries'] = 'Submissions are not limited by max entries setting'; $string['surveypro:importresponses'] = 'Import data'; @@ -536,6 +543,7 @@ $string['utemplate_apply'] = 'Apply'; $string['utemplate_import'] = 'Import'; $string['utemplate_manage'] = 'Manage'; +$string['utemplate_nolongervalid'] = '
It may be you are trying to apply a no longer valid usertemplate.'; $string['utemplate_save'] = 'Save'; $string['utemplate'] = 'User templates'; $string['utemplatessection'] = 'User templates section'; @@ -562,6 +570,7 @@ $string['wrongrelation'] = '"{$a}" will never match'; $string['xmltemplate_help'] = 'Choose the template you want to download as zip file to share it with other moodle users.'; $string['xsdnotfound'] = 'xsd validation schema for your xml template was not found.
Your code must be fixed by a developer.'; +$string['yes_applyutemplate'] = 'Yes, apply the usertemplate ignoring preexisting items'; $string['yes_deleteallitems'] = 'Delete each element'; $string['yes_deletehiddenitems'] = 'Delete each hidden element'; $string['yes_deletevisibleitems'] = 'Delete each visible element'; diff --git a/lang/es/surveypro.php b/lang/es/surveypro.php index 36d584488f2..fe7496799d9 100644 --- a/lang/es/surveypro.php +++ b/lang/es/surveypro.php @@ -24,11 +24,11 @@ defined('MOODLE_INTERNAL') || die(); -$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['action'] = 'Elementos pre-existentes'; +$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['addnewsubmission'] = 'Nueva respuesta'; -$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['anonymous'] = 'Respuestas anónimas'; +$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['answerisnoanswer'] = 'Contestación rehusada'; $string['answernotsubmitted'] = 'Contestación no enviada'; $string['apply'] = 'Aplicar'; @@ -38,21 +38,21 @@ $string['applyusertemplates'] = 'Aplicar plantillas de usuario'; $string['arrayexpected'] = 'Se espera un arreglo (una matriz) en {$a}'; $string['attemptinfo'] = 'Información de encuesta y respuestas'; -$string['availability_fs'] = 'Disponibilidad'; $string['availability'] = 'Disponibilidad'; +$string['availability_fs'] = 'Disponibilidad'; $string['available_title'] = 'Elemento de acceso libre. Haga clic para reservar.'; $string['badchildparentvalue'] = 'Condición malformada: "{$a}".
Podría ser que nunca sea verificada.'; $string['badtablenamefound'] = 'Error de procesamiento al leer XML. "{$a}" se ha encontrado como nombre de tabla y, lo más probable, es inválido.'; $string['basic_editthanks'] = 'Gracias. ¡Su respuesta ha sido modificada exitosamente!'; $string['basic_submitthanks'] = 'Gracias. ¡Su respuesta ha sido enviada exitosamente!'; $string['branching'] = 'Ramificación'; -$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['bulkaction'] = 'Acciones masivas'; +$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['canneversubmit'] = 'Usted no tiene permitido el enviar una respuesta'; $string['cannotsubmittooearly'] = 'La encuesta aun no está abierta. Usted tiene que esperar hasta {$a}'; $string['cannotsubmittoolate'] = 'La encuesta se ha cerrado en {$a}'; -$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['captcha'] = 'Añadir CAPTCHA'; +$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['category'] = 'Categoría de curso'; $string['changeorder_title'] = 'Reordenar'; $string['closed'] = 'Esta encuesta cerró en'; @@ -60,10 +60,10 @@ $string['collesactual'] = 'COLLES (Actual/Real)'; $string['collespreferred'] = 'COLLES (Favorita)'; $string['common_fs'] = 'Configuraciones generales'; +$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; $string['completionsubmit_check'] = 'Los estudiantes deben de enviar la encuesta al menos'; -$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['completionsubmit_group'] = 'Requerir envío'; -$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; +$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['confirm_delete1item'] = 'Está seguro de querer eliminar el \'{$a->pluginname}\' elemento: {$a->content}'; $string['confirm_delete1utemplate'] = '¿Está seguro de querer eliminar la plantilla del usuario "{$a}"'; $string['confirm_deleteallitems'] = '¿Confirma la eliminación de TODOS los elementos?'; @@ -81,31 +81,31 @@ $string['confirm_duplicateotherresponse_modified'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y modificada en {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y nunca modificada?'; $string['confirm_free1item'] = 'Liberando al elemento "{$a->itemcontent}" Usted va a liberar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; -$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_freechainitems'] = 'Haciendo disponible el elemento "{$a->itemcontent}" Usted va a hacer disponible todas sus dependencias.
Las dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_hide1item'] = 'Ocultando al elementot "{$a->itemcontent}" su dependencia se ocultará también.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_hideallitems'] = '¿Confirma el ocultamiento de TODOS los elementos?'; $string['confirm_hidechainitems'] = 'Al ocultar el elementot "{$a->itemcontent}" todas sus dependencias se ocultarán también.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reserve1item'] = 'Al reservar el elemento {$a->parentcontent}, Usted también va a reservar sus dependencias.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; -$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reservechainitems'] = 'Al reservar el elemento "{$a->itemcontent}" Usted también va a reservar todas sus dependencias.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_show1item'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; $string['confirm_showallitems'] = '¿Confirma el mostrar TODOS los elementos ?'; $string['confirm_showchainitems'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar todos sus ancestros.
Ancestros son los elementos en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; +$string['content'] = 'Contenido'; +$string['content_editor'] = 'Contenido'; $string['content_editor_err'] = 'El contenido es obligatorio'; $string['content_editor_help'] = 'El contenido del elemento tal como será mostrado al usuario remoto.'; -$string['content_editor'] = 'Contenido'; $string['content_err'] = 'El contenido es obligatorio'; -$string['content'] = 'Contenido'; $string['count_allitems'] = 'Encuesta construida en {$a} elementos.'; $string['count_hiddenitems'] = '({$a} ocultos)'; $string['count_pages'] = 'Dividida en {$a} páginas.'; $string['course'] = 'Curso'; $string['crontask'] = 'Trabajos de mantenimiento de Surveypro'; $string['currenttotemplate'] = 'Guardar encuesta actual como plantilla maestra en formato ZIP.
Para instalar una plantilla maestra, descomprímala a mod/surveypro/template/ y visite la página de notificaciones.'; +$string['customnumber'] = 'Elemento número'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use este campo para darle un número personalizado al elemento. Puede ser un número natural como 1 o cualquier otro que Usted necesite: 1a, A, 1.1.a, #1, A, A.1... Tome en cuenta que Usted es responsable por la coherencia de esos números. Debido a esto, tenga cuidado si Usted planea cambiar el orden de los elementos.'; -$string['customnumber'] = 'Elemento número'; $string['dataimport'] = 'Importar datos'; $string['deleteallitems'] = 'Eliminar todos los elementos'; $string['deleteallsubmissions'] = 'Eliminar todas las respuestas'; @@ -149,10 +149,10 @@ $string['event_usertemplate_imported'] = 'Se ha importado una plantilla de usuario'; $string['event_usertemplate_saved'] = 'Se ha guardado una plantilla de usuario'; $string['exporttemplate'] = 'exportar plantilla'; -$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranote'] = 'Nota adicional'; -$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; +$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranoteinsearch'] = 'Nota extra en formato de búsqueda'; +$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; $string['feedback_delete1item'] = 'El \'{$a->pluginname}\' elemento : {$a->content} ha sido eliminado exitosamente'; $string['feedback_delete1response'] = 'La respuesta del usuario ha sido eliminada exitosamente'; $string['feedback_delete1utemplate'] = 'La plantilla_de_usuario "{$a}" fue eliminada exitosamente'; @@ -175,27 +175,27 @@ $string['feedback_showallitems'] = 'Todos los elementos fueron mostrados exitosamente'; $string['field'] = 'elemento de campo'; $string['fieldplugin'] = 'Plugin de Elemento'; -$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['fillinginstructioninsearch'] = 'Instrucción de llenado en formato de búsqueda'; +$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['forcedoptionalitem_title'] = 'Elemento opcional forzado debido al valor por defecto.'; $string['format'] = 'elemento de formato'; $string['formatplugin'] = 'Plugin de formato'; $string['free'] = 'libre'; $string['fullwidth'] = 'superior izquierdo (ancho completo)'; $string['gotolist'] = 'Continuar hacia lista de respuestas'; -$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_alert'] = 'Esta encuesta ya ha sido contestada al menos una vez.
Por favor proceda con extrema cautela y sólamente haga cambios neutros que no comprometan la validez de toda la encuesta.'; +$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_danger'] = '
Las respuestas "En progreso"...
  • están sujetas a eliminación en 4 horas si no estuvierapermitido guardar/continuar;
  • están sujetas a eliminación en el número de horas configurado en la página de configuraciones de surveypro settings page si gguardar/continuar está permitido.
'; -$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hidden'] = 'Oculto'; +$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hideallitems'] = 'Ocultar todos los elementos'; $string['hidefield_title'] = 'Elemento visible. Hacer clic para ocultar.'; -$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideinstructions'] = 'Ocultar instrucciones de llenado'; +$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideitems'] = 'Ocultar'; $string['hideshow'] = 'Ocultar/Mostrar'; -$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['history'] = 'Preservar historia'; +$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['ierr_invalidinput'] = 'Valor incorrecto ingresado'; $string['ierr_missingparentcontent'] = 'Usted necesita especificar un contenido paterno o de lo contrario vaciar el campo "{$a}"'; $string['ierr_missingparentid'] = 'Usted necesita seleccionar un elemento para ramificar la encuesta. De lo contario, vaciar el campo "{$a}"'; @@ -228,48 +228,48 @@ $string['includenames'] = 'Incluir nombre del propietario'; $string['includereserved'] = 'Incluir elementos reservados'; $string['incorrectaccessdetected'] = 'Acceso incorrecto detectado'; -$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['indent'] = 'Indentar'; +$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['inprogresssubmissions'] = 'Respuestas en progreso'; $string['inputclean'] = 'La entrada será limpiada de espacios finales al momento de guardar'; +$string['insearchform'] = 'Formato de búsqueda'; $string['insearchform_help'] = '¿Será usado este elemento en el formato de búsqueda?'; $string['insearchform_title'] = 'Ítem buscable. Haga clic para hacerlo no buscable.'; -$string['insearchform'] = 'Formato de búsqueda'; $string['invalidtypeorplugin'] = 'Tipo inválido o plugin fueron proporcionados como propiedades de ítem en la plantilla'; $string['invitedefault'] = 'Invitar'; $string['item'] = 'Elemento'; $string['itemlist'] = 'Lista de elementos'; -$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; $string['keepinprogress'] = 'Conservar respuestas "en progreso" '; +$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; +$string['layout'] = 'Diseño'; $string['layout_branchingvalidation'] = 'Validación ramificada'; $string['layout_items'] = 'Elementos'; $string['layout_itemsetup'] = 'Configuración de elemento'; $string['layout_preview'] = 'Previsualización'; -$string['layout'] = 'Diseño'; $string['left'] = 'izquierda'; $string['likelast'] = 'Como la última respuesta'; $string['mailcontentdefault'] = 'Usuario {FULLNAME} añadió una respuesta a "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailcontenteditor'] = 'Mensaje de notificación'; -$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; +$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailextraaddresses'] = 'Más direcciones'; -$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; +$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; $string['mailroles'] = 'Roles a notificarle'; +$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; $string['managesurveyprofieldplugins'] = 'Gestionar plugins de campo'; $string['managesurveyproformatplugins'] = 'Gestionar plugins de formato'; $string['managesurveyproreportplugins'] = 'Gestionar plugins de reporte'; $string['managesurveyprotemplateplugins'] = 'Gestionar plugins de plantilla'; $string['manageusertemplates'] = 'Gestionar plantillas de usuario'; -$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplate'] = 'Plantillas maestras'; +$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplateaddendum'] = '
Usted no puede aplicar esta plantilla_maestra hasta que la des-instale, le arregle todos los problemas y la re-instale.'; -$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplatename'] = 'Nombre de plantilla maestra'; +$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplateplugin'] = 'Plugin de plantilla maestra'; -$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxentries'] = 'Máximos intentos permitidos'; -$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; +$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxinputdelay'] = 'Retraso máximo para contestar'; +$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; $string['missingfile'] = 'Al parecer no se seleccionó ningun archivo'; $string['missingitemplugin'] = 'A uno o más ítems de la plantilla les falta el plugin'; $string['missingitemtype'] = 'A uno o más ítems de la plantilla les falta el tipo'; @@ -277,17 +277,17 @@ $string['missingmandatory'] = 'No se ha encontrado alguna contestación obligatoria de esta respuesta. Por esto, las respuestas generales se han marcado como "{$a}".
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['missingvalidation'] = 'Algunas contestaciones de esta respuesta han sido encontradas como no-verificadas. Por esto, la respuesta general la sido marcada como "{$a}".
Sus datos no son necesariamente incorrectos, pero necesitan validación antes del almacenamiento definitivo.
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['module'] = 'Esta instancia de encuesta'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro le permite crear encuestas personalizadas, tanto como encuestas tipo ATTLS, COLLES y de INCIDENTES CRÍTICOS. Usted también puede gurdar y re-utilizar partes de, o toda su encuenta personalizada.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Configuraciones de Encuestapro (Surveypro)'; +$string['mtemplate'] = 'Master plantillas'; $string['mtemplate_apply'] = 'Aplicar'; $string['mtemplate_save'] = 'Guardar'; -$string['mtemplate'] = 'Master plantillas'; $string['mtemplatessection'] = 'Sección de plantillas maestras'; -$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newpageforchild'] = 'Las ramas aumentan las páginas'; +$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newsubmissionbody'] = '{$a->username} envió un nuevo registro en "{$a->surveyproname}" Usted puede revisarlo aquí'; $string['newsubmissionsubject'] = 'Nueva respuesta'; $string['nextformpage'] = 'Página siguiente >>'; @@ -297,9 +297,9 @@ $string['noitemsfoundadmin'] = 'Esta plantilla no tiene elementos. Por favor añádalos desde "{$a}".'; $string['nomoreitems'] = 'Con base en las contestaciones proporcionadas, ya no quedan más elementos para mostrar.
Su encuesta está terminada. Usted solamente necesita enviar {$a}.'; $string['nomoresubmissionsallowed'] = 'El número máximo de {$a} respuestas ya fue alcanzado.
No se permiten más intentos'; +$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nomtemplates_help'] = 'El creador del curso probablemente negó la instalación de cada plantilla maestra. Contacte a su creador del curso para más detalles.'; $string['nomtemplates_message'] = 'Lo sentimos. No aparece ninguna plantilla maestra disponible en esta instancia de sitio Moodle.'; -$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nosubmissionfound'] = 'No se encontraron repuestas en esta encuesta.'; $string['note'] = 'Nota:'; $string['nothingtodownload'] = 'Nada para descargar'; @@ -310,38 +310,38 @@ $string['opened'] = 'Hora de apertura'; $string['optionalitem_title'] = 'Elemento opcional. Haga click para volver obligatorio al elemento.'; $string['outputstyle'] = 'Estilo de salida'; -$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['overwrite'] = 'Remplazar plantilla más antigua'; +$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['pagexofy'] = 'Página {$a->formpage} de {$a->userformpagecount}'; $string['parentconstraints'] = 'Limitantes paternas'; -$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentcontent'] = 'Contenido paterno'; +$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentelement_help'] = 'El elemento cuya respuesta, durante la compilación del questionnaire, determina el acceso al elemento actual.'; $string['parentelement_title'] = 'Elemento paterno'; $string['parentformat'] = 'Defina el formato "{$a->fieldname}" tal y como se muestra aquí: {$a->examples}'; +$string['parentid'] = 'Elemento paterno'; $string['parentid_header'] = 'Relación'; $string['parentid_help'] = 'Los elementos paternos le permiten a Usted crear ramificación condicional. Los elementos atenuados en la lista identifican elementos paternos ocultos. Muéstrelos para tenerlos disponibles en la lista.
Elementos precedidos por un asterisco se supone que pertenecen SOLAMENTE a formato reservado.'; -$string['parentid'] = 'Elemento paterno'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['pauseresume'] = 'Permitir Guardar/Continuar'; +$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['plugin'] = 'Elemento'; $string['pluginadministration'] = 'Administración de Surveypro'; -$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['plugintype'] = 'Tipo de plugin'; -$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['position'] = 'Posición de la pregunta'; +$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['previewmode'] = 'Usted está en \'{$a}\': se supone que no deben de mostrarse los botones para guardar datos'; $string['previousformpage'] = '<< Página anterior'; +$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; $string['privacy:metadata:answer:content'] = 'Campo donde son almacenados las respuestas a ítems.'; $string['privacy:metadata:answer:contentformat'] = 'Campo que almacena el formato de las respuestas a los ítems.'; -$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; +$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:submission:status'] = 'El estdo global de la respuesta proporcionada por el usuario.'; $string['privacy:metadata:submission:timecreated'] = 'La hora de cuando se publicó la respuesta.'; $string['privacy:metadata:submission:timemodified'] = 'La hora de cuando se modificó la respuesta.'; $string['privacy:metadata:submission:userid'] = 'La ID del usuario que mandó su respuesta.'; -$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Datos de campo para el surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Datos de formato para el surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Datos de reporte para el surveypro.'; @@ -357,12 +357,12 @@ $string['reportplugin'] = 'Plugin de reporte'; $string['reports'] = 'Reportes'; $string['reportsection'] = 'Sección de reportes'; -$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['required'] = 'Requerido'; +$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['requireditem_title'] = 'Elemento obligatorio. Haga clic para hacer opcional al elemento.'; +$string['reserved'] = 'Reservado'; $string['reserved_help'] = '¿Este elemento solamente estará disponible para usuarios equipados con un permiso especial, o generalmente estará disponible para cada usuario?'; $string['reserved_title'] = 'Elemento reservado. Haga click para liberarlo.'; -$string['reserved'] = 'Reservado'; $string['response'] = 'respuesta'; $string['responseauthor'] = 'Autor:'; $string['responses'] = 'respuestas'; @@ -370,8 +370,8 @@ $string['responsetimemodified'] = ', Última midificación en:'; $string['revieworpause'] = ', revisar o pausar'; $string['reviewsubmissions'] = 'Revisar envíos de Encuestapro'; -$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['riskyeditdeadline'] = 'Fecha límite de sesión de modificación riesgosa'; +$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['runreport'] = 'Correr reporte de {$a->reportname}'; $string['save'] = 'Guardar'; $string['saveasnew'] = 'Guardar como nuevo'; @@ -379,23 +379,24 @@ $string['saveusertemplates'] = 'Guardar plantillas de usuario'; $string['schemavalidationfailed'] = 'La plantilla usa un archivo XML inválido. Por favor verifíquelo'; $string['settings'] = 'Encuestapro (Surveypro)'; -$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['sharinglevel'] = 'Nivel de compartir'; +$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['showallitems'] = 'Mostrar todos los elementos'; $string['showallsubmissions'] = 'Mostrar todas las respuestas'; $string['showfield_title'] = 'Elemento oculto. Haga click para mostrar.'; $string['sortindex'] = 'Orden'; $string['specializations'] = 'Configuraciones específicas de {$a}'; $string['star'] = '*'; -$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['startyear'] = 'Año mínimo permitido'; +$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['status'] = 'Estatus de encuesta'; $string['statusboth'] = 'ambas cerrada y en progreso'; $string['statusclosed'] = 'cerrada'; $string['statusinprogress'] = 'en progreso'; -$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['stopyear'] = 'Año máximo permitido'; +$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['submission'] = 'Intento'; +$string['submissions'] = 'Respuestas'; $string['submissions_all_1_1'] = '1 respuesta enviada por 1 usuario'; $string['submissions_all_1_many'] = '1 respuesta enviada por {$a->usercount} usuarios'; $string['submissions_all_many_1'] = '{$a->submissions} respuestas enviadas por 1 usuario'; @@ -405,7 +406,6 @@ $string['submissions_detail_many_1'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por 1 usuario'; $string['submissions_detail_many_many'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por {$a->usercount} usuarios'; $string['submissions_welcome'] = 'Vista general de respuestas'; -$string['submissions'] = 'Respuestas'; $string['submissionslist'] = 'Lista de respuestas'; $string['surveypro_dashboard'] = 'Tablero'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Editar'; diff --git a/lang/es_mx/surveypro.php b/lang/es_mx/surveypro.php index 26952e0e474..055189d7073 100644 --- a/lang/es_mx/surveypro.php +++ b/lang/es_mx/surveypro.php @@ -24,11 +24,11 @@ defined('MOODLE_INTERNAL') || die(); -$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['action'] = 'Elementos pre-existentes'; +$string['action_help'] = 'Operar sobre elementos que ya están presentes en la encuesta con la acción siguiente.'; $string['addnewsubmission'] = 'Nueva respuesta'; -$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['anonymous'] = 'Respuestas anónimas'; +$string['anonymous_help'] = 'La tabla de manejo de respuestas no mostrará al propietario de las respuestas y los reportes y la exportación serán anónimos.'; $string['answerisnoanswer'] = 'Contestación rehusada'; $string['answernotsubmitted'] = 'Contestación no enviada'; $string['apply'] = 'Aplicar'; @@ -38,21 +38,21 @@ $string['applyusertemplates'] = 'Aplicar plantillas de usuario'; $string['arrayexpected'] = 'Se espera un arreglo (una matriz) en {$a}'; $string['attemptinfo'] = 'Información de encuesta y respuestas'; -$string['availability_fs'] = 'Disponibilidad'; $string['availability'] = 'Disponibilidad'; +$string['availability_fs'] = 'Disponibilidad'; $string['available_title'] = 'Elemento de acceso libre. Haga clic para reservar.'; $string['badchildparentvalue'] = 'Condición malformada: "{$a}".
Podría ser que nunca sea verificada.'; $string['badtablenamefound'] = 'Error de procesamiento al leer XML. "{$a}" se ha encontrado como nombre de tabla y, lo más probable, es inválido.'; $string['basic_editthanks'] = 'Gracias. ¡Su respuesta ha sido modificada exitosamente!'; $string['basic_submitthanks'] = 'Gracias. ¡Su respuesta ha sido enviada exitosamente!'; $string['branching'] = 'Ramificación'; -$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['bulkaction'] = 'Acciones masivas'; +$string['bulkaction_help'] = 'Use este menú para realizar acciones contra elementos como se describen por etiquetas.'; $string['canneversubmit'] = 'Usted no tiene permitido el enviar una respuesta'; $string['cannotsubmittooearly'] = 'La encuesta aun no está abierta. Usted tiene que esperar hasta {$a}'; $string['cannotsubmittoolate'] = 'La encuesta se ha cerrado en {$a}'; -$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['captcha'] = 'Añadir CAPTCHA'; +$string['captcha_help'] = 'Añadirle a esta colección el CAPTCHA para aumentar la seguridad.'; $string['category'] = 'Categoría de curso'; $string['changeorder_title'] = 'Reordenar'; $string['closed'] = 'Esta encuesta cerró en'; @@ -60,10 +60,10 @@ $string['collesactual'] = 'COLLES (Actual/Real)'; $string['collespreferred'] = 'COLLES (Favorita)'; $string['common_fs'] = 'Configuraciones generales'; +$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; $string['completionsubmit_check'] = 'Los estudiantes deben de enviar la encuesta al menos'; -$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['completionsubmit_group'] = 'Requerir envío'; -$string['completionsubmit'] = 'Este es el título de la \'ayuda\'. ¿En donde aparece?'; +$string['completionsubmit_group_help'] = 'La encuesta es considerada completa cuando el estudiante la envía al menos el número de veces que está escrito aquí.'; $string['confirm_delete1item'] = 'Está seguro de querer eliminar el \'{$a->pluginname}\' elemento: {$a->content}'; $string['confirm_delete1utemplate'] = '¿Está seguro de querer eliminar la plantilla del usuario "{$a}"'; $string['confirm_deleteallitems'] = '¿Confirma la eliminación de TODOS los elementos?'; @@ -81,32 +81,30 @@ $string['confirm_duplicateotherresponse_modified'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y modificada en {$a->timemodified}?'; $string['confirm_duplicateotherresponse_original'] = '¿Está seguro de querer duplicar la respuesta peerteneciente a {$a->fullname}, creada en {$a->timecreated} y nunca modificada?'; $string['confirm_free1item'] = 'Liberando al elemento "{$a->itemcontent}" Usted va a liberar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; -$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_freechainitems'] = 'Haciendo disponible el elemento "{$a->itemcontent}" Usted va a hacer disponible todas sus dependencias.
Las dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_freechainitems_newparent'] = 'Haciendo disponible el elemento "{$a->itemcontent}", todas las dependencias del elemento "{$a->parentcontent}" serán hechas disponibles también.
So, Además del elemento seleccionado, Usted va a hacer disponiblees los elementos en posición: {$a->dependencies}.
¿Confirma esta acción?'; $string['confirm_hide1item'] = 'Ocultando al elementot "{$a->itemcontent}" su dependencia se ocultará también.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_hideallitems'] = '¿Confirma el ocultamiento de TODOS los elementos?'; $string['confirm_hidechainitems'] = 'Al ocultar el elementot "{$a->itemcontent}" todas sus dependencias se ocultarán también.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reserve1item'] = 'Al reservar el elemento {$a->parentcontent}, Usted también va a reservar sus dependencias.
Dependencia es el elemento en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; -$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_reservechainitems'] = 'Al reservar el elemento "{$a->itemcontent}" Usted también va a reservar todas sus dependencias.
Dependencias son los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; +$string['confirm_reservechainitems_newparent'] = 'Al reservar el elemento "{$a->itemcontent}", Usted también va a reservar las dependencias del elemento "{$a->parentcontent}" .
Así, además del elemento elegido, Usted va a reservar los elementos en posición: {$a->dependencies}.
¿Confirma Usted esta acción?'; $string['confirm_show1item'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar a su ancestro.
Ancestro es el elemento en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; $string['confirm_showallitems'] = '¿Confirma el mostrar TODOS los elementos ?'; $string['confirm_showchainitems'] = 'Mostrando el elemento {$a->lastitem}, Usted va a mostrar todos sus ancestros.
Ancestros son los elementos en posición: {$a->ancestors}.
¿Confirma Usted esta acción?'; +$string['content'] = 'Contenido'; +$string['content_editor'] = 'Contenido'; $string['content_editor_err'] = 'El contenido es obligatorio'; -$string['content_editor_err'] = 'El contenido es obligatorio'; -$string['content_editor_help'] = 'El contenido del elemento tal como será mostrado al usuario remoto.'; $string['content_editor_help'] = 'El contenido del elemento tal y como se le mostrará al usuario remoto.'; -$string['content_editor'] = 'Contenido'; -$string['content'] = 'Contenido'; $string['count_allitems'] = 'Encuesta construida en {$a} elementos.'; $string['count_hiddenitems'] = '({$a} ocultos)'; $string['count_pages'] = 'Dividida en {$a} páginas.'; $string['course'] = 'Curso'; $string['crontask'] = 'Trabajos de mantenimiento de Surveypro'; $string['currenttotemplate'] = 'Guardar encuesta actual como plantilla maestra en formato ZIP.
Para instalar una plantilla maestra, descomprímala a mod/surveypro/template/ y visite la página de notificaciones.'; +$string['customnumber'] = 'Elemento número'; $string['customnumber_header'] = '#'; $string['customnumber_help'] = 'Use este campo para darle un número personalizado al elemento. Puede ser un número natural como 1 o cualquier otro que Usted necesite: 1a, A, 1.1.a, #1, A, A.1... Tome en cuenta que Usted es responsable por la coherencia de esos números. Debido a esto, tenga cuidado si Usted planea cambiar el orden de los elementos.'; -$string['customnumber'] = 'Elemento número'; $string['dataimport'] = 'Importar datos'; $string['deleteallitems'] = 'Eliminar todos los elementos'; $string['deleteallsubmissions'] = 'Eliminar todas las respuestas'; @@ -150,10 +148,10 @@ $string['event_usertemplate_imported'] = 'Se ha importado una plantilla de usuario'; $string['event_usertemplate_saved'] = 'Se ha guardado una plantilla de usuario'; $string['exporttemplate'] = 'exportar plantilla'; -$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranote'] = 'Nota adicional'; -$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; +$string['extranote_help'] = 'Escriba aquí una descripción/nota acerca de información extra que el usuario debería conocer acerca de este elemento.'; $string['extranoteinsearch'] = 'Nota extra en formato de búsqueda'; +$string['extranoteinsearch_descr'] = '¿Se necesitan notas del usuario en el formato para búsqueda?'; $string['feedback_delete1item'] = 'El \'{$a->pluginname}\' elemento : {$a->content} ha sido eliminado exitosamente'; $string['feedback_delete1response'] = 'La respuesta del usuario ha sido eliminada exitosamente'; $string['feedback_delete1utemplate'] = 'La plantilla_de_usuario "{$a}" fue eliminada exitosamente'; @@ -176,27 +174,27 @@ $string['feedback_showallitems'] = 'Todos los elementos fueron mostrados exitosamente'; $string['field'] = 'elemento de campo'; $string['fieldplugin'] = 'Plugin de Elemento'; -$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['fillinginstructioninsearch'] = 'Instrucción de llenado en formato de búsqueda'; +$string['fillinginstructioninsearch_descr'] = '¿Se necesitan instrucciones para el llenado en el formato para búsqueda?'; $string['forcedoptionalitem_title'] = 'Elemento opcional forzado debido al valor por defecto.'; $string['format'] = 'elemento de formato'; $string['formatplugin'] = 'Plugin de formato'; $string['free'] = 'libre'; $string['fullwidth'] = 'superior izquierdo (ancho completo)'; $string['gotolist'] = 'Continuar hacia lista de respuestas'; -$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_alert'] = 'Esta encuesta ya ha sido contestada al menos una vez.
Por favor proceda con extrema cautela y sólamente haga cambios neutros que no comprometan la validez de toda la encuesta.'; +$string['hassubmissions_alert_activitycompletion'] = '
Simplemente añadiendo un nuevo elemento o cambiando la visibilidad a uno de los conjuntos de elementos existentes CAMBIARÁ el estatus de finalización de actividad de estudiantes.
Usted ha sido advertido.'; $string['hassubmissions_danger'] = '
Las respuestas "En progreso"...
  • están sujetas a eliminación en 4 horas si no estuvierapermitido guardar/continuar;
  • están sujetas a eliminación en el número de horas configurado en la página de configuraciones de surveypro settings page si gguardar/continuar está permitido.
'; -$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hidden'] = 'Oculto'; +$string['hidden_help'] = 'Use esta opción para ocultar el elemento. Los elementos ocultos no estarán disponibles para nadie. Usted puede considerar a estos elementos como que no son parte de la encuesta.'; $string['hideallitems'] = 'Ocultar todos los elementos'; $string['hidefield_title'] = 'Elemento visible. Hacer clic para ocultar.'; -$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideinstructions'] = 'Ocultar instrucciones de llenado'; +$string['hideinstructions_help'] = 'Use esta casilla para mostrar/ocultar instrucciones de llenado para este elemento.'; $string['hideitems'] = 'Ocultar'; $string['hideshow'] = 'Ocultar/Mostrar'; -$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['history'] = 'Preservar historia'; +$string['history_help'] = 'Preservando historia, los usuarios ya no podrán modificar directamente una respuesta cerrada. Las modificaciones a respuestas cerradas serán guardadas como una copia nueva, dejando el original sin tocar y la historia preservada.'; $string['ierr_invalidinput'] = 'Valor incorrecto ingresado'; $string['ierr_missingparentcontent'] = 'Usted necesita especificar un contenido paterno o de lo contrario vaciar el campo "{$a}"'; $string['ierr_missingparentid'] = 'Usted necesita seleccionar un elemento para ramificar la encuesta. De lo contario, vaciar el campo "{$a}"'; @@ -229,48 +227,48 @@ $string['includenames'] = 'Incluir nombre del propietario'; $string['includereserved'] = 'Incluir elementos reservados'; $string['incorrectaccessdetected'] = 'Acceso incorrecto detectado'; -$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['indent'] = 'Indentar'; +$string['indent_help'] = 'La indentación del elemento, o el margen izquierdo, que el elemento respetará una vez que se dibuje.'; $string['inprogresssubmissions'] = 'Respuestas en progreso'; $string['inputclean'] = 'La entrada será limpiada de espacios finales al momento de guardar'; +$string['insearchform'] = 'Formato de búsqueda'; $string['insearchform_help'] = '¿Será usado este elemento en el formato de búsqueda?'; $string['insearchform_title'] = 'Ítem buscable. Haga clic para hacerlo no buscable.'; -$string['insearchform'] = 'Formato de búsqueda'; $string['invalidtypeorplugin'] = 'Tipo inválido o plugin fueron proporcionados como propiedades de ítem en la plantilla'; $string['invitedefault'] = 'Invitar'; $string['item'] = 'Elemento'; $string['itemlist'] = 'Lista de elementos'; -$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; $string['keepinprogress'] = 'Conservar respuestas "en progreso" '; +$string['keepinprogress_help'] = 'No eliminar respuestas "en progreso" aún a pesar de política del módulo. Las respuestas "En progreso" se suponía que fueran descartadas para garantizar siempre una buena confibilidad a la base de datos final. Si, por cualquier razón, Usted necesitara colectartambién las respuestas "en progreso" , active esta casilla.'; +$string['layout'] = 'Diseño'; $string['layout_branchingvalidation'] = 'Validación ramificada'; $string['layout_items'] = 'Elementos'; $string['layout_itemsetup'] = 'Configuración de elemento'; $string['layout_preview'] = 'Previsualización'; -$string['layout'] = 'Diseño'; $string['left'] = 'izquierda'; $string['likelast'] = 'Como la última respuesta'; $string['mailcontentdefault'] = 'Usuario {FULLNAME} añadió una respuesta a "{SURVEYPRONAME}"'; -$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailcontenteditor'] = 'Mensaje de notificación'; -$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; +$string['mailcontenteditor_help'] = 'El contenido del mensaje personalizado que será enviado al momento del envío de la respuesta. Si se solicita un correo de notificación al momento de envío de la respuesta y este mensaje no es proporcionado, se usará el contenido predeterminado del Email.

Use:
  • {FIRSTNAME}
  • {LASTNAME}
  • {FULLNAME}
  • {COURSENAME}
  • {SURVEYPRONAME}
  • {SURVEYPROURL}
para obtener
  • el nombre del usuario
  • los apellidos
  • el nombre completo del usuario
  • the name of the course
  • the name of this surveypro
  • la url de este surveypro
Tenga cuidado: el mensaje predeterminado es multi-idioma, su mensaje personalizado será usado tal como Usted lo escriba y nunca será traducido.'; $string['mailextraaddresses'] = 'Más direcciones'; -$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; +$string['mailextraaddresses_help'] = 'Algunas direcciones de Email a notificarles acerca de nuevas respuestas. Las direcciones se supone que son una por fila.'; $string['mailroles'] = 'Roles a notificarle'; +$string['mailroles_help'] = 'Enviar un Email a cada componente de los roles seleccionados en cada respuesta. El Email solamente avisará acerca de respuesta del usuario, no acerca del contenido y sin los detalles de quien envía.'; $string['managesurveyprofieldplugins'] = 'Gestionar plugins de campo'; $string['managesurveyproformatplugins'] = 'Gestionar plugins de formato'; $string['managesurveyproreportplugins'] = 'Gestionar plugins de reporte'; $string['managesurveyprotemplateplugins'] = 'Gestionar plugins de plantilla'; $string['manageusertemplates'] = 'Gestionar plantillas de usuario'; -$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplate'] = 'Plantillas maestras'; +$string['mastertemplate_help'] = 'Elija una plantilla maestra, como por ejemplo una de las clásicas proporcionadas por defecto, o una personalizada añadida a esta instancia de surveypro. Los tipos de encuesta clásicos son:
  • ATTLS: Attitudes To Thinking and Learning Survey (Encuesta de Actitudes Hacia el Pensamiento y Aprendizaje).
    Para más detalles, vea la documentación en ATTLS.
  • COLLES: Constructivist On-Line Learning Environment Survey (Encuesta Constructivista de Ambiente de Aprendizaje En-Línea).
    Para más detalles, vea la documentación en COLLES.
  • INCIDENTES CRÍTICOS.
    ara más detalles, vea la documentación en Critical incidents
'; $string['mastertemplateaddendum'] = '
Usted no puede aplicar esta plantilla_maestra hasta que la des-instale, le arregle todos los problemas y la re-instale.'; -$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplatename'] = 'Nombre de plantilla maestra'; +$string['mastertemplatename_help'] = 'Elija el nombre de la plantilla maestra que será descargada en formato ZIP.'; $string['mastertemplateplugin'] = 'Plugin de plantilla maestra'; -$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxentries'] = 'Máximos intentos permitidos'; -$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; +$string['maxentries_help'] = 'El número máximo de respuestas que un estudiante tiene permitido enviar para esta actividad'; $string['maxinputdelay'] = 'Retraso máximo para contestar'; +$string['maxinputdelay_descr'] = 'El retraso en horas máximo permitido para que los usuarios envíen una encuesta. Aun y cuando al usuario se le permita pausar el ingreso de datos y reiniciarlo después; posteriormente a este tiempo definido aquí, las respuestas parciales se eliminarán. El valor por defecto es de 168 horas que equivalen a una semana. Configure esto a cero (0) si realmente Usted desea permitir respuestas parciales (lo que no se recomienda).'; $string['missingfile'] = 'Al parecer no se seleccionó ningun archivo'; $string['missingitemplugin'] = 'A uno o más ítems de la plantilla les falta el plugin'; $string['missingitemtype'] = 'A uno o más ítems de la plantilla les falta el tipo'; @@ -278,17 +276,17 @@ $string['missingmandatory'] = 'No se ha encontrado alguna contestación obligatoria de esta respuesta. Por esto, las respuestas generales se han marcado como "{$a}".
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['missingvalidation'] = 'Algunas contestaciones de esta respuesta han sido encontradas como no-verificadas. Por esto, la respuesta general la sido marcada como "{$a}".
Sus datos no son necesariamente incorrectos, pero necesitan validación antes del almacenamiento definitivo.
Para corregir este problema, por favor edite la respuesta y revise los contenidos de los ítems página por página.'; $string['module'] = 'Esta instancia de encuesta'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro le permite crear encuestas personalizadas, tanto como encuestas tipo ATTLS, COLLES y de INCIDENTES CRÍTICOS. Usted también puede gurdar y re-utilizar partes de, o toda su encuenta personalizada.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveys'; $string['modulesettinghdr'] = 'Configuraciones de Encuestapro (Surveypro)'; +$string['mtemplate'] = 'Master plantillas'; $string['mtemplate_apply'] = 'Aplicar'; $string['mtemplate_save'] = 'Guardar'; -$string['mtemplate'] = 'Master plantillas'; $string['mtemplatessection'] = 'Sección de plantillas maestras'; -$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newpageforchild'] = 'Las ramas aumentan las páginas'; +$string['newpageforchild_help'] = 'Use esta opción para forzar una página nueva después de cada elemento que ramifica.'; $string['newsubmissionbody'] = '{$a->username} envió un nuevo registro en "{$a->surveyproname}" Usted puede revisarlo aquí'; $string['newsubmissionsubject'] = 'Nueva respuesta'; $string['nextformpage'] = 'Página siguiente >>'; @@ -298,9 +296,9 @@ $string['noitemsfoundadmin'] = 'Esta plantilla no tiene elementos. Por favor añádalos desde "{$a}".'; $string['nomoreitems'] = 'Con base en las contestaciones proporcionadas, ya no quedan más elementos para mostrar.
Su encuesta está terminada. Usted solamente necesita enviar {$a}.'; $string['nomoresubmissionsallowed'] = 'El número máximo de {$a} respuestas ya fue alcanzado.
No se permiten más intentos'; +$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nomtemplates_help'] = 'El creador del curso probablemente negó la instalación de cada plantilla maestra. Contacte a su creador del curso para más detalles.'; $string['nomtemplates_message'] = 'Lo sentimos. No aparece ninguna plantilla maestra disponible en esta instancia de sitio Moodle.'; -$string['nomtemplates'] = 'Faltan plantillas maestras'; $string['nosubmissionfound'] = 'No se encontraron repuestas en esta encuesta.'; $string['note'] = 'Nota:'; $string['nothingtodownload'] = 'Nada para descargar'; @@ -311,38 +309,38 @@ $string['opened'] = 'Hora de apertura'; $string['optionalitem_title'] = 'Elemento opcional. Haga click para volver obligatorio al elemento.'; $string['outputstyle'] = 'Estilo de salida'; -$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['overwrite'] = 'Remplazar plantilla más antigua'; +$string['overwrite_help'] = 'Al seleccionar esta casilla Usted sobre-escribirá una plantilla más antigua con el mismo nombre. Si Usted deja esta casilla sin seleccionar, en caso de conflictos se le pedirá un nuevo nombre único.'; $string['pagexofy'] = 'Página {$a->formpage} de {$a->userformpagecount}'; $string['parentconstraints'] = 'Limitantes paternas'; -$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentcontent'] = 'Contenido paterno'; +$string['parentcontent_help'] = 'Esto es lo que el usuario se supone que deba contestar al elemento paterno para habilitar/mostrar este elementp.'; $string['parentelement_help'] = 'El elemento cuya respuesta, durante la compilación del questionnaire, determina el acceso al elemento actual.'; $string['parentelement_title'] = 'Elemento paterno'; $string['parentformat'] = 'Defina el formato "{$a->fieldname}" tal y como se muestra aquí: {$a->examples}'; +$string['parentid'] = 'Elemento paterno'; $string['parentid_header'] = 'Relación'; $string['parentid_help'] = 'Los elementos paternos le permiten a Usted crear ramificación condicional. Los elementos atenuados en la lista identifican elementos paternos ocultos. Muéstrelos para tenerlos disponibles en la lista.
Elementos precedidos por un asterisco se supone que pertenecen SOLAMENTE a formato reservado.'; -$string['parentid'] = 'Elemento paterno'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['pauseresume'] = 'Permitir Guardar/Continuar'; +$string['pauseresume_help'] = 'Permitir pausar una encuesta para poder continuarla y enviarla en una segunda sesión de respuesta.'; $string['plugin'] = 'Elemento'; $string['pluginadministration'] = 'Administración de Surveypro'; -$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['pluginname'] = 'Surveypro'; +$string['pluginname_help'] = 'Escriba aquí el nombre del plugin de encuesta que Usted va a guardar.'; $string['plugintype'] = 'Tipo de plugin'; -$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['position'] = 'Posición de la pregunta'; +$string['position_help'] = 'Use esta opción para elegir la posición del contenido del elemento. Puede ser hacia la izquierda de la interfaz del usuario, en una fila dedicada justo arriba de la interfaz para ingresar la contestación, o en una fila dedicada justo arriba de la interfaz que abarca a toda la fila.
Tome nota de que la posición izquierda fuerza a los contenidos del elemento a texto plano sin imágenes.
¡Las dos posiciones \'superiores\' usualmente son necesitadas para contenidos que sean más largos de unas cuantas palabras y son necesarias para preguntas que que contienen imágenes!'; $string['previewmode'] = 'Usted está en \'{$a}\': se supone que no deben de mostrarse los botones para guardar datos'; $string['previousformpage'] = '<< Página anterior'; +$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; $string['privacy:metadata:answer:content'] = 'Campo donde son almacenados las respuestas a ítems.'; $string['privacy:metadata:answer:contentformat'] = 'Campo que almacena el formato de las respuestas a los ítems.'; -$string['privacy:metadata:answer'] = 'Respuesta a elementos de surveypros.'; +$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:submission:status'] = 'El estdo global de la respuesta proporcionada por el usuario.'; $string['privacy:metadata:submission:timecreated'] = 'La hora de cuando se publicó la respuesta.'; $string['privacy:metadata:submission:timemodified'] = 'La hora de cuando se modificó la respuesta.'; $string['privacy:metadata:submission:userid'] = 'La ID del usuario que mandó su respuesta.'; -$string['privacy:metadata:submission'] = 'Respuestas a surveypros.'; $string['privacy:metadata:surveyprofieldpluginsummary'] = 'Datos de campo para el surveypro.'; $string['privacy:metadata:surveyproformatpluginsummary'] = 'Datos de formato para el surveypro.'; $string['privacy:metadata:surveyproreportpluginsummary'] = 'Datos de reporte para el surveypro.'; @@ -358,12 +356,12 @@ $string['reportplugin'] = 'Plugin de reporte'; $string['reports'] = 'Reportes'; $string['reportsection'] = 'Sección de reportes'; -$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['required'] = 'Requerido'; +$string['required_help'] = '¿Será forzado el usuario a contestar este elemento?'; $string['requireditem_title'] = 'Elemento obligatorio. Haga clic para hacer opcional al elemento.'; +$string['reserved'] = 'Reservado'; $string['reserved_help'] = '¿Este elemento solamente estará disponible para usuarios equipados con un permiso especial, o generalmente estará disponible para cada usuario?'; $string['reserved_title'] = 'Elemento reservado. Haga click para liberarlo.'; -$string['reserved'] = 'Reservado'; $string['response'] = 'respuesta'; $string['responseauthor'] = 'Autor:'; $string['responses'] = 'respuestas'; @@ -371,8 +369,8 @@ $string['responsetimemodified'] = ', Última midificación en:'; $string['revieworpause'] = ', revisar o pausar'; $string['reviewsubmissions'] = 'Revisar envíos de Encuestapro'; -$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['riskyeditdeadline'] = 'Fecha límite de sesión de modificación riesgosa'; +$string['riskyeditdeadline_help'] = 'Permitirles forzar modificaciones de esta encuesta a los usuarios que tienen permitido gestionar elementos de la encuesta, aunque ya estuvieran contestados.'; $string['runreport'] = 'Correr reporte de {$a->reportname}'; $string['save'] = 'Guardar'; $string['saveasnew'] = 'Guardar como nuevo'; @@ -380,23 +378,24 @@ $string['saveusertemplates'] = 'Guardar plantillas de usuario'; $string['schemavalidationfailed'] = 'La plantilla usa un archivo XML inválido. Por favor verifíquelo'; $string['settings'] = 'Encuestapro (Surveypro)'; -$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['sharinglevel'] = 'Nivel de compartir'; +$string['sharinglevel_help'] = 'Elija en cual nivel será compartida su plantilla con otros cursos. Si Usted elige "curso", esta plantilla estará disponible SOLAMENTE en este curso. Si Usted elige categoría de curso, esta plantilla estará disponible SOLAMENTE para cursos que compartan la misma "categoría" de curso con este curso. Si Usted elige "sitio", esta plantilla estará disponible para todos y cada uno de los cursos en esta plataforma.'; $string['showallitems'] = 'Mostrar todos los elementos'; $string['showallsubmissions'] = 'Mostrar todas las respuestas'; $string['showfield_title'] = 'Elemento oculto. Haga click para mostrar.'; $string['sortindex'] = 'Orden'; $string['specializations'] = 'Configuraciones específicas de {$a}'; $string['star'] = '*'; -$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['startyear'] = 'Año mínimo permitido'; +$string['startyear_help'] = 'Definir el menor año que cada pregunta requerirá.'; $string['status'] = 'Estatus de encuesta'; $string['statusboth'] = 'ambas cerrada y en progreso'; $string['statusclosed'] = 'cerrada'; $string['statusinprogress'] = 'en progreso'; -$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['stopyear'] = 'Año máximo permitido'; +$string['stopyear_help'] = 'Definir el año más alto que cada pregunta requerirá.'; $string['submission'] = 'Intento'; +$string['submissions'] = 'Respuestas'; $string['submissions_all_1_1'] = '1 respuesta enviada por 1 usuario'; $string['submissions_all_1_many'] = '1 respuesta enviada por {$a->usercount} usuarios'; $string['submissions_all_many_1'] = '{$a->submissions} respuestas enviadas por 1 usuario'; @@ -406,7 +405,6 @@ $string['submissions_detail_many_1'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por 1 usuario'; $string['submissions_detail_many_many'] = '{$a->submissions} respuestas \'{$a->status}\' enviadas por {$a->usercount} usuarios'; $string['submissions_welcome'] = 'Vista general de respuestas'; -$string['submissions'] = 'Respuestas'; $string['submissionslist'] = 'Lista de respuestas'; $string['surveypro_dashboard'] = 'Tablero'; // Maybe 'Overview' is better? $string['surveypro_edit'] = 'Editar'; diff --git a/lang/it/surveypro.php b/lang/it/surveypro.php index 9928c8c5c4f..430f8d444a7 100644 --- a/lang/it/surveypro.php +++ b/lang/it/surveypro.php @@ -51,8 +51,8 @@ $string['cssstylefilearea'] = 'Fogli di stile'; $string['currentcategory'] = 'Questa categoria di corso'; $string['currentcourse'] = 'Questo corso'; -$string['customnumber_help'] = 'Definisce un numero personalizzato per l\'elemento. Può essere un numero intero come "1" o una qualunque altra scelta come, per esempio: 1a, A, 1.1.a, #1, A, A.1... Si consideri la coerenza della numerazione è lasciata alla tua responsabilità. Per questo, si faccia sempre una doppia verifica qualora si scegliesse di modificare l\'ordine delle domande.'; $string['customnumber'] = 'Numero dell\'elemento'; +$string['customnumber_help'] = 'Definisce un numero personalizzato per l\'elemento. Può essere un numero intero come "1" o una qualunque altra scelta come, per esempio: 1a, A, 1.1.a, #1, A, A.1... Si consideri la coerenza della numerazione è lasciata alla tua responsabilità. Per questo, si faccia sempre una doppia verifica qualora si scegliesse di modificare l\'ordine delle domande.'; $string['deleteallitems'] = 'Elimina tutti gli elementi'; $string['deleteallsubmissions'] = 'Cancella tutte le risposte'; $string['deletehiddenitems'] = 'Elimina gli elementi nascosti'; @@ -88,43 +88,43 @@ $string['event_usertemplate_exported'] = 'Esportato "template utente"'; $string['event_usertemplate_imported'] = 'Importato "template utente"'; $string['event_usertemplate_saved'] = 'Salvato "template utente"'; -$string['extranote_help'] = 'Breve nota aggiuntiva relativa a dettagli necessari per rispondere a questa domanda.'; $string['extranote'] = 'Nota personalizzata'; +$string['extranote_help'] = 'Breve nota aggiuntiva relativa a dettagli necessari per rispondere a questa domanda.'; $string['feedback_deleteallresponses'] = 'Tutte le risposte sono state cancellate con successo'; $string['gotolist'] = 'Mostra la lista'; -$string['hassubmissions_alert_activitycompletion'] = '
La modifica degli elementi del sondaggio cambierà anche lo stato di completamento dell\'attività.
Sei stato avvisato.'; $string['hassubmissions_alert'] = 'Questo sondaggio è stato già compilato almeno una volta.
Si procedera con estrema cautela e si apportino solo modifiche neutre per non compromettere la validità dell\'intero sondaggio.

ATTENZIONE: Aggiungendo un nuovo elemento lo stato di ogni risposta già inviata verrà forzato a "in corso".'; +$string['hassubmissions_alert_activitycompletion'] = '
La modifica degli elementi del sondaggio cambierà anche lo stato di completamento dell\'attività.
Sei stato avvisato.'; $string['hassubmissions_danger'] = '
Le risposte "in corso"...
  • sono soggette a cancellazione in 4 ore se la pausa/ripresa non è consentita;
  • sono soggette a cancellazione nel numero di ore impostato nelle impostazioni di surveypro se la pausa/ripresa è consentita.
'; -$string['hidden_help'] = 'Nascondi questa domanda qualora sia ancora in fase di definizione o, comunque, non ancora pronta per comparire regolarmente nel questionario.'; $string['hidden'] = 'Nascosta'; +$string['hidden_help'] = 'Nascondi questa domanda qualora sia ancora in fase di definizione o, comunque, non ancora pronta per comparire regolarmente nel questionario.'; $string['hideallitems'] = 'Nascondi tutti gli elementi'; -$string['hideinstructions_help'] = 'Nasconde o mostra le istruzioni di compilazione. Queste indirizzano l\'utente a fornire la risposta attesa riducendo il tempo necesario alla compilazione del questionario.'; $string['hideinstructions'] = 'Nascondi le istruzioni di compilazione'; +$string['hideinstructions_help'] = 'Nasconde o mostra le istruzioni di compilazione. Queste indirizzano l\'utente a fornire la risposta attesa riducendo il tempo necesario alla compilazione del questionario.'; $string['importusertemplates'] = 'Importa un template utente'; $string['includedates'] = 'Includi le date di creazione e modifica'; $string['includehidden'] = 'Includi gli elementi nascosti'; $string['includereserved'] = 'Includi gli elementi riservati'; -$string['indent_help'] = 'Il rientro dell\'elemento ovvero il margine sinistro che avrà rispetto alla pagina del questionario.'; $string['indent'] = 'Rientro'; -$string['insearchform_help'] = 'Includi questo elemento fra i campi di ricerca?'; +$string['indent_help'] = 'Il rientro dell\'elemento ovvero il margine sinistro che avrà rispetto alla pagina del questionario.'; $string['insearchform'] = 'Includi nella ricerca'; +$string['insearchform_help'] = 'Includi questo elemento fra i campi di ricerca?'; $string['item'] = 'Elemento'; $string['itemcontentfilearea'] = 'Contentenuto degli elementi'; +$string['layout'] = 'Scheda'; $string['layout_branchingvalidation'] = 'Relazioni'; $string['layout_edititem'] = 'Modifica elemento'; $string['layout_items'] = 'Elementi'; $string['layout_itemsetup'] = 'Nuovo elemento'; $string['layout_preview'] = 'Anteprima'; -$string['layout'] = 'Scheda'; $string['manageusertemplates'] = 'Gestisci i template utente'; $string['maxentries'] = 'Numero massimo di risposte consentite'; +$string['modulename'] = 'Surveypro'; $string['modulename_help'] = 'Surveypro consente la realizzazione di indagini personalizzate così come di indagini classiche quali ATTLS, COLLES and CRITICAL INCIDENTS. E\' possibile anche riutilizzare parti di indagini già costruite per integrarle in altre.'; $string['modulename_link'] = 'mod/surveypro/view'; -$string['modulename'] = 'Surveypro'; $string['modulenameplural'] = 'surveypro'; +$string['mtemplate'] = 'Template di sistema'; $string['mtemplate_apply'] = 'Applica'; $string['mtemplate_save'] = 'Salva'; -$string['mtemplate'] = 'Template di sistema'; $string['nextformpage'] = 'Pagina successiva >>'; $string['noanswer'] = 'Nessuna risposta'; $string['noitemsfound'] = 'This survey is still a work in progress.
Please try again later.'; @@ -138,18 +138,18 @@ $string['opened'] = 'Data di apertura'; $string['outputstyle'] = 'Stile del file'; $string['parentconstraints'] = 'Opzioni di relazione'; -$string['parentcontent_help'] = 'Risposta che l\'utente deve fornire all\'elemento padre affinché questo elemento divenga acessibile.'; $string['parentcontent'] = 'Risposta abilitante'; -$string['parentelement_help'] = 'Elemento la cui risposta, in fase di compilazione del questionario, determina l\'accesso a all\'elemento corrente'; +$string['parentcontent_help'] = 'Risposta che l\'utente deve fornire all\'elemento padre affinché questo elemento divenga acessibile.'; $string['parentelement'] = 'Elemento padre'; +$string['parentelement_help'] = 'Elemento la cui risposta, in fase di compilazione del questionario, determina l\'accesso a all\'elemento corrente'; $string['parentformat'] = 'Definisci il formato del "{$a->fieldname}" come dai seguenti esempi: {$a->examples}'; $string['pause'] = 'Pausa'; -$string['pauseresume_help'] = 'Consente di interrompere una compilazione per riprenderla ed inviarla in un secondo momento'; $string['pauseresume'] = 'Consenti Pausa/Ripresa'; +$string['pauseresume_help'] = 'Consente di interrompere una compilazione per riprenderla ed inviarla in un secondo momento'; $string['pluginadministration'] = 'Amministrazione surveypro'; $string['pluginname'] = 'Surveypro'; -$string['position_help'] = 'Colloca il testo della domanda intorno all\'elemento di acquisizione del dato. La collocazione può essere a sinistra dell\'elemento di input, in una riga dedicata immediatamente sopra all\'elemento di input oppure, sempre sopra all\'elemento di input, ma ricoprendo l\'intera larghezza della pagina.'; $string['position'] = 'Collocazione della domanda'; +$string['position_help'] = 'Colloca il testo della domanda intorno all\'elemento di acquisizione del dato. La collocazione può essere a sinistra dell\'elemento di input, in una riga dedicata immediatamente sopra all\'elemento di input oppure, sempre sopra all\'elemento di input, ma ricoprendo l\'intera larghezza della pagina.'; $string['previewmode'] = 'Sei in \'{$a}\'. I bottoni per il salvataggio dei dati non saranno visualizzati'; $string['previousformpage'] = '<< Pagina precedente'; $string['raw'] = 'Grezzo (per ulteriori importazioni in surveypro; il "{$a}" scelto potrebbe non essere rispettato;)'; @@ -167,10 +167,10 @@ $string['reminderpaused_content3'] = '
Per favore, cerca di collegarti al più presto a {$a} per inviare definitivamente le informazioni richieste.

Il personale di progetto'; $string['remindneverstarted_content'] = 'Gentile {$a->fullname}
sembra che il tuo contributo all\'indagine "{$a->surveyproname}" non sia mai stato avviato.
Per favore, collegati al più presto a {$a->surveyprourl} per avviare la tua collaborazione con l\'indagine che ti vede coinvolto.

Il personale di progetto'; $string['reports'] = 'Rapporti'; -$string['required_help'] = 'Rende questa domanda obbligatoria o opzionale per l\'utente?'; $string['required'] = 'Obbligatorio'; -$string['reserved_help'] = 'Rendi questo elemento disponibile solo agli utenti con specifico permesso di compilazione o, in alternativa, rendi questo elemento accessibile a chiunque.'; +$string['required_help'] = 'Rende questa domanda obbligatoria o opzionale per l\'utente?'; $string['reserved'] = 'Riservato'; +$string['reserved_help'] = 'Rendi questo elemento disponibile solo agli utenti con specifico permesso di compilazione o, in alternativa, rendi questo elemento accessibile a chiunque.'; $string['revieworpause'] = ', rivederlo o metterlo in pausa'; $string['runreport'] = 'Esegui il report {$a->reportname}'; $string['savemastertemplates'] = 'Salva un master template'; diff --git a/layout.php b/layout.php index 3d373c7066f..f9834c21320 100644 --- a/layout.php +++ b/layout.php @@ -25,11 +25,11 @@ use mod_surveypro\utility_page; use mod_surveypro\utility_layout; use mod_surveypro\utility_submission; -use mod_surveypro\utility_mform; use mod_surveypro\layout_itemsetup; use mod_surveypro\layout_itemlist; use mod_surveypro\layout_preview; +use mod_surveypro\layout_branchingvalidation; use mod_surveypro\utemplate_apply; use mod_surveypro\mtemplate_apply; @@ -40,7 +40,7 @@ use mod_surveypro\local\form\utemplate_applyform; use mod_surveypro\local\form\mtemplate_applyform; use mod_surveypro\local\form\item_bulkactionform; -use mod_surveypro\local\form\userform; +use mod_surveypro\local\form\response_submitform; require_once(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/lib.php'); @@ -83,8 +83,6 @@ $overflowpage = optional_param('overflowpage', 0, PARAM_INT); // Went the user to a overflow page? // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - $previewman = new layout_preview($cm, $context, $surveypro); $previewman->setup($submissionid, $formpage); @@ -110,7 +108,7 @@ $formparams->overflowpage = $overflowpage; // Went the user to a overflow page? // End of: prepare params for the form. - $userform = new userform($formurl, $formparams, 'post', '', ['id' => 'userentry']); + $userform = new response_submitform($formurl, $formparams, 'post', '', ['id' => 'userentry', 'class' => 'narrowlines']); // Begin of: manage form submission. if ($data = $userform->get_data()) { @@ -365,7 +363,7 @@ $plugin = optional_param('plugin', null, PARAM_TEXT); $itemid = optional_param('itemid', 0, PARAM_INT); $action = optional_param('act', SURVEYPRO_NOACTION, PARAM_INT); - $mode = optional_param('mode', SURVEYPRO_NOMODE, PARAM_INT); // Ho sostituito SURVEYPRO_NEWRESPONSEMODE con SURVEYPRO_NOMODE? + $mode = optional_param('mode', SURVEYPRO_NOMODE, PARAM_INT); // I replaced SURVEYPRO_NEWRESPONSEMODE con SURVEYPRO_NOMODE? // Required capability. require_capability('mod/surveypro:additems', $context); @@ -398,8 +396,7 @@ // Begin of: get item. $itemtype = $itemsetupman->get_type(); $itemplugin = $itemsetupman->get_plugin(); - $item = surveypro_get_item($cm, $surveypro, $itemid, $itemtype, $itemplugin, true); - $item->set_editor(); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $itemtype, $itemplugin, true); // End of: get item. // Set $PAGE params. @@ -428,7 +425,7 @@ // End of: define $itemform return url. // Begin of: prepare params for the form. - $classname = 'surveyprofield_'.$itemplugin.'\itemsetupform'; + $classname = 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemplugin.'\itemsetupform'; $itemform = new $classname($formurl, ['item' => $item], null, null, ['id' => 'itemsetup']); // End of: prepare params for the form. @@ -448,7 +445,7 @@ $feedback = $item->get_itemeditingfeedback(); // Copy the returned feedback. // Overwrite item to get new settings in the object. - $item = surveypro_get_item($cm, $surveypro, $itemid, $item->get_type(), $item->get_plugin()); + $item = surveypro_get_itemclass($cm, $surveypro, $itemid, $item->get_type(), $item->get_plugin()); $item->item_update_childrenparentvalue(); $paramurl = ['s' => $cm->instance, 'section' => 'itemslist', 'iefeedback' => $feedback]; @@ -468,9 +465,9 @@ $message = $utilitysubmissionman->get_submissions_warning(); echo $OUTPUT->notification($message, 'notifyproblem'); } - $itemsetupman->item_identitycard(); + $itemsetupman->display_iteminfo(); - $data = $item->get_itemform_preset(); + $data = $item->get_plugin_presets(); $itemform->set_data($data); $itemform->display(); diff --git a/lib.php b/lib.php index d3dac42c2c3..4adc06344cb 100644 --- a/lib.php +++ b/lib.php @@ -89,6 +89,7 @@ // ACTIONS in UTEMPLATE section. define('SURVEYPRO_DELETEUTEMPLATE' , '21'); define('SURVEYPRO_EXPORTUTEMPLATE' , '22'); +define('SURVEYPRO_APPLYUTEMPLATE' , '23'); /** * VIEW @@ -126,11 +127,6 @@ /** * INVITE, NO-ANSWER AND IGNOREME VALUE */ -// Since the very first beginning of the development. -// define('SURVEYPRO_INVITATIONVALUE', '__invItat10n__'); // User should never guess it. -// define('SURVEYPRO_NOANSWERVALUE', '__n0__Answer__'); // User should never guess it. -// define('SURVEYPRO_IGNOREMEVALUE', '__1gn0rE__me__'); // User should never guess it. - // Starting from version 2015090901. define('SURVEYPRO_INVITEVALUE' , '@@_INVITE_@@'); // User should never guess it. define('SURVEYPRO_NOANSWERVALUE' , '@@_NOANSW_@@'); // User should never guess it. @@ -266,6 +262,15 @@ require_once($CFG->dirroot.'/mod/surveypro/deprecatedlib.php'); /* Do not include any libraries here! */ +/** + * Get icon mapping for font-awesome. + * + * @return array + */ +function mod_surveypro_get_fontawesome_icon_map() { + return ['mod_surveypro:stamp' => 'fa-solid fa-stamp']; +} + /** * Saves a new instance of the surveypro into the database * @@ -1156,7 +1161,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $fieldplugins = core_component::get_plugin_list('surveypro'.SURVEYPRO_TYPEFIELD); if (!empty($includetype)) { foreach ($fieldplugins as $k => $v) { - if (!get_config('surveyprofield_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFIELD.'_'.$k, 'disabled')) { $fieldplugins[$k] = SURVEYPRO_TYPEFIELD.'_'.$k; } else { unset($fieldplugins[$k]); @@ -1165,7 +1170,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $fieldplugins = array_flip($fieldplugins); } else { foreach ($fieldplugins as $k => $v) { - if (!get_config('surveyprofield_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFIELD.'_'.$k, 'disabled')) { $fieldplugins[$k] = $k; } else { unset($fieldplugins[$k]); @@ -1181,7 +1186,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $formatplugins = core_component::get_plugin_list('surveypro'.SURVEYPRO_TYPEFORMAT); if (!empty($includetype)) { foreach ($formatplugins as $k => $v) { - if (!get_config('surveyproformat_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$k, 'disabled')) { $formatplugins[$k] = SURVEYPRO_TYPEFORMAT.'_'.$k; } else { unset($formatplugins[$k]); @@ -1190,7 +1195,7 @@ function surveypro_get_plugin_list($plugintype=null, $includetype=false, $count= $formatplugins = array_flip($formatplugins); } else { foreach ($formatplugins as $k => $v) { - if (!get_config('surveyproformat_'.$k, 'disabled')) { + if (!get_config('surveypro'.SURVEYPRO_TYPEFORMAT.'_'.$k, 'disabled')) { $formatplugins[$k] = $k; } else { unset($formatplugins[$k]); @@ -1350,7 +1355,7 @@ function surveypro_inplace_editable($itemtype, $id, $newvalue) { * @param bool $getparentcontent * @return $item object */ -function surveypro_get_item($cm, $surveypro, $itemid=0, $type='', $plugin='', $getparentcontent=false) { +function surveypro_get_itemclass($cm, $surveypro, $itemid=0, $type='', $plugin='', $getparentcontent=false) { global $CFG, $DB; if (!empty($itemid)) { diff --git a/mod_form.php b/mod_form.php index a732d62a1f3..29604c9e804 100644 --- a/mod_form.php +++ b/mod_form.php @@ -253,8 +253,9 @@ public function data_preprocessing(&$defaults) { $draftitemid = file_get_submitted_draft_itemid($filename.'_filemanager'); if ($this->current->instance) { - file_prepare_draft_area($draftitemid, $this->context->id, 'mod_surveypro', - SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions); + file_prepare_draft_area( + $draftitemid, $this->context->id, 'mod_surveypro', SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions + ); $defaults[$filename.'_filemanager'] = $draftitemid; // Manage thankspage editor. @@ -262,8 +263,10 @@ public function data_preprocessing(&$defaults) { $editoroptions = surveypro_get_editor_options(); // Editing an existing surveypro - let us prepare the added editor elements (intro done automatically). $draftitemid = file_get_submitted_draft_itemid('thankspage'); - $defaults[$filename]['text'] = file_prepare_draft_area($draftitemid, $this->context->id, - 'mod_surveypro', SURVEYPRO_THANKSPAGEFILEAREA, 0, $editoroptions, $defaults['thankspage']); + $defaults[$filename]['text'] = file_prepare_draft_area( + $draftitemid, $this->context->id, + 'mod_surveypro', SURVEYPRO_THANKSPAGEFILEAREA, 0, $editoroptions, $defaults['thankspage'] + ); $defaults[$filename]['format'] = $defaults['thankspageformat']; $defaults[$filename]['itemid'] = $draftitemid; @@ -282,8 +285,9 @@ public function data_preprocessing(&$defaults) { $defaults[$filename]['format'] = $defaults['mailcontentformat']; } } else { - file_prepare_draft_area($draftitemid, $this->context->id, 'mod_surveypro', - SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions); + file_prepare_draft_area( + $draftitemid, $this->context->id, 'mod_surveypro', SURVEYPRO_STYLEFILEAREA, 0, $filemanageroptions + ); $defaults[$filename.'_filemanager'] = $draftitemid; // Manage thankspage editor. diff --git a/mtemplates.php b/mtemplates.php index a2b5f68a4d5..1c28b067f72 100644 --- a/mtemplates.php +++ b/mtemplates.php @@ -37,8 +37,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('mtemplates'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); @@ -77,7 +77,12 @@ // Start of: define $createmtemplate return url. $formurl = new \moodle_url('/mod/surveypro/mtemplates.php', ['s' => $cm->instance, 'section' => 'save']); - $createmtemplate = new mtemplate_createform($formurl); + // End of: define $createutemplate return url. + + // Begin of: prepare params for the form. + $formparams = new \stdClass(); + $formparams->defaultname = $surveypro->name; + $createmtemplate = new mtemplate_createform($formurl, $formparams); // End of: define $createmtemplate return url. // Start of: manage form submission. @@ -140,8 +145,12 @@ // Begin of: manage form submission. if ($applyman->formdata = $applymtemplate->get_data()) { - $applyman->apply_template(); - $applyman->trigger_event('mastertemplate_applied'); + $applyman->set_mastertemplate($applyman->formdata->mastertemplate); + $applyman->lastminute_template_check(); + if (!isset($applyman->xmlvalidationoutcome->key)) { + $applyman->apply_template(); + $applyman->trigger_event('mastertemplate_applied'); + } } // End of: manage form submission. @@ -163,6 +172,8 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_mtemplates_action_bar(); + $applyman->lastminute_stop(); + $applyman->friendly_stop(); $riskyediting = ($surveypro->riskyeditdeadline > time()); diff --git a/pix/stamp.png b/pix/stamp.png new file mode 100644 index 0000000000000000000000000000000000000000..88eb31238b69a7db5cb0c5200fe4ea5e4bf31c30 GIT binary patch literal 379 zcmV->0fhdEP)K~zebQL3i#3MvYv2T)Mycmb6}FCR`y!CB0_g#90z#Ky^rxqZXbbDw6Ts&JmCaspaA9&SSn$Q z8Jq9s*Ywt8o);yondd||xk}&?U#OR`g?zzv54%qWXE-kHduR?5;u_vClJ|RTRdGiv zEOcy)VJfBcfoYsq5&H?W^PJ6jz)ht002ovPDHLkV1mA)naltH literal 0 HcmV?d00001 diff --git a/pix/stamp.svg b/pix/stamp.svg new file mode 100644 index 00000000000..29a212a0389 --- /dev/null +++ b/pix/stamp.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/report/attachments/classes/filterform.php b/report/attachments/classes/filterform.php index 5ba7a987cd7..395000638be 100644 --- a/report/attachments/classes/filterform.php +++ b/report/attachments/classes/filterform.php @@ -73,7 +73,7 @@ public function definition() { if ($itemseed->plugin != 'fileupload') { continue; } - $content = $DB->get_field('surveyprofield_fileupload', 'content', ['itemid' => $itemseed->id]); + $content = $DB->get_field('surveypro_item', 'content', ['id' => $itemseed->id]); $options[$itemseed->id] = strip_tags($content); } $itemseeds->close(); diff --git a/report/attachments/classes/form.php b/report/attachments/classes/form.php index 002d3933273..51685c2f7bc 100644 --- a/report/attachments/classes/form.php +++ b/report/attachments/classes/form.php @@ -54,6 +54,16 @@ class form { */ protected $surveypro; + /** + * @var int $userid + */ + protected $userid; + + /** + * @var int $itemid + */ + protected $itemid; + /** * @var int ID of the saved suryey_submission */ @@ -171,10 +181,9 @@ public function display_attachment($submissionid, $itemid) { echo $renderer->render_report_paragraph($viewreportparagraph); $whereparams = ['submissionid' => $submissionid, 'plugin' => 'fileupload']; - $sql = 'SELECT i.id, a.id as answerid, fu.content + $sql = 'SELECT i.id, i.content, a.id as answerid FROM {surveypro_item} i JOIN {surveypro_answer} a ON a.itemid = i.id - JOIN {surveyprofield_fileupload} fu ON fu.itemid = a.itemid WHERE i.plugin = :plugin AND a.submissionid = :submissionid'; if ($itemid) { diff --git a/report/attachments/classes/report.php b/report/attachments/classes/report.php index a5af3a9a445..eabb4847663 100644 --- a/report/attachments/classes/report.php +++ b/report/attachments/classes/report.php @@ -93,7 +93,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'attachments'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/attachments/lang/en/surveyproreport_attachments.php b/report/attachments/lang/en/surveyproreport_attachments.php index 73cf1e4667f..1725f0967f1 100644 --- a/report/attachments/lang/en/surveyproreport_attachments.php +++ b/report/attachments/lang/en/surveyproreport_attachments.php @@ -28,11 +28,11 @@ $string['missing_uploads'] = 'No attachments found'; $string['noattachmentitemsfound'] = 'No attachment items were found in this survey.'; $string['nofilesfound'] = 'no attachment uploaded'; +$string['notinanygroup'] = 'Not in any group'; $string['pluginname'] = 'Attachments overview'; +$string['privacy:metadata'] = 'The "Attachments" report plugin does not store any personal data.'; $string['submission'] = 'Response'; $string['submissionid'] = 'Response id'; $string['submissioninfo'] = 'Response info'; $string['submissions'] = 'Responses'; $string['uploads'] = 'Uploads'; -$string['notinanygroup'] = 'Not in any group'; -$string['privacy:metadata'] = 'The "Attachments" report plugin does not store any personal data.'; diff --git a/report/attachments/tests/behat/attachment_functionality.feature b/report/attachments/tests/behat/attachment_functionality.feature index fe692283859..87b72fcc494 100644 --- a/report/attachments/tests/behat/attachment_functionality.feature +++ b/report/attachments/tests/behat/attachment_functionality.feature @@ -26,9 +26,6 @@ Feature: Test attachment report And the following "permission overrides" exist: | capability | permission | role | contextlevel | reference | | mod/surveypro:editownsubmissions | Allow | student | Course | Test attachment report | - And the following "user preferences" exist: - | user | preference | value | - | teacher1 | htmleditor | textarea | And the following "activities" exist: | activity | name | intro | course | | surveypro | Attachment report test | To test functionality of attachment report | Test attachment report | diff --git a/report/attachments/version.php b/report/attachments/version.php index 914a9144153..7beaddd4c97 100644 --- a/report/attachments/version.php +++ b/report/attachments/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023120101; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_attachments'; // Full name of the plugin (used for diagnostics). diff --git a/report/attachments/view.php b/report/attachments/view.php index ac63569891a..6233fac7558 100644 --- a/report/attachments/view.php +++ b/report/attachments/view.php @@ -194,7 +194,7 @@ $formparams->canviewhiddenactivities = $canviewhiddenactivities; // End of: prepare params for the form. - $filterform = new filterform($formurl, $formparams, 'post', '', ['id' => 'userentry']); + $filterform = new filterform($formurl, $formparams, 'post', '', ['id' => 'userentry', 'class' => 'narrowlines']); // Output starts here. echo $OUTPUT->header(); diff --git a/report/colles/classes/report.php b/report/colles/classes/report.php index 95977a9c17b..0a24d40f3dd 100644 --- a/report/colles/classes/report.php +++ b/report/colles/classes/report.php @@ -330,8 +330,8 @@ public function fetch_summarydata() { // Begin of: options (label of answers). $itemid = $qid1area[0][0]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->ylabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->ylabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: calculate the mean and the standard deviation of answers. @@ -486,8 +486,8 @@ public function fetch_scalesdata($areaidx=0) { // Begin of: options (label of answers). $itemid = $qid1area[0][0]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->ylabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->ylabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: calculate the mean and the standard deviation of answers. @@ -607,8 +607,8 @@ public function fetch_questionsdata($areaidx, $qid) { // Begin of: options (label of answers). $itemid = $qid1area[$areaidx][$qid]; // One of the itemid of the surveypro (the first). - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); - $this->xlabels = $item->get_content_array(SURVEYPRO_LABELS, 'options'); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid, SURVEYPRO_TYPEFIELD, $this->templateuseritem); + $this->xlabels = $item->get_textarea_content(SURVEYPRO_LABELS, 'options'); // End of: options (label of answers). // Begin of: graph title. diff --git a/report/colles/graph.php b/report/colles/graph.php index e4f5aba3a3c..ea8495cb9bd 100644 --- a/report/colles/graph.php +++ b/report/colles/graph.php @@ -28,8 +28,8 @@ require_once($CFG->libdir.'/graphlib.php'); require_once($CFG->dirroot.'/mod/surveypro/report/colles/lib.php'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $type = required_param('type', PARAM_ALPHA); // Report type. if (!empty($id)) { diff --git a/report/colles/lang/en/surveyproreport_colles.php b/report/colles/lang/en/surveyproreport_colles.php index e356743692b..79351720241 100644 --- a/report/colles/lang/en/surveyproreport_colles.php +++ b/report/colles/lang/en/surveyproreport_colles.php @@ -22,46 +22,46 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Colles report'; -$string['seemoredetail'] = 'Click here to see more detail'; - -$string['summary'] = 'Summary report'; - -$string['collespreferred'] = 'preferred'; $string['collesactual'] = 'actual'; - -$string['summaryreport'] = 'Summary report'; -$string['scalesreport'] = 'Scales report'; -$string['questionsreport'] = 'Questions report'; - +$string['collespreferred'] = 'preferred'; +$string['pluginname'] = 'Colles report'; +$string['privacy:metadata'] = 'The "Colles" report plugin does not store any personal data.'; $string['question01short'] = 'focus on interesting issues'; $string['question02short'] = 'important to my practice'; $string['question03short'] = 'improve my practice'; $string['question04short'] = 'connects with my practice'; - $string['question05short'] = 'I\'m critical of my learning'; $string['question06short'] = 'I\'m critical of my own ideas'; $string['question07short'] = 'I\'m critical of other students'; $string['question08short'] = 'I\'m critical of readings'; - $string['question09short'] = 'I explain my ideas'; $string['question10short'] = 'I ask for explanations'; $string['question11short'] = 'I\'m asked to explain'; $string['question12short'] = 'students respond to me'; - $string['question13short'] = 'tutor stimulates thinking'; $string['question14short'] = 'tutor encourages me'; $string['question15short'] = 'tutor models discourse'; $string['question16short'] = 'tutor models self-reflection'; - $string['question17short'] = 'students encourage me'; $string['question18short'] = 'students praise me'; $string['question19short'] = 'students value me'; $string['question20short'] = 'students empathise'; - $string['question21short'] = 'I understand other students'; $string['question22short'] = 'students understand me'; $string['question23short'] = 'I understand the tutor'; $string['question24short'] = 'tutor understands me'; +$string['questionsreport'] = 'Questions report'; +$string['scalesreport'] = 'Scales report'; +$string['seemoredetail'] = 'Click here to see more detail'; + +$string['summary'] = 'Summary report'; + + +$string['summaryreport'] = 'Summary report'; + + + + + + -$string['privacy:metadata'] = 'The "Colles" report plugin does not store any personal data.'; diff --git a/report/colles/version.php b/report/colles/version.php index c147f9516ee..4cd4b115c9c 100644 --- a/report/colles/version.php +++ b/report/colles/version.php @@ -24,9 +24,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->dependencies = [ 'surveyprotemplate_collesactual' => 2013103101, 'surveyprotemplate_collesactualpreferred' => 2013103101, diff --git a/report/frequency/classes/filterform.php b/report/frequency/classes/filterform.php index 4562eb94ed3..0e859b635bb 100644 --- a/report/frequency/classes/filterform.php +++ b/report/frequency/classes/filterform.php @@ -71,13 +71,14 @@ public function definition() { if (($itemseed->plugin == 'textarea') || ($itemseed->plugin == 'fileupload')) { continue; } - $where = ['itemid' => $itemseed->id]; - $thiscontent = $DB->get_field('surveypro'.$itemseed->type.'_'.$itemseed->plugin, 'content', $where); + $where = ['id' => $itemseed->id]; + $thiscontent = $DB->get_field('surveypro_item', 'content', $where); if (!empty($surveypro->template)) { $thiscontent = get_string($thiscontent, 'surveyprotemplate_'.$surveypro->template); } - $content = get_string('pluginname', 'surveyprofield_'.$itemseed->plugin).$labelsep.strip_tags($thiscontent); + $content = get_string('pluginname', 'surveypro'.SURVEYPRO_TYPEFIELD.'_'.$itemseed->plugin); + $content .= $labelsep.strip_tags($thiscontent); $content = surveypro_cutdownstring($content); $options[$itemseed->id] = $content; } diff --git a/report/frequency/classes/report.php b/report/frequency/classes/report.php index 98561e31bf5..0e9596d6820 100644 --- a/report/frequency/classes/report.php +++ b/report/frequency/classes/report.php @@ -103,7 +103,6 @@ public function setup_outputtable($itemid) { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'frequencies'); $this->outputtable->set_attribute('class', 'generaltable'); @@ -166,7 +165,7 @@ public function fetch_data($itemid) { // TAKE CARE: this is the answer count, not the submissions count! They may be different. [$sql, $whereparams] = $this->get_answercount_sql($itemid); $answercount = $DB->count_records_sql($sql, $whereparams); - $item = surveypro_get_item($this->cm, $this->surveypro, $itemid); + $item = surveypro_get_itemclass($this->cm, $this->surveypro, $itemid); $decimalseparator = get_string('decsep', 'langconfig'); foreach ($answers as $answer) { diff --git a/report/frequency/graph.php b/report/frequency/graph.php index d017eaef689..5a9524c7ed7 100644 --- a/report/frequency/graph.php +++ b/report/frequency/graph.php @@ -47,7 +47,7 @@ list($sql, $whereparams) = $reportman->get_submissions_sql($itemid); $answers = $DB->get_recordset_sql($sql, $whereparams); -$item = surveypro_get_item($cm, $surveypro, $itemid); +$item = surveypro_get_itemclass($cm, $surveypro, $itemid); $content = []; $absolute = []; diff --git a/report/frequency/lang/en/surveyproreport_frequency.php b/report/frequency/lang/en/surveyproreport_frequency.php index 6a83cc34523..01978b8df58 100644 --- a/report/frequency/lang/en/surveyproreport_frequency.php +++ b/report/frequency/lang/en/surveyproreport_frequency.php @@ -24,11 +24,11 @@ $string['absolute'] = 'absolute'; $string['content'] = 'answer'; -$string['itemid_help'] = 'The variable to calculate its distribution'; $string['itemid'] = 'Survey question'; +$string['itemid_help'] = 'The variable to calculate its distribution'; $string['nosubmissionsfound'] = 'No submissions found'; $string['percentage'] = 'percentage'; $string['pleasechooseavalue'] = 'Please choose a variable to make its distribution'; $string['pluginname'] = 'Frequency distribution'; -$string['textareasarenotallowed'] = 'This survey has no fields or uses only fields, among visible and not reserved, that are not suitable for this report.'; $string['privacy:metadata'] = 'The "Frequency" report plugin does not store any personal data.'; +$string['textareasarenotallowed'] = 'This survey has no fields or uses only fields, among visible and not reserved, that are not suitable for this report.'; diff --git a/report/frequency/lang/it/surveyproreport_frequency.php b/report/frequency/lang/it/surveyproreport_frequency.php index 20c4409f121..fc6399e643f 100644 --- a/report/frequency/lang/it/surveyproreport_frequency.php +++ b/report/frequency/lang/it/surveyproreport_frequency.php @@ -22,5 +22,5 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Distribuzione di frequenza'; $string['nosubmissionsfound'] = 'Nessuna risposta trovata.'; +$string['pluginname'] = 'Distribuzione di frequenza'; diff --git a/report/frequency/version.php b/report/frequency/version.php index 9f8eace287a..1fe4c88a0a7 100644 --- a/report/frequency/version.php +++ b/report/frequency/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_frequency'; // Full name of the plugin (used for diagnostics). diff --git a/report/lateusers/classes/report.php b/report/lateusers/classes/report.php index 67667e90991..c5dcadd03aa 100644 --- a/report/lateusers/classes/report.php +++ b/report/lateusers/classes/report.php @@ -98,7 +98,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'lateusers'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/lateusers/version.php b/report/lateusers/version.php index 4b0252261d8..d65e456c7f8 100644 --- a/report/lateusers/version.php +++ b/report/lateusers/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_lateusers'; // Full name of the plugin (used for diagnostics). diff --git a/report/responsesperuser/classes/report.php b/report/responsesperuser/classes/report.php index c12a4493946..c518f8ce1ca 100644 --- a/report/responsesperuser/classes/report.php +++ b/report/responsesperuser/classes/report.php @@ -101,7 +101,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); // $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'responsesperuser'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/responsesperuser/version.php b/report/responsesperuser/version.php index 448effd9ba0..43b6c852197 100644 --- a/report/responsesperuser/version.php +++ b/report/responsesperuser/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_responsesperuser'; // Full name of the plugin (used for diagnostics). diff --git a/report/userspercount/classes/report.php b/report/userspercount/classes/report.php index 3533d470aac..727202c7000 100644 --- a/report/userspercount/classes/report.php +++ b/report/userspercount/classes/report.php @@ -95,7 +95,6 @@ public function setup_outputtable() { $this->outputtable->column_suppress('fullname'); // General properties for the whole table. - $this->outputtable->summary = get_string('submissionslist', 'mod_surveypro'); // $this->outputtable->set_attribute('cellpadding', '5'); $this->outputtable->set_attribute('id', 'userattempts'); $this->outputtable->set_attribute('class', 'generaltable'); diff --git a/report/userspercount/lang/en/surveyproreport_userspercount.php b/report/userspercount/lang/en/surveyproreport_userspercount.php index 027854afd28..1aaa486236e 100644 --- a/report/userspercount/lang/en/surveyproreport_userspercount.php +++ b/report/userspercount/lang/en/surveyproreport_userspercount.php @@ -23,5 +23,5 @@ */ $string['pluginname'] = 'Users per count of responses'; -$string['userresponses'] = 'Count of submitted responses'; $string['privacy:metadata'] = 'The "Users per count" report plugin does not store any personal data.'; +$string['userresponses'] = 'Count of submitted responses'; diff --git a/report/userspercount/version.php b/report/userspercount/version.php index 84eef6c1840..8bc8284e9d4 100644 --- a/report/userspercount/version.php +++ b/report/userspercount/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyproreport_userspercount'; // Full name of the plugin (used for diagnostics). diff --git a/reports.php b/reports.php index 9b9f9343296..7537aa2a59f 100644 --- a/reports.php +++ b/reports.php @@ -24,8 +24,8 @@ require_once(dirname(__FILE__).'/../../config.php'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $report = optional_param('report', null, PARAM_TEXT); // Requested report. Section is the report name. if (!empty($id)) { diff --git a/styles.css b/styles.css index 1f7453c10c3..32be52102e3 100644 --- a/styles.css +++ b/styles.css @@ -23,12 +23,12 @@ /* End of: hacky coluorunifier html element */ /* Begin of: connect note to question */ -.path-mod-surveypro #userentry > div.fitem, -.path-mod-surveypro #usersearch > div.fitem, -.path-mod-surveypro #userentry > fieldset > div > div.fitem, -.path-mod-surveypro #usersearch > fieldset > div > div.fitem { - margin: 0; +/* stylelint-disable declaration-no-important */ +.path-mod-surveypro .narrowlines > div.fitem, +.path-mod-surveypro .narrowlines > fieldset > div > div.fitem { + margin-bottom: 0 !important; } +/* stylelint-enable declaration-no-important */ /* End of: connect note to question */ /* Begin of: no margin bottom to p inside question in SURVEYPRO_POSITIONTOP and SURVEYPRO_POSITIONFULLWIDTH */ @@ -222,7 +222,8 @@ text-align: center; } -.path-mod-surveypro table .dimmed { +.path-mod-surveypro table .dimmed, +.path-mod-surveypro table .dimmed:hover { color: #cdcdcd; } @@ -319,12 +320,13 @@ vertical-align: middle; } +#page-mod-surveypro-utemplates table#managetemplates td.actions img.icon, #page-mod-surveypro-utemplates table#managetemplates td.actions i.icon { width: 16px; height: 16px; - padding: 0; + margin: 0 0 0 0.45em; + padding-right: 0; vertical-align: middle; - margin-right: 0; } #page-mod-surveypro-utemplates table#managetemplates td.actions a.icon { @@ -336,175 +338,33 @@ } /* End of: #managetemplates table */ -/* classes = indent-n */ -.path-mod-surveypro .fitem .felement .indent-1 { - margin-left: 1.5em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-1 > div > select, -.path-mod-surveypro div.indent-1 > div > textarea, -.path-mod-surveypro div.indent-1 > div > input[type='text'], -.path-mod-surveypro div.indent-1 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-1 { - margin-left: 1.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-1.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-1.fileupload_filemanager ~ p { - margin-left: 1.5em; -} - -/* class = indent-2 */ -.path-mod-surveypro .fitem .felement .indent-2 { - margin-left: 3em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-2 > div > select, -.path-mod-surveypro div.indent-2 > div > textarea, -.path-mod-surveypro div.indent-2 > div > input[type='text'], -.path-mod-surveypro div.indent-2 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-2 { - margin-left: 3em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-2.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-2.fileupload_filemanager ~ p { - margin-left: 3em; -} - -/* class = indent-3 */ -.path-mod-surveypro .fitem .felement .indent-3 { - margin-left: 4.5em; -} -/* correction for select, textarea, plain text and ignoreme checkboxes that resist to the general selector */ -.path-mod-surveypro div.indent-3 > div > select, -.path-mod-surveypro div.indent-3 > div > textarea, -.path-mod-surveypro div.indent-3 > div > input[type='text'], -.path-mod-surveypro div.indent-3 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-3 { - margin-left: 4.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-3.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-3.fileupload_filemanager ~ p { - margin-left: 4.5em; -} - -/* class = indent-4 */ -.path-mod-surveypro .fitem .felement .indent-4 { - margin-left: 6em; -} -.path-mod-surveypro div.indent-4 > div > select, -.path-mod-surveypro div.indent-4 > div > textarea, -.path-mod-surveypro div.indent-4 > div > input[type='text'], -.path-mod-surveypro div.indent-4 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-4 { - margin-left: 6em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-4.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-4.fileupload_filemanager ~ p { - margin-left: 6em; -} - -/* class = indent-5 */ -.path-mod-surveypro .fitem .felement .indent-5 { - margin-left: 7.5em; -} -.path-mod-surveypro div.indent-5 > div > select, -.path-mod-surveypro div.indent-5 > div > textarea, -.path-mod-surveypro div.indent-5 > div > input[type='text'], -.path-mod-surveypro div.indent-5 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-5 { - margin-left: 7.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-5.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-5.fileupload_filemanager ~ p { - margin-left: 7.5em; -} - -/* class = indent-6 */ -.path-mod-surveypro .fitem .felement .indent-6 { - margin-left: 9em; -} -.path-mod-surveypro div.indent-6 > div > select, -.path-mod-surveypro div.indent-6 > div > textarea, -.path-mod-surveypro div.indent-6 > div > input[type='text'], -.path-mod-surveypro div.indent-6 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-6 { - margin-left: 9em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-6.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-6.fileupload_filemanager ~ p { - margin-left: 9em; -} - -/* class = indent-7 */ -.path-mod-surveypro .fitem .felement .indent-7 { - margin-left: 10.5em; -} -.path-mod-surveypro div.indent-7 > div > select, -.path-mod-surveypro div.indent-7 > div > textarea, -.path-mod-surveypro div.indent-7 > div > input[type='text'], -.path-mod-surveypro div.indent-7 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-7 { - margin-left: 10.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-7.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-7.fileupload_filemanager ~ p { - margin-left: 10.5em; -} - -/* class = indent-8 */ -.path-mod-surveypro .fitem .felement .indent-8 { - margin-left: 12em; -} -.path-mod-surveypro div.indent-8 > div > select, -.path-mod-surveypro div.indent-8 > div > textarea, -.path-mod-surveypro div.indent-8 > div > input[type='text'], -.path-mod-surveypro div.indent-8 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-8 { - margin-left: 12em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-8.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-8.fileupload_filemanager ~ p { - margin-left: 12em; -} - -/* class = indent-9 */ -.path-mod-surveypro .fitem .felement .indent-9 { - margin-left: 13.5em; -} -.path-mod-surveypro div.indent-9 > div > select, -.path-mod-surveypro div.indent-9 > div > textarea, -.path-mod-surveypro div.indent-9 > div > input[type='text'], -.path-mod-surveypro div.indent-9 > div > div > label, -.path-mod-surveypro .form-group div.fitem.indent-9 { - margin-left: 13.5em; -} -/* correction for fileupload_filemanager specifications that resist to the general selector */ -.path-mod-surveypro div.indent-9.fileupload_filemanager ~ div, -.path-mod-surveypro div.indent-9.fileupload_filemanager ~ p { - margin-left: 13.5em; -} - -/* This is for checkboxes affected by MDL-62634 */ -.path-mod-surveypro label.indent-1 > input[type='checkbox'].indent-1, -.path-mod-surveypro label.indent-2 > input[type='checkbox'].indent-2, -.path-mod-surveypro label.indent-3 > input[type='checkbox'].indent-3, -.path-mod-surveypro label.indent-4 > input[type='checkbox'].indent-4, -.path-mod-surveypro label.indent-5 > input[type='checkbox'].indent-5, -.path-mod-surveypro label.indent-6 > input[type='checkbox'].indent-6, -.path-mod-surveypro label.indent-7 > input[type='checkbox'].indent-7, -.path-mod-surveypro label.indent-8 > input[type='checkbox'].indent-8, -.path-mod-surveypro label.indent-9 > input[type='checkbox'].indent-9 { - margin-left: 0; -} -/* End of: classes = indent-n */ +.path-mod-surveypro div.indent-1 > div.felement { + padding-left: 1.5em; +} +.path-mod-surveypro div.indent-2 > div.felement { + padding-left: 3em; +} +.path-mod-surveypro div.indent-3 > div.felement { + padding-left: 4.5em; +} +.path-mod-surveypro div.indent-4 > div.felement { + padding-left: 6em; +} +.path-mod-surveypro div.indent-5 > div.felement { + padding-left: 7.5em; +} +.path-mod-surveypro div.indent-6 > div.felement { + padding-left: 9em; +} +.path-mod-surveypro div.indent-7 > div.felement { + padding-left: 10.5em; +} +.path-mod-surveypro div.indent-8 > div.felement { + padding-left: 12em; +} +.path-mod-surveypro div.indent-9 > div.felement { + padding-left: 13.5em; +} /* Begin of: fix to owful alignment of fielset legends in surveypro -> cover */ .path-mod-surveypro_cover .coverinfolegend { diff --git a/template/attls/lang/en/surveyprotemplate_attls.php b/template/attls/lang/en/surveyprotemplate_attls.php index 032f47b5ddd..cc8abe09472 100644 --- a/template/attls/lang/en/surveyprotemplate_attls.php +++ b/template/attls/lang/en/surveyprotemplate_attls.php @@ -22,16 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'ATTLS (20 item version)'; -$string['privacy:metadata'] = 'The "ATTLS (20 item version)" template plugin does not store any personal data.'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Attitudes Towards Thinking and Learning'; +$string['item_parentvalue_01'] = ''; $string['label_content_01'] = '

The purpose of this questionnaire is to help us understand how well the online delivery of this unit enabled you to learn. Each couple of the 24 statements below asks you to compare your preferred (ideal) and actual experience in this unit. @@ -41,8 +33,11 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Attitudes Towards Thinking and Learning'; +$string['label_leftlabel_01'] = ''; +$string['pluginname'] = 'ATTLS (20 item version)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "ATTLS (20 item version)" template plugin does not store any personal data.'; $string['radiobutton_content_02'] = '

In evaluating what someone says, I focus on the quality of their argument, not on the person who\'s presenting it.

'; $string['radiobutton_content_03'] = '

I like playing devil\'s advocate - arguing the opposite of what someone is saying.

'; @@ -64,11 +59,16 @@ $string['radiobutton_content_19'] = '

I can obtain insight into opinions that differ from mine through empathy.

'; $string['radiobutton_content_20'] = '

When I encounter people whose opinions seem alien to me, I make a deliberate effort to \'extend\' myself into that person, to try to see how they could have those opinions.

'; $string['radiobutton_content_21'] = '

I spend time figuring out what\'s \'wrong\' with things. For example, I\'ll look for something in a literary interpretation that isn\'t argued well enough.

'; +$string['radiobutton_defaultvalue_01'] = ''; +$string['radiobutton_labelother_01'] = ''; +$string['radiobutton_options_01'] = "1::Strongly disagree\n2::Somewhat disagree\n3::Neither agree nor disagree\n4::Somewhat agree\n5::Strongly agree"; +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + -$string['item_parentvalue_01'] = ''; -$string['radiobutton_options_01'] = "1::Strongly disagree\n2::Somewhat disagree\n3::Neither agree nor disagree\n4::Somewhat agree\n5::Strongly agree"; -$string['radiobutton_labelother_01'] = ''; -$string['radiobutton_defaultvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/attls/lang/it/surveyprotemplate_attls.php b/template/attls/lang/it/surveyprotemplate_attls.php index 2537ab883f2..8162abd287e 100644 --- a/template/attls/lang/it/surveyprotemplate_attls.php +++ b/template/attls/lang/it/surveyprotemplate_attls.php @@ -22,15 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'ATTLS (versione con 20 elementi)'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Atteggiamenti nei Confronti del Pensare e dell\'Imparare'; +$string['item_parentvalue_01'] = ''; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a comprendere come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande ti chiede di confrontare l\'esperienza ideale e quella reale in questa unità. @@ -40,9 +33,11 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità online in futuro. Grazie.

'; +$string['label_leftlabel_01'] = ''; +$string['pluginname'] = 'ATTLS (versione con 20 elementi)'; -$string['fieldset_content_01'] = 'Atteggiamenti nei Confronti del Pensare e dell\'Imparare'; - +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_02'] = '

Valutando ciò che le persone dicono, pongo attenzione alla qualità dei suoi argomenti, non alla persona che li presenta.

'; $string['radiobutton_content_03'] = '

Mi piace fare l\'avvocato del diavolo, affermando il contrario di quello che qualcuno sta dicendo.

'; $string['radiobutton_content_04'] = '

Mi piace capire \'da dove vengono\' le altre persone, quali esperienze le hanno portate ad essere quello che sono.

'; @@ -63,11 +58,16 @@ $string['radiobutton_content_19'] = '

Posso arrivare alla comprensione di opinioni diverse dalle mie grazie all\'empatia (immedesimarsi nell\'altra persona).

'; $string['radiobutton_content_20'] = '

Quando incontro persone che sembrano avere opinioni diverse dalle mie, faccio uno sforzo per \'immedesimarmi\' in loro, per cercare di capire come hanno maturato quelle opinioni.

'; $string['radiobutton_content_21'] = '

Passo il tempo a cercare cosa c\'è di sbagliato nelle cose. Per esempio, cercherò qualcosa, in un\'interpretazione letteraria, che non è sufficientemente chiaro.

'; +$string['radiobutton_defaultvalue_01'] = ''; +$string['radiobutton_labelother_01'] = ''; +$string['radiobutton_options_01'] = "1::Fortemente in disaccordo\n2::Un po\' in disaccordo\n3::Né d\'accordo né in disaccordo\n4::Abbastanza d\'accordo\n5::Completamente d\'accordo"; +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + -$string['item_parentvalue_01'] = ''; -$string['radiobutton_options_01'] = "1::Fortemente in disaccordo\n2::Un po\' in disaccordo\n3::Né d\'accordo né in disaccordo\n4::Abbastanza d\'accordo\n5::Completamente d\'accordo"; -$string['radiobutton_labelother_01'] = ''; -$string['radiobutton_defaultvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/attls/template.xml b/template/attls/template.xml index 4884fe35d0c..84250a0b48f 100644 --- a/template/attls/template.xml +++ b/template/attls/template.xml @@ -1,43 +1,43 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 0 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + - 0 - 1 - 0 - - radiobutton_content_02 1 1 0 0 attls_radiobutton_01 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -46,19 +46,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 attls_radiobutton_02 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -67,19 +67,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 attls_radiobutton_03 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -88,19 +88,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 attls_radiobutton_04 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -109,19 +109,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 attls_radiobutton_05 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -130,19 +130,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 attls_radiobutton_06 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -151,19 +151,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 attls_radiobutton_07 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -172,19 +172,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 attls_radiobutton_08 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -193,19 +193,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 attls_radiobutton_09 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -214,19 +214,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 attls_radiobutton_10 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -235,19 +235,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 attls_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -256,19 +256,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 attls_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -277,19 +277,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 attls_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -298,19 +298,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 attls_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -319,19 +319,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 attls_radiobutton_15 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -340,19 +340,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 attls_radiobutton_16 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -361,19 +361,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 attls_radiobutton_17 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -382,19 +382,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 attls_radiobutton_18 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -403,19 +403,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 attls_radiobutton_19 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -424,19 +424,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 attls_radiobutton_20 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -445,4 +445,4 @@ 1 - \ No newline at end of file + diff --git a/template/attls/version.php b/template/attls/version.php index ead574345d2..69de17896ec 100644 --- a/template/attls/version.php +++ b/template/attls/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_attls'; // Full name of the plugin (used for diagnostics). diff --git a/template/collesactual/lang/en/surveyprotemplate_collesactual.php b/template/collesactual/lang/en/surveyprotemplate_collesactual.php index e208d689df8..2acc733667a 100644 --- a/template/collesactual/lang/en/surveyprotemplate_collesactual.php +++ b/template/collesactual/lang/en/surveyprotemplate_collesactual.php @@ -22,20 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Actual)'; -$string['privacy:metadata'] = 'The "COLLES (Actual)" template plugin does not store any personal data.'; - -$string['summary'] = 'Summary'; -$string['scales'] = 'Scales'; $string['areaidxs'] = 'Questions'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Relevance'; +$string['fieldset_content_02'] = 'Reflective thinking'; $string['label_content_01'] = '

The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. Each one of the 24 statements below asks about your experience in this unit. @@ -45,17 +34,28 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Relevance'; - $string['label_content_02'] = '

In this online unit...

'; +$string['pluginname'] = 'COLLES (Actual)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "COLLES (Actual)" template plugin does not store any personal data.'; $string['radiobutton_content_03'] = '

my learning focuses on issues that interest me.

'; $string['radiobutton_content_04'] = '

what I learn is important for my professional practice.

'; $string['radiobutton_content_05'] = '

I learn how to improve my professional practice.

'; $string['radiobutton_content_06'] = '

what I learn connects well with my professional practice.

'; +$string['scales'] = 'Scales'; +$string['summary'] = 'Summary'; + +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + + -$string['fieldset_content_02'] = 'Reflective thinking'; // $string['label_content_02'] = '

In this online unit...

'; diff --git a/template/collesactual/lang/it/surveyprotemplate_collesactual.php b/template/collesactual/lang/it/surveyprotemplate_collesactual.php index e2b15115e59..6bb3db49086 100644 --- a/template/collesactual/lang/it/surveyprotemplate_collesactual.php +++ b/template/collesactual/lang/it/surveyprotemplate_collesactual.php @@ -22,18 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Actual)'; -$string['summary'] = 'Riepilogo'; -$string['scales'] = 'Valutazioni'; $string['areaidxs'] = 'Aree'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Pertinenza'; +$string['fieldset_content_02'] = 'Senso critico'; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande riguarda la tua esperienza in questa unità. @@ -43,17 +34,26 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità. Grazie.

'; - -$string['fieldset_content_01'] = 'Pertinenza'; - $string['label_content_02'] = '

In questa unità online...

'; - +$string['pluginname'] = 'COLLES (Actual)'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_03'] = '

il mio apprendimento si concentra sulle cose che mi interessano.

'; $string['radiobutton_content_04'] = '

quello che imparo è importante per la mia pratica professionale.

'; $string['radiobutton_content_05'] = '

imparo come migliorare la mia pratica professionale.

'; $string['radiobutton_content_06'] = '

quello che imparo si collega bene con la mia pratica professionale.

'; +$string['scales'] = 'Valutazioni'; +$string['summary'] = 'Riepilogo'; + +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + + -$string['fieldset_content_02'] = 'Senso critico'; // $string['label_content_02'] = '

In questa unità online...

'; diff --git a/template/collesactual/template.xml b/template/collesactual/template.xml index 63eb32326ca..f9ccd1515d9 100644 --- a/template/collesactual/template.xml +++ b/template/collesactual/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 ca_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 ca_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 ca_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 ca_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,44 +123,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 ca_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -169,19 +169,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 ca_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -190,19 +190,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 ca_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -211,19 +211,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 ca_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -232,44 +232,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 ca_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -278,19 +278,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 ca_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -299,19 +299,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 ca_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -320,19 +320,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 ca_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -341,44 +341,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 ca_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -387,19 +387,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 ca_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -408,19 +408,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 ca_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -429,19 +429,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 ca_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -450,44 +450,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 ca_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -496,19 +496,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 ca_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -517,19 +517,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 ca_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -538,19 +538,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 ca_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -559,44 +559,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 ca_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -605,19 +605,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 ca_radiobutton_62 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -626,19 +626,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 ca_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -647,19 +647,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 ca_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -668,19 +668,19 @@ 1 - + - 0 - 1 - 0 - - select_content_27 1 1 0 0 ca_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -688,13 +688,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_28 1 0 @@ -702,12 +697,17 @@ 0 0 ca_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collesactual/tests/behat/graphs.feature b/template/collesactual/tests/behat/graphs.feature index f873aedcaf9..dd07078d399 100644 --- a/template/collesactual/tests/behat/graphs.feature +++ b/template/collesactual/tests/behat/graphs.feature @@ -41,32 +41,32 @@ Feature: Apply a COLLES (actual) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_3 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_0 | 1 | - | id_surveypro_field_radiobutton_19_1 | 1 | - | id_surveypro_field_radiobutton_22_2 | 1 | - | id_surveypro_field_radiobutton_23_3 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_0 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_4 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_3 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_0 | 1 | + | id_field_radiobutton_19_1 | 1 | + | id_field_radiobutton_22_2 | 1 | + | id_field_radiobutton_23_3 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_0 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_4 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collesactual/tests/behat/reportswithanswers.feature b/template/collesactual/tests/behat/reportswithanswers.feature index 971bd2f8b0c..73e675901cb 100644 --- a/template/collesactual/tests/behat/reportswithanswers.feature +++ b/template/collesactual/tests/behat/reportswithanswers.feature @@ -56,32 +56,32 @@ Feature: Test colles report for courses divided into groups having answers # student11 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_1 | 1 | - | id_surveypro_field_radiobutton_5_0 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_0 | 1 | - | id_surveypro_field_radiobutton_13_1 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_4 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_4 | 1 | - | id_surveypro_field_radiobutton_28_3 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_1 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_2 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_1 | 1 | + | id_field_radiobutton_5_0 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_0 | 1 | + | id_field_radiobutton_13_1 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_4 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_4 | 1 | + | id_field_radiobutton_28_3 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_1 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_2 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out @@ -93,32 +93,32 @@ Feature: Test colles report for courses divided into groups having answers # student12 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_2 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_3 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_3 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_0 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_1 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_4 | 1 | - | id_surveypro_field_radiobutton_30_2 | 1 | - | id_surveypro_field_radiobutton_31_1 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_3 | 1 | - | id_surveypro_field_radiobutton_37_2 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_2 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_3 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_3 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_0 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_1 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_4 | 1 | + | id_field_radiobutton_30_2 | 1 | + | id_field_radiobutton_31_1 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_3 | 1 | + | id_field_radiobutton_37_2 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out @@ -130,32 +130,32 @@ Feature: Test colles report for courses divided into groups having answers # student21 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_4 | 1 | - | id_surveypro_field_radiobutton_5_2 | 1 | - | id_surveypro_field_radiobutton_6_1 | 1 | - | id_surveypro_field_radiobutton_7_0 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_4 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_0 | 1 | - | id_surveypro_field_radiobutton_16_2 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_1 | 1 | - | id_surveypro_field_radiobutton_19_4 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_0 | 1 | - | id_surveypro_field_radiobutton_24_3 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_28_4 | 1 | - | id_surveypro_field_radiobutton_29_1 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_4 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_4 | 1 | + | id_field_radiobutton_5_2 | 1 | + | id_field_radiobutton_6_1 | 1 | + | id_field_radiobutton_7_0 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_4 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_0 | 1 | + | id_field_radiobutton_16_2 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_1 | 1 | + | id_field_radiobutton_19_4 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_0 | 1 | + | id_field_radiobutton_24_3 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_28_4 | 1 | + | id_field_radiobutton_29_1 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_4 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out diff --git a/template/collesactual/tests/behat/reportswithoutanswers.feature b/template/collesactual/tests/behat/reportswithoutanswers.feature index 9dcaa44c18d..403b901ae61 100644 --- a/template/collesactual/tests/behat/reportswithoutanswers.feature +++ b/template/collesactual/tests/behat/reportswithoutanswers.feature @@ -37,6 +37,7 @@ Feature: Test colles report for courses divided into groups not having answers | surveypro | Verify reports | Verify reports | Course grouped | When I am on the "Verify reports" "Activity editing" page logged in as teacher1 + And I expand all fieldsets And I set the following fields to these values: | Group mode | Visible groups | And I press "Save and display" @@ -53,32 +54,32 @@ Feature: Test colles report for courses divided into groups not having answers # student11 submits his response And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_1 | 1 | - | id_surveypro_field_radiobutton_5_0 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_4 | 1 | - | id_surveypro_field_radiobutton_10_3 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_0 | 1 | - | id_surveypro_field_radiobutton_13_1 | 1 | - | id_surveypro_field_radiobutton_16_1 | 1 | - | id_surveypro_field_radiobutton_17_2 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_22_3 | 1 | - | id_surveypro_field_radiobutton_23_4 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_4 | 1 | - | id_surveypro_field_radiobutton_28_3 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_1 | 1 | - | id_surveypro_field_radiobutton_31_0 | 1 | - | id_surveypro_field_radiobutton_34_2 | 1 | - | id_surveypro_field_radiobutton_35_4 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | No, please. | + | id_field_radiobutton_4_1 | 1 | + | id_field_radiobutton_5_0 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_4 | 1 | + | id_field_radiobutton_10_3 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_0 | 1 | + | id_field_radiobutton_13_1 | 1 | + | id_field_radiobutton_16_1 | 1 | + | id_field_radiobutton_17_2 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_22_3 | 1 | + | id_field_radiobutton_23_4 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_4 | 1 | + | id_field_radiobutton_28_3 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_1 | 1 | + | id_field_radiobutton_31_0 | 1 | + | id_field_radiobutton_34_2 | 1 | + | id_field_radiobutton_35_4 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | No, please. | And I press "Submit" And I log out diff --git a/template/collesactual/version.php b/template/collesactual/version.php index 5eb5c47c6ba..5474b76bd11 100644 --- a/template/collesactual/version.php +++ b/template/collesactual/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collesactual'; // Full name of the plugin (used for diagnostics). diff --git a/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php b/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php index c947e90619c..6f4f71c1ad0 100644 --- a/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php +++ b/template/collesactualpreferred/lang/en/surveyprotemplate_collesactualpreferred.php @@ -22,19 +22,19 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['areaidxs'] = 'Questions'; $string['pluginname'] = 'COLLES (Preferred and Actual)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; $string['privacy:metadata'] = 'The "COLLES (Preferred and Actual)" template plugin does not store any personal data.'; -$string['summary'] = 'Summary'; $string['scales'] = 'Scales'; -$string['areaidxs'] = 'Questions'; +$string['summary'] = 'Summary'; +$string['useradio'] = 'Radio buttons'; $string['useritem'] = 'Style of the choice elements'; $string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; $string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; // Label. $string['label_content_01'] = '

The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. diff --git a/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php b/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php index aaf5fb21d5b..83e8640a48b 100644 --- a/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php +++ b/template/collesactualpreferred/lang/it/surveyprotemplate_collesactualpreferred.php @@ -22,17 +22,17 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['areaidxs'] = 'Aree'; $string['pluginname'] = 'COLLES (Ideale e Reale)'; -$string['summary'] = 'Riepilogo'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['scales'] = 'Valutazioni'; -$string['areaidxs'] = 'Aree'; +$string['summary'] = 'Riepilogo'; +$string['useradio'] = 'Bottoni radio'; $string['useritem'] = 'Tipo di selettore'; $string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; $string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; // Label. $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. diff --git a/template/collesactualpreferred/template.xml b/template/collesactualpreferred/template.xml index 7063150e63c..245d7893417 100644 --- a/template/collesactualpreferred/template.xml +++ b/template/collesactualpreferred/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 cap_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 cap_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 cap_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 cap_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,19 +123,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 cap_radiobutton_15 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -144,19 +144,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 cap_radiobutton_16 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -165,19 +165,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 cap_radiobutton_17 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -186,19 +186,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 cap_radiobutton_18 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -207,44 +207,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 cap_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -253,19 +253,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 cap_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -274,19 +274,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 cap_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -295,19 +295,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 cap_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -316,19 +316,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 cap_radiobutton_25 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -337,19 +337,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 cap_radiobutton_26 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -358,19 +358,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 cap_radiobutton_27 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -379,19 +379,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 cap_radiobutton_28 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -400,44 +400,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 cap_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -446,19 +446,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 cap_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -467,19 +467,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 cap_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -488,19 +488,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 cap_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -509,19 +509,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 cap_radiobutton_35 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -530,19 +530,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 cap_radiobutton_36 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -551,20 +551,20 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 cap_radiobutton_37 - radiobutton_options_01 + 0 + 1 + 0 + + + radiobutton_options_01 radiobutton_labelother_01 2 radiobutton_defaultvalue_01 @@ -572,19 +572,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 cap_radiobutton_38 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -593,44 +593,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_27 1 1 0 0 cap_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -639,19 +639,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_28 1 1 0 0 cap_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -660,19 +660,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_29 1 1 0 0 cap_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -681,19 +681,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_30 1 1 0 0 cap_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -702,19 +702,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_31 1 1 0 0 cap_radiobutton_45 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -723,19 +723,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_32 1 1 0 0 cap_radiobutton_46 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -744,19 +744,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_33 1 1 0 0 cap_radiobutton_47 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -765,19 +765,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_34 1 1 0 0 cap_radiobutton_48 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -786,44 +786,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_35 1 1 0 0 cap_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -832,19 +832,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_36 1 1 0 0 cap_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -853,19 +853,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_37 1 1 0 0 cap_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -874,19 +874,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_38 1 1 0 0 cap_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -895,19 +895,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_39 1 1 0 0 cap_radiobutton_55 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -916,19 +916,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_40 1 1 0 0 cap_radiobutton_56 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -937,19 +937,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_41 1 1 0 0 cap_radiobutton_57 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -958,19 +958,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_42 1 1 0 0 cap_radiobutton_58 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -979,44 +979,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_43 1 1 0 0 cap_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1025,19 +1025,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_44 1 1 0 0 cap_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1046,19 +1046,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_45 1 1 0 0 cap_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1067,19 +1067,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_46 1 1 0 0 cap_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1088,19 +1088,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_47 1 1 0 0 cap_radiobutton_65 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1109,19 +1109,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_48 1 1 0 0 cap_radiobutton_66 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1130,19 +1130,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_49 1 1 0 0 cap_radiobutton_67 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1151,19 +1151,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_50 1 1 0 0 cap_radiobutton_68 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -1172,19 +1172,19 @@ 1 - + - 0 - 1 - 0 - - select_content_51 1 1 0 0 cap_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -1192,13 +1192,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_52 1 0 @@ -1206,12 +1201,17 @@ 0 0 cap_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collesactualpreferred/tests/behat/graphs.feature b/template/collesactualpreferred/tests/behat/graphs.feature index 80c7ee2191a..0ddefded04f 100644 --- a/template/collesactualpreferred/tests/behat/graphs.feature +++ b/template/collesactualpreferred/tests/behat/graphs.feature @@ -41,62 +41,62 @@ Feature: Apply a COLLES (actual and preferred) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_8_4 | 1 | - | id_surveypro_field_radiobutton_9_0 | 1 | - | id_surveypro_field_radiobutton_10_1 | 1 | - | id_surveypro_field_radiobutton_11_2 | 1 | - - | id_surveypro_field_radiobutton_14_3 | 1 | - | id_surveypro_field_radiobutton_15_4 | 1 | - | id_surveypro_field_radiobutton_16_0 | 1 | - | id_surveypro_field_radiobutton_17_1 | 1 | - | id_surveypro_field_radiobutton_18_2 | 1 | - | id_surveypro_field_radiobutton_19_3 | 1 | - | id_surveypro_field_radiobutton_20_4 | 1 | - | id_surveypro_field_radiobutton_21_0 | 1 | - - | id_surveypro_field_radiobutton_24_1 | 1 | - | id_surveypro_field_radiobutton_25_2 | 1 | - | id_surveypro_field_radiobutton_26_3 | 1 | - | id_surveypro_field_radiobutton_27_4 | 1 | - | id_surveypro_field_radiobutton_28_0 | 1 | - | id_surveypro_field_radiobutton_29_1 | 1 | - | id_surveypro_field_radiobutton_30_2 | 1 | - | id_surveypro_field_radiobutton_31_3 | 1 | - - | id_surveypro_field_radiobutton_34_4 | 1 | - | id_surveypro_field_radiobutton_35_0 | 1 | - | id_surveypro_field_radiobutton_36_1 | 1 | - | id_surveypro_field_radiobutton_37_2 | 1 | - | id_surveypro_field_radiobutton_38_3 | 1 | - | id_surveypro_field_radiobutton_39_4 | 1 | - | id_surveypro_field_radiobutton_40_0 | 1 | - | id_surveypro_field_radiobutton_41_1 | 1 | - - | id_surveypro_field_radiobutton_44_2 | 1 | - | id_surveypro_field_radiobutton_45_3 | 1 | - | id_surveypro_field_radiobutton_46_4 | 1 | - | id_surveypro_field_radiobutton_47_0 | 1 | - | id_surveypro_field_radiobutton_48_1 | 1 | - | id_surveypro_field_radiobutton_49_2 | 1 | - | id_surveypro_field_radiobutton_50_3 | 1 | - | id_surveypro_field_radiobutton_51_4 | 1 | - - | id_surveypro_field_radiobutton_54_0 | 1 | - | id_surveypro_field_radiobutton_55_1 | 1 | - | id_surveypro_field_radiobutton_56_2 | 1 | - | id_surveypro_field_radiobutton_57_3 | 1 | - | id_surveypro_field_radiobutton_58_4 | 1 | - | id_surveypro_field_radiobutton_59_0 | 1 | - | id_surveypro_field_radiobutton_60_1 | 1 | - | id_surveypro_field_radiobutton_61_2 | 1 | - - | id_surveypro_field_select_62 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_8_4 | 1 | + | id_field_radiobutton_9_0 | 1 | + | id_field_radiobutton_10_1 | 1 | + | id_field_radiobutton_11_2 | 1 | + + | id_field_radiobutton_14_3 | 1 | + | id_field_radiobutton_15_4 | 1 | + | id_field_radiobutton_16_0 | 1 | + | id_field_radiobutton_17_1 | 1 | + | id_field_radiobutton_18_2 | 1 | + | id_field_radiobutton_19_3 | 1 | + | id_field_radiobutton_20_4 | 1 | + | id_field_radiobutton_21_0 | 1 | + + | id_field_radiobutton_24_1 | 1 | + | id_field_radiobutton_25_2 | 1 | + | id_field_radiobutton_26_3 | 1 | + | id_field_radiobutton_27_4 | 1 | + | id_field_radiobutton_28_0 | 1 | + | id_field_radiobutton_29_1 | 1 | + | id_field_radiobutton_30_2 | 1 | + | id_field_radiobutton_31_3 | 1 | + + | id_field_radiobutton_34_4 | 1 | + | id_field_radiobutton_35_0 | 1 | + | id_field_radiobutton_36_1 | 1 | + | id_field_radiobutton_37_2 | 1 | + | id_field_radiobutton_38_3 | 1 | + | id_field_radiobutton_39_4 | 1 | + | id_field_radiobutton_40_0 | 1 | + | id_field_radiobutton_41_1 | 1 | + + | id_field_radiobutton_44_2 | 1 | + | id_field_radiobutton_45_3 | 1 | + | id_field_radiobutton_46_4 | 1 | + | id_field_radiobutton_47_0 | 1 | + | id_field_radiobutton_48_1 | 1 | + | id_field_radiobutton_49_2 | 1 | + | id_field_radiobutton_50_3 | 1 | + | id_field_radiobutton_51_4 | 1 | + + | id_field_radiobutton_54_0 | 1 | + | id_field_radiobutton_55_1 | 1 | + | id_field_radiobutton_56_2 | 1 | + | id_field_radiobutton_57_3 | 1 | + | id_field_radiobutton_58_4 | 1 | + | id_field_radiobutton_59_0 | 1 | + | id_field_radiobutton_60_1 | 1 | + | id_field_radiobutton_61_2 | 1 | + + | id_field_select_62 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collesactualpreferred/version.php b/template/collesactualpreferred/version.php index df55ca3a61f..04ea0d9ab2a 100644 --- a/template/collesactualpreferred/version.php +++ b/template/collesactualpreferred/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collesactualpreferred'; // Full name of the plugin (used for diagnostics). diff --git a/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php b/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php index 70b16f83000..caf334b2b0d 100644 --- a/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php +++ b/template/collespreferred/lang/en/surveyprotemplate_collespreferred.php @@ -22,20 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Preferred)'; -$string['privacy:metadata'] = 'The "COLLES (Preferred)" template plugin does not store any personal data.'; - -$string['summary'] = 'Summary'; -$string['scales'] = 'Scales'; $string['areaidxs'] = 'Questions'; - -$string['useritem'] = 'Style of the choice elements'; -$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; -$string['useradio'] = 'Radio buttons'; -$string['useselect'] = 'Use drop down menus'; -$string['position'] = 'Position of attls elements question'; -$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; - +$string['fieldset_content_01'] = 'Relevance'; +$string['fieldset_content_02'] = 'Reflective thinking'; $string['label_content_01'] = '

The purpose of this survey is to help us understand what you value in an online learning experience. Each one of the 24 statements below asks about your preferred (ideal) experience in this unit. @@ -45,17 +34,28 @@ Your carefully considered responses will help us improve the way this unit is presented online in the future. Thanks very much.

'; - -$string['fieldset_content_01'] = 'Relevance'; - $string['label_content_02'] = '

In this online unit...

'; +$string['pluginname'] = 'COLLES (Preferred)'; +$string['position'] = 'Position of attls elements question'; +$string['position_desc'] = 'This option let you choose the position of the question respect to the user interface to provide the answer.
Changes will take effect with new surveypro'; +$string['privacy:metadata'] = 'The "COLLES (Preferred)" template plugin does not store any personal data.'; $string['radiobutton_content_03'] = '

my learning focuses on issues that interest me.

'; $string['radiobutton_content_04'] = '

what I learn is important for my professional practice.

'; $string['radiobutton_content_05'] = '

I learn how to improve my professional practice.

'; $string['radiobutton_content_06'] = '

what I learn connects well with my professional practice.

'; +$string['scales'] = 'Scales'; +$string['summary'] = 'Summary'; + +$string['useradio'] = 'Radio buttons'; +$string['useritem'] = 'Style of the choice elements'; +$string['useritem_desc'] = 'This option let you choose the style of the elemets for the choices of the survey. "Radio buttons" is the standard, "Drop down menu" is better for not huge monitors.
Changes will take effect with new surveypro'; +$string['useselect'] = 'Use drop down menus'; + + + + -$string['fieldset_content_02'] = 'Reflective thinking'; // $string['label_content_02'] = '

In this online unit...

'; diff --git a/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php b/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php index ab3a71a8568..aabccfa4fa4 100644 --- a/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php +++ b/template/collespreferred/lang/it/surveyprotemplate_collespreferred.php @@ -22,18 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'COLLES (Ideale)'; -$string['summary'] = 'Riepilogo'; -$string['scales'] = 'Valutazioni'; $string['areaidxs'] = 'Aree'; - -$string['useritem'] = 'Tipo di selettore'; -$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; -$string['useradio'] = 'Bottoni radio'; -$string['useselect'] = 'Menu a tendina'; -$string['position'] = 'Posizione delle domande'; -$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; - +$string['fieldset_content_01'] = 'Pertinenza'; +$string['fieldset_content_02'] = 'Senso critico'; $string['label_content_01'] = '

L\'obiettivo di questo sondaggio è di aiutarci a capire come lo svolgimento online di questa unità ti sia stato utile nell\'apprendimento. Ciascuna delle seguenti 24 domande riguarda l\'esperienza ideale in questa unità. @@ -43,17 +34,26 @@ Le tue risposte saranno considerate con attenzione e ci aiuteranno a migliorare le caratteristiche di questa unità online in futuro. Grazie.

'; - -$string['fieldset_content_01'] = 'Pertinenza'; - $string['label_content_02'] = '

In questa unità online...

'; - +$string['pluginname'] = 'COLLES (Ideale)'; +$string['position'] = 'Posizione delle domande'; +$string['position_desc'] = 'Questa opzione consente di scegliere la posizione del testo delle domande nell\'elemento.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; $string['radiobutton_content_03'] = '

il mio apprendimento si concentra sulle cose che mi interessano.

'; $string['radiobutton_content_04'] = '

quello che imparo è importante per la mia pratica professionale.

'; $string['radiobutton_content_05'] = '

imparo come migliorare la mia pratica professionale.

'; $string['radiobutton_content_06'] = '

quello che imparo si collega bene con la mia pratica professionale.

'; +$string['scales'] = 'Valutazioni'; +$string['summary'] = 'Riepilogo'; + +$string['useradio'] = 'Bottoni radio'; +$string['useritem'] = 'Tipo di selettore'; +$string['useritem_desc'] = 'Questa opzione consente di scegliere il tipo di selettore per rispondere al sondaggio. "Bottoni radio" è lo standard, "Menu a tendina" è consigliato per i monitor di modeste dimensioni.
Le modifiche avranno effetto sui prossimi nuovi somdaggi.'; +$string['useselect'] = 'Menu a tendina'; + + + + -$string['fieldset_content_02'] = 'Senso critico'; // $string['label_content_02'] = '

In questa unità online...

'; diff --git a/template/collespreferred/template.xml b/template/collespreferred/template.xml index b7da9be12d9..89ffbd7dc51 100644 --- a/template/collespreferred/template.xml +++ b/template/collespreferred/template.xml @@ -1,57 +1,57 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 1 label_leftlabel_01 - + + fieldset_content_01 0 1 0 - fieldset_content_01 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_03 1 1 0 0 cp_radiobutton_11 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -60,19 +60,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_04 1 1 0 0 cp_radiobutton_12 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -81,19 +81,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_05 1 1 0 0 cp_radiobutton_13 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -102,19 +102,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_06 1 1 0 0 cp_radiobutton_14 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -123,44 +123,44 @@ 1 - + + fieldset_content_02 0 1 0 - fieldset_content_02 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_07 1 1 0 0 cp_radiobutton_21 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -169,19 +169,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_08 1 1 0 0 cp_radiobutton_22 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -190,19 +190,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_09 1 1 0 0 cp_radiobutton_23 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -211,19 +211,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_10 1 1 0 0 cp_radiobutton_24 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -232,44 +232,44 @@ 1 - + + fieldset_content_03 0 1 0 - fieldset_content_03 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_11 1 1 0 0 cp_radiobutton_31 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -278,19 +278,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_12 1 1 0 0 cp_radiobutton_32 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -299,19 +299,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_13 1 1 0 0 cp_radiobutton_33 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -320,19 +320,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_14 1 1 0 0 cp_radiobutton_34 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -341,44 +341,44 @@ 1 - + + fieldset_content_04 0 1 0 - fieldset_content_04 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_15 1 1 0 0 cp_radiobutton_41 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -387,19 +387,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_16 1 1 0 0 cp_radiobutton_42 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -408,19 +408,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_17 1 1 0 0 cp_radiobutton_43 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -429,19 +429,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_18 1 1 0 0 cp_radiobutton_44 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -450,44 +450,44 @@ 1 - + + fieldset_content_05 0 1 0 - fieldset_content_05 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_19 1 1 0 0 cp_radiobutton_51 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -496,19 +496,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_20 1 1 0 0 cp_radiobutton_52 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -517,19 +517,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_21 1 1 0 0 cp_radiobutton_53 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -538,19 +538,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_22 1 1 0 0 cp_radiobutton_54 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -559,44 +559,44 @@ 1 - + + fieldset_content_06 0 1 0 - fieldset_content_06 2 - + + label_content_02 + 1 + 0 0 1 0 - label_content_02 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - radiobutton_content_23 1 1 0 0 cp_radiobutton_61 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -605,19 +605,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_24 1 1 0 0 cp_radiobutton_62 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -626,19 +626,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_25 1 1 0 0 cp_radiobutton_63 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -647,19 +647,19 @@ 1 - + - 0 - 1 - 0 - - radiobutton_content_26 1 1 0 0 cp_radiobutton_64 + 0 + 1 + 0 + + radiobutton_options_01 radiobutton_labelother_01 2 @@ -668,19 +668,19 @@ 1 - + - 0 - 1 - 0 - - select_content_27 1 1 0 0 cp_select + 0 + 1 + 0 + + select_options_01 select_labelother_01 2 @@ -688,13 +688,8 @@ 0 - + - 0 - 1 - 0 - - textarea_content_28 1 0 @@ -702,12 +697,17 @@ 0 0 cp_textarea + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - \ No newline at end of file + diff --git a/template/collespreferred/tests/behat/graphs.feature b/template/collespreferred/tests/behat/graphs.feature index 447dc5f398f..fdf4cb7c74b 100644 --- a/template/collespreferred/tests/behat/graphs.feature +++ b/template/collespreferred/tests/behat/graphs.feature @@ -41,32 +41,32 @@ Feature: Apply a COLLES (preferred) mastertemplate to test graphs # student1 submits his first response And I expand all fieldsets And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_0 | 1 | - | id_surveypro_field_radiobutton_5_1 | 1 | - | id_surveypro_field_radiobutton_6_2 | 1 | - | id_surveypro_field_radiobutton_7_3 | 1 | - | id_surveypro_field_radiobutton_10_4 | 1 | - | id_surveypro_field_radiobutton_11_0 | 1 | - | id_surveypro_field_radiobutton_12_1 | 1 | - | id_surveypro_field_radiobutton_13_2 | 1 | - | id_surveypro_field_radiobutton_16_3 | 1 | - | id_surveypro_field_radiobutton_17_4 | 1 | - | id_surveypro_field_radiobutton_18_0 | 1 | - | id_surveypro_field_radiobutton_19_1 | 1 | - | id_surveypro_field_radiobutton_22_2 | 1 | - | id_surveypro_field_radiobutton_23_3 | 1 | - | id_surveypro_field_radiobutton_24_4 | 1 | - | id_surveypro_field_radiobutton_25_0 | 1 | - | id_surveypro_field_radiobutton_28_1 | 1 | - | id_surveypro_field_radiobutton_29_2 | 1 | - | id_surveypro_field_radiobutton_30_3 | 1 | - | id_surveypro_field_radiobutton_31_4 | 1 | - | id_surveypro_field_radiobutton_34_0 | 1 | - | id_surveypro_field_radiobutton_35_1 | 1 | - | id_surveypro_field_radiobutton_36_2 | 1 | - | id_surveypro_field_radiobutton_37_3 | 1 | - | id_surveypro_field_select_38 | 2-3 min | - | Do you have any other comments? | Am I sexy? | + | id_field_radiobutton_4_0 | 1 | + | id_field_radiobutton_5_1 | 1 | + | id_field_radiobutton_6_2 | 1 | + | id_field_radiobutton_7_3 | 1 | + | id_field_radiobutton_10_4 | 1 | + | id_field_radiobutton_11_0 | 1 | + | id_field_radiobutton_12_1 | 1 | + | id_field_radiobutton_13_2 | 1 | + | id_field_radiobutton_16_3 | 1 | + | id_field_radiobutton_17_4 | 1 | + | id_field_radiobutton_18_0 | 1 | + | id_field_radiobutton_19_1 | 1 | + | id_field_radiobutton_22_2 | 1 | + | id_field_radiobutton_23_3 | 1 | + | id_field_radiobutton_24_4 | 1 | + | id_field_radiobutton_25_0 | 1 | + | id_field_radiobutton_28_1 | 1 | + | id_field_radiobutton_29_2 | 1 | + | id_field_radiobutton_30_3 | 1 | + | id_field_radiobutton_31_4 | 1 | + | id_field_radiobutton_34_0 | 1 | + | id_field_radiobutton_35_1 | 1 | + | id_field_radiobutton_36_2 | 1 | + | id_field_radiobutton_37_3 | 1 | + | id_field_select_38 | 2-3 min | + | Do you have any other comments? | Am I sexy? | And I press "Submit" And I am on the "Run COLLES report" "mod_surveypro > Reports from secondary navigation" page diff --git a/template/collespreferred/version.php b/template/collespreferred/version.php index d4423b3ff29..51ebe298a75 100644 --- a/template/collespreferred/version.php +++ b/template/collespreferred/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_collespreferred'; // Full name of the plugin (used for diagnostics). diff --git a/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php b/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php index 4bffc773bb5..73b5ff17d4d 100644 --- a/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php +++ b/template/criticalincidents/lang/en/surveyprotemplate_criticalincidents.php @@ -22,10 +22,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['item_parentvalue_01'] = ''; +$string['label_content_01'] = '

While thinking about recent events in this class, answer the questions below.

'; +$string['label_leftlabel_01'] = ''; $string['pluginname'] = 'Critical Incidents'; $string['privacy:metadata'] = 'The "Critical Incidents" template plugin does not store any personal data.'; -$string['label_content_01'] = '

While thinking about recent events in this class, answer the questions below.

'; $string['textarea_content_02'] = '

At what moment in class were you most engaged as a learner?

'; $string['textarea_content_03'] = '

At what moment in class were you most distanced as a learner?

'; @@ -33,6 +35,4 @@ $string['textarea_content_05'] = '

What action from anyone in the forums did you find most puzzling or confusing?

'; $string['textarea_content_06'] = '

What event surprised you most?

'; -$string['item_parentvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php b/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php index 4575e444950..81079b0e05f 100644 --- a/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php +++ b/template/criticalincidents/lang/it/surveyprotemplate_criticalincidents.php @@ -22,9 +22,11 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['item_parentvalue_01'] = ''; +$string['label_content_01'] = '

Rispondi alle seguenti domande pensando alle attività svolte recentemente in classe.

'; +$string['label_leftlabel_01'] = ''; $string['pluginname'] = 'Incidenti critici'; -$string['label_content_01'] = '

Rispondi alle seguenti domande pensando alle attività svolte recentemente in classe.

'; $string['textarea_content_02'] = '

In classe in quale momento sei più partecipe come studente?

'; $string['textarea_content_03'] = '

In classe in quale momento sei meno partecipe come studente?

'; @@ -32,6 +34,4 @@ $string['textarea_content_05'] = '

Quale azione nei forum da parte degli altri partecipanti trovi disorientante e confusionaria?

'; $string['textarea_content_06'] = '

Quale evento ti ha sorpreso di più?

'; -$string['item_parentvalue_01'] = ''; -$string['label_leftlabel_01'] = ''; diff --git a/template/criticalincidents/template.xml b/template/criticalincidents/template.xml index 14508a4c4ad..301cfa72675 100644 --- a/template/criticalincidents/template.xml +++ b/template/criticalincidents/template.xml @@ -1,26 +1,21 @@ - + + label_content_01 + 1 + 0 0 1 0 - label_content_01 - 1 - 0 0 label_leftlabel_01 - + - 0 - 1 - 0 - - textarea_content_02 1 1 @@ -28,21 +23,21 @@ 0 0 ci_textarea_01 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_03 1 1 @@ -50,21 +45,21 @@ 0 0 ci_textarea_02 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_04 1 1 @@ -72,21 +67,21 @@ 0 0 ci_textarea_03 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_05 1 1 @@ -94,21 +89,21 @@ 0 0 ci_textarea_04 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 - + - 0 - 1 - 0 - - textarea_content_06 1 1 @@ -116,10 +111,15 @@ 0 0 ci_textarea_05 + 0 + 1 + 0 + + + 0 0 12 60 - 0 0 0 diff --git a/template/criticalincidents/version.php b/template/criticalincidents/version.php index 6312d59f4ba..ad2cc024b19 100644 --- a/template/criticalincidents/version.php +++ b/template/criticalincidents/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017112201; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 2015111600; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_criticalincidents'; // Full name of the plugin (used for diagnostics). diff --git a/template/flags/classes/privacy/provider.php b/template/flags/classes/privacy/provider.php new file mode 100644 index 00000000000..26442aac8b1 --- /dev/null +++ b/template/flags/classes/privacy/provider.php @@ -0,0 +1,44 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_flags\privacy; + +/** + * Privacy Subsystem for template_flags implementing null_provider. + * + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/template/flags/classes/template.php b/template/flags/classes/template.php new file mode 100644 index 00000000000..5127041720c --- /dev/null +++ b/template/flags/classes/template.php @@ -0,0 +1,47 @@ +. + +/** + * Surveypro class to manage flags template + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_flags; + +/** + * The class to manage flags template + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template { + + /** + * Apply template settings. + * + * @param string $tablename + * @param object $record + * @param object $config + * @return [$tablename, $record] + */ + public function apply_template_settings($tablename, $record, $config) { + return [$tablename, $record]; + } +} diff --git a/template/flags/lang/en/surveyprotemplate_flags.php b/template/flags/lang/en/surveyprotemplate_flags.php new file mode 100644 index 00000000000..3590e227f45 --- /dev/null +++ b/template/flags/lang/en/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

Do you recognize this flag?

+

ENFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEhUSExIWFRAXFhcVFRUVFRcVFRYVFRUWFhUVFhUYHSggGB0lHRUVITEhJSktLi4uFx8zODMsNygtLisBCgoKDg0OGhAQGy0lIB0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAJ8BPgMBEQACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAAGAgMEBQcBAAj/xABHEAABAgMDBwcICAYCAgMAAAABAgMABBEFITEGEhNBUWFxByJCUoGRklNigpOhsbLRIzJDcnPB0tMUJGODoqMVVDPxFhcl/8QAGwEAAgMBAQEAAAAAAAAAAAAAAAQBAgMFBgf/xAA0EQACAgECAwQIBwEBAQEAAAAAAQIDEQQhEjFRBRNBkSIyYXGBobHRFDNCUsHh8CMVciT/2gAMAwEAAhEDEQA/AKew8qpiXoK6VrqOX0HmrxT7RuhZTaPY6jsui/fk+q/lGjZP5WSkzROdo3T9m5QVPmKwV790bRsTPP6rsy+jfGV1X8hJnJEXOcJ06RrgAjz7TD6C26hDjZxSsBQ434HfFoycXlMhrJm+UnJa2qq5J3NPkXSSnghy8jXcqvEQ9VrfCZjKheBmtqWY9LL0b7Sm16goXHelQuUN4Jh6M4zWYsXlFrmRIuVPQAdbbKjQYmIAksSdRUit1QnOCTS6pJOFAQe2KtlsHJqZqSE1pVV5NbjQUF1wuwgUQyRKROCDlIMAepBgDtIMAaXyHoq9M/ht/EqEtd6sfiMUeJqVspAl3vwnPgVHMfIe0/5sPevqYJngCFD3sppMZXMiJwYSvSGVTJi2DB3sl2I6f4hn8VHxCJXMW1M26Z+5mrIS4dsMHkzHMskET0wDjnj4Ex1KE+7QrZ6xT5sbYZnk7mxOAyj1InAZPZsGAyepBgjI63LKVSguJIrUUuFTXZdA8ATA0ltJJzqkABSVAEmtVACl1KUMV4cstnBCfUVG/CpoBgKmtIlVojiY1o4O7DiLawslZucvZaJRrcVzWx6XSwwTUxhZKNfNmkYthzZ/J22wM94h1QvOdzWk+icfSPYISnqG+WwxCrfC3YzaWUrbXNZGeRdUXNjht7Lt8KuzodWnsyyW89l8wWn7UeeP0iyRqSLkjgn8zfGbbZ1adPCpeivuRW6kgAEk4AXk8BEG/HhZYTWRkq65RTp0aNmKz2YJ7e6LKDYjf2rCG0N38g4smy2GBRtAB1qPOUeKj7sI0UUjjXaq255m/wCEANr2A/L1Obnt9dFTQecnFPu3xi62j0tHadVu2cPoylLsVwNu1lzZOV80xROfpGx0FmtB5qsR7Rui6k0c3U6Kq7fGH1QWWblg29QZ2Yvqrur904H37o1UkziX6K2rfGV1RZ/8iqLCgpFrGABUzNtvILbyEuNnFKwFDjfgd8TGTi8ohrIFW1kGhVVyjmafJOElPouYjgqvEQ7XrHyn5mUqU+QET0k6wrMdbUhWxQx3pIuUN4MPRtjJZTF5Qa5iJZ4JNTsNCACQdRAOMWbyVxgemJ5Sjco0upgCSABUkbaViVFAyNFiD0AHIAPQAerABovIxMhDsyf6bfxKjn657R+IzQG2UVtfQuiuLax/iY5r5DtLxZF+1GIl4mMMHqZ2uTOpQTARGLZIbYiuRiFJcZNS1ZuXG15sf5iJT3ROpqxp5/8Ay/oboiTQIZPEnz7yggC0pqmGkHwJjtab8qIlb6wPVjbKMztYMoD1YMoD1YNgPQEkuXmghNBUKoRSgIJOCiTsGqn5xVxyyckdx1SsTXXuwphhhFkkRkt8nslZudP0DRKK0Lq+a0PT6XBIJ3RnZdCv1mXjW5GpZP8AJlKSw0k0oPrF5z+awn0CedxUSNwjnW6yUuWyGa6N0luyVbWX0uyMyWSHVAUBHNaTuB6XAXb458reh39L2JbPe30V8/6M/ti235o1ecJGpA5rY4JHvNTvjFyb5notPoqaFiEfj4+ZXJYziEhJKjcABUk7ABeYg2nGKWXyCuxuTZ92i3zoUdW4uHswR237o1jBvmcLV9qUQ9Gr0n18P7CyTyPZlxRtFDrUb1Hio+7CNVFI4F2psufpv4eApdmERYwOCVIgAA7C5Q0GiZtGb/VbBI4qbxHFNeAh6zRvnBmMbl4hNMZKyk6jSsqTfg4yQUk+cnAnbgYQnU08NYOpp+0Lats8S6MDrayOmZeqijSNDpoBIA85OKfdvjGUWjuafW0X7Zw+j+5QFqK5HXUWVnW28zQVz2+qvV91WI9o3RZTaOff2dXZ4YfsCaz7YZfuCsxzqrur904K9+6NFNM4t+guq3xldUTltkRcSEB1QgA8+4h1OY6hK0HEKFRxGw74mMnHdBz5gra2RaTVUsun9Nw1HorxHbXjDdeqfKRjKpPkCM5KuMqzHUFCtihjvBwUN4hyFqktmYuDQyFxoplMCguLcQYPZ0HEGDhXEcYYElcVcyeEKuTyaKFvU1pR71QjqpZSGKlgKJ5SltuHzFfCYRfIaq9ePvQAsM1jBs9ZCrJOaYijY7XSPgARUYSSJ+T7tJuXP9Zv4xFo80K62a/DzXsZrkzae+GzwhgmWz+dPzB2rHwJjqUy/wCa/wB1FbF6RR58acZXB7PiOMOE9pInjDhO58HGHCdDkTxkcJZ2NYr80aNI5utaua2OKtfAVMVlqIw5slVNml5OZDybA0kyQ+sXnP5rKfQ6XpGm4QnbrJy9XZDEKN8JZZc2pyisNDMl0hxQFARzWk02dbgLt8ISt6Hc0vZE7N7Xwr5/0AlsZQTE0avOEpxCBzWxwSPeanfGDbfM9JptLRp1itfHx8yA2kqISkEqNwAFSTsAGMVGnJJZb2DGwuT592inzoW+rcp0jhgjtv3RrGpvmcbVdtVV+jV6T+X9mhWNYEvKijLYCsCs85w8VG+m4UG6NoxS5HnNTrLtQ82S+Hh5FkYsKiFwAUmUFvysmnOmHUpJ+qn6zivuoF544bTGkKpT5IhyS5mXW5ynvLVSWaS22NbgC1q4gHNTwv4w9DRxXrmDv6ACIeQuTbLtR6WXpGHVNr1lJuO5STcobiDFZQjNYkiYya5GmZN8qyDRE63mnyzQJTxW3iNV6a8BCNuhfOD+AxG/qE07kvIWgjTMKSCrB1gggnz04E7cDvjm2U4eGsM6+l7Uup2zxR6P7gFb2RczLVUU6RofaNgmg85OKfdvjBwcT0Om7Q0+o2Tw+j/h+INKaiuRyVZY2fbrzNBXSN9Vd9B5qsR7RujRTaOZqezard8YfVfYJZO1WHrgrMXhmqoK/dOB9+6NVJM4N+gtp3xldUPuy5EWExg1EADcwlLicxxAWnYoVHHcd8SpOLyge4LWpkiL1S6qf01m70V49/fDUNT+4ylWvAFpqXcaVmuJKVbDr3g4EbxDKsT5GTi0M50TxEYOFURxk4OExVsnAV8nrRU4791PxGFtRyRrWaQbO+hdNMG1/AYVfIZoX/SPvRnDDVBCjZ7yFaQ4TSINW8DLjsWSF52CrKfpMMn+qj4hF4rc52sszTNexmiF1SzdDB5IynKtkicfBxzxXwpjp0RzBC1j3KvRxv3ZnxHtHB3ZHEKQyL6mKuslSLKyMmJmaP0DZUgGhcPNbHp6zuFTujKyUYc2aRTYXyWQCGBnvEOEXmvNbHYce27dCc72+WxvGvfCEz2UyWua0M8i4EXIHDb2Xb4VczpVdn2Peey+YNz9svPH6RZI1JFyRwT+ZvjN5Z1KK4U+ovj4jDbxJAF5OAF5PZEYGlfjmE1jZOrcoXVaNGzFZ7ME9vdFlW2KXdrxhtDd/I0WwGJeWH0SAFYFZvWeKjf2C6NFFLkcXUay69+m/h4BCzPgxYWJaJgGACtt3KSWk01fdSkkVSgc5xX3UC88cI0hVKfqoq5JczLcpOVR92qJVOgb66qKePDoo17TvEdCvRxjvLcwld0M+fdUtRWtRUtV6lKJUonaVG8w2klsjDLfMbiAOAxGScHQqJyGD2dBkjBNsq1X5ZekYdU2vWUm47lJNyhuIMEoxmsSWS0ZOPI07JrlbBoidbzT5ZoEp4rbxHFNeAhCzReMH8DeN3UJ57JuQtBGmZUkKVg6wQQT56cCdtaHfHOspw8NYZ2NJ2rdTtnij0f8MArfyLmpaqinSND7RupoPOTin2jfGDg4nodN2jp9RtnD6P8AhgwtoGKpjcqyws+3Xmbq6Rvqrvp91WI9o3RpGbRy9T2dVbvjD6r7BFI2sw/cDmOdRd1T5pwV790aqaZw9RoLad8ZXVEp2WIiwkRlNGACPNSiXE5q0hSdhFe7ZEptcgwDFp5H4qYV6Cz7lfPvhiN/7jNw6AxNSq21ZriClWwj2g6xvEbxalyM2sDQEXSIyaByQy2e8/uQj4lRhqliKNKma7OSYTLPH+k58CoSfJjen/Nh719TEc66FD6BJ4I7rkSkK2WERxyLiU7CXYDJXMsja6gf5CJXMXui3TN+xm5SFlJQLxfG55gw/L4UtGZ/EHwJjs6f8qP+6idvrFBGpmW1g5NzU4aMNEprQuK5raeKzjwFTujOy2EPWZeNbZptgcm0rLjSTSg8sXkK5rCeKT9biq7dCFusk/V2Ga6N8JZZKtfLiXZGjlkh0gUFOaymmFKfW4C7fCErTu6Xsa2e9nor5/0Adr2w/Mmrq6jUgXIHBP5mpjFyb5nfo0dNC9BfHxK0S+cQACVG4ACpJ2ADGIyXnXHGWEFn8nz7gznfok9XFw9mCe2/dGsYN8zharX0w2r9J/ItUZNJl/qJv1qN6j2xqkkca2+dj9JiCpScYkyHmbQIgAemcqWmBV1wDYnFR4JF/bhF4wcuRDaQK2zylzDgKJcaFHXNFOnh0Ue07xDdenivW3MpWdANdfUtRWtRUs3qUolSidpUbzDsZLwF3l8zmdF+Irg9WDIHIMkjdYxyXPZ0HEB4KieIjAoKieIjA820opKgKgY/PhdFuJBwkmyrVfll6Rh1TS9ZScRsUk3KG4giCUYzWJLIKTXI0/JrlbBoidbp/WaBI4raxHFNeAhKzReMPI3jcvEJ53JuQtFGmZUkFX2rBBBPnpFxO2tDvjnWU4eJLDOxpe1Lqds8S6P+AAt/IualqqzdI0Om2CaDzk4p9o3xhKDR6DT9o0ajbOH0f3BlbcQmNyrLGzrdeZurpG+qvUPNViPaN0XU2jmajs2q3fGH1X2CezrWYfuBzHOougJPmnBXv3RqppnDv0FtO+MrqiwVIxYSPCRgA89YyHU5jiAtOxQr2jYd4iVJp5QYBq1eTFRqqVVf5Jw+xK/yV3w3XqfCaMpV55FryPWS6xMzTb7Sm1htu5YpXnKvBwUN4qItq5RlCLi8kVJpvJpVuuAS734TnwGEJchzT/mw96+p8+rcuhZI9vbPchuuRYRnMSy2VGBsrXBzYRZMN0mpf8Zv4xFU90M6itR01n/y/obcpUNHiTEcprCmJq0ZnRNkp0gqtXNbTzE4rOPAVO6OpXdCuqPExaUHKWxeWVkXKy3PmSHli8g81lPZ0/Su3QtZq5S2jsawpXvZNtHlBbaGZLpCyBQU5rSeFMey7fCMrDq0dnSlhz2XzA21cpH5k/SuFSdSBcgcEj3mpjJ5fM7unjVQvQj8fHzIjb9SABUnAC8k7hFeEc/ER5sL7AyNceop5YZRsxcPZgntv3RaNbfM5+p7ZqhtX6T+X9mi2LYUvLCjTYCqUKzzlnio+4UG6NoxS5Hn9RrLtQ/Tfw8PIsVNRYVIr0oDqgAFcp3pWWTV5xKSb0oxWr7qBeeOG+NIVSn6qKuSXMyy2cqFrJDCdGjrGhWfyT7eMMx03DzM3b0BpxRJqSSTiSak8SY0xgrnIkKieJkYFhUWUiGhYVF1Iq0KCosmQdzotkAwc5M50dNjxOftwn+Jh7TbumRnMgJsYqa8S/0RX8TH2h3bGDkRM9drxL/RB+Jj7Se7ZIlciHr85bRBBAGc5UUvJ+rq2a4PxMfaHdMkO5JTKrkuNa7ytZoCAClP0fNEStTH2kd0xDfJ9NH7RjxOftxf8XD2kdyyS3yazh+1l/G5+3FlrYe0juZFpZGQFqS69JLzTLS9qXHBXcpOioobiCIiWqqksSTfkSqpx5M1DJ9c7m5s4JcqGDjC1877za0ADiD2CEbO7/Rn4myz4kK3si5WZqrN0Tp6bdBU+cnBXHHfGEq0zp6XtO+jbOY9H/AFP8mk0Cc1xkp1ElaSRvGaad8Z90zrLtrTtbxl8iOrk3m+ux4l/og7tkf+vp+kvJfctrJsC0mKAuMuN9Va3DQearMqPaN0XSkjn6i/RXb8LT6pL6ZChuSNBUAHWAagdtBXujQ5TxnYlMyMBBPYlgIAH3FgCAAfyimvoHvw1/AYh8jWj82PvRgzjkYI9ZbPcYSKmJYtHMmWcu1QRm2dWmvhRa5Pn+al/wAZv4xEx5oz1r//AD2e5mwTUyE8YaPDA9ak84R9HmlV/wBZSkjHEUSe67jEMvDhb9Ll7AKtKxZ2YNVutlNSQgKUEip1AIv4m+KOMnzOnTq9NUvRi/f4/UjDImZPSa8S/wBERwM2/wDSp6P5fcelshXifpFpCfMqonvAA4xPAUs7Shj0E8+0vpOwUMD6NNDrUb1Ht+UXSSOZbqLLfWf2JCXXEazEmJZSVvqTcqAAjkrXQvEwAVOUTFqvVRKLlmG+uVuKeP8AqzUdlTsIhip0reWX/veUlxeAAv8AJVaClFS32FLN6lKcdUonaVFuphv8ZX4JmLpk+YwrknnvKS/jc/biHq6/aHcyI7vJZOjpy/jc/bij1NftLd3Igv8AJzNpxUz2KX+iM3fD2k92yGvIqZGKm/Er9MR38Se7YlOSEx1mvEr9MStREju2PN5FzB6bXiX+iLfiY+0ju2SE5BTJ+0Z8S/0Rb8VH2kd0zeEuNK6Se8Qhka4JdH5DEzJNK6SfEIjIcEuj8iombNSk1Ck+IYa+MGQ4JdGD85VN2dd94e/XEhwy6ENM0B0h3wEYfQlsWgOsO8QBwvoWctaKesO8QBwy6FrLWknrDvEBPBLoWTFoo66e8QBwS6MmInUddPiEGQ4JdH5DomkddPiERknu59H5Hi62emnxCJyRwS6PyEZ6OunxCIyHBLo/I6FN9dPiETlBwS6PyFB5sdNPiEGUHBLo/I4ubQOmnxCIyg4J9H5FdOWgjrp7xE5Dgl0BTKC0ElpwZw+ovWOqYh8i9UWpx28UY6pUYnoZyyybIs64rJj2lq8WTlRQfbwTbBT/ADDKqgUcQbzsUDTj8ovFbiOtmlTNdUzRLQtAYBQ2jnA1G/djDOTxnDLoQELCz9YHtEAcMuheWfIpOKk94gyHdz6PyLVuSaHTT4hBlBwS6PyFmUa66fEIMoO7l0fkR3pFvUpPiEGUHdy6PyK2akE9ZPeIjIcEuj8inmpJPWHeInIcEujK/Sls3KHeIA4ZdC7snKMC4qGzGAjhfQKJS1Wlj66e8QE8EuhKLqD00+IRGSe7n0fkMOFB6Se8ROQ7ufR+RCmGkHpJ7xEZI7uXR+RVTMkg9JPeInIcEuj8isekE9ZPeIA4JdGMCXA6Q7xAHDLoSG6DpDvEAcEuhmDd5AAvOGEK4PcK3BYshKBnEJJIN+cDrpQAX4VvrEYwT3rlsJdezidQNbhvuqd9MYhjEUsEV2WB1QJlJ1ZK9+WpGiZzraWiMRFthXLQpJiGi0ZseQsRGDeNjH0KGyIwbxsHkqGwRXhN42DiSNgiMGqsFimwQYLqZ2g2QE8R67ZEYDjOGmwROCHMbURsEGDOU2RnSIukK2WEN1UWSErLGeYRnGBlKo8Ui5aRQRkzt1w4YjjTWcdgrtAwvNKxKKWTwImZoJTmgX021peTeRcSLiDqi6Eptt5K1RKjea8b8YDNewlS8uNkUbHqaiQUgahFRrPCIKxsETgo7TmeNggwR3osKGwQYLq0Vmg6hEFspiFsDZE5KSryRnZcbIsmKTrIrjFMIshOdbQ2hebBhFYWyiycxMDYIo4nQq1WSWnNOoRXA4pZOlsbBADQgtDYIko0NqaGyJMnEQWhsiSjRzRjZAVwTnilsfVIUTqCRXNzeduSb+8xbIo4SZXuv1NaUGAAwG4bsYC8ZOIpt6K4N4WklDkVwNRsFKQDAWlFSK+Zloumc67TkFaSIuc+UWjiVQApDqXIjBrGY8lyIN42DqXIjBqrB0ORGDVTFByDBZTPFyDBPGJLsGCjmNKcicGUrCM6uJwK2TI5NYsLN5ZZ2ezrjOTOppKsblpLIBrUEi4UAvFeluAp7YhDdsschE3NpvCRtANAKYDm02j8oshVp+JULMSYSeR6WarENm9FeSaTQRQebUURnHIlIWnMazosY8RzPgI4hQXAWUxxDkRg0jYPocirRvGwWRWINMJjLjUWTMJ1kN1iLJidlJFUkiLZFHFxH2ZqkQ4m9eoaJ7UyDFGjoQvTHgaxBummcIgIaE5uqAzaJwS0m9QxJFCkm8Urm7se/dFxXE3yK/NBio0kpDLkvEpmM6COpBEWFnFxFIciMFoTJTTsVaG4WDxAMQbNKSIcxLRZMSu05XOskRpk5s6nFjdYkyyLSuIwXUxxLkRg1UxwORGDRTFB2At3h7SwB3gkuQFXMbU5E4M3MZWqJMJSHZVqpiGzWitykXTaaCMjuQjwxwIWYlFZMiuqiyFLJDSE1MSYxXEyybTQRmzqQioxGHXIlIXsmRyYsLtnICuRJMSQcrAVydC4CVIcQ5EGsZklt2KtDULB8KrEG6aYlbcGSsq8kV1mLJis6iI6xFkxKdPQZBIidjFOUWSWpqKuIzXqWiW3M1ivCOR1CY4HAYMGqmmdUquJrAGxz+CfT9i76tfyi2BH8RCP6l5ofaYdN2hc9Wr5RDixiGsqfOS80Oqsh5WDDvql/KI3LSspl+teaIb1jPj7B31a/lFlkTnKtcpLzQymTeH2TngV8onBSN8F+peaJbMq95Fz1a/lFWmNV6qv9y80Sk2c+fsHfVL+UVwxn8RS/wBS80MvWI+fsHfVL+UWWRayVMv1LzRWzFivj7F31a/lF0zn2KvwkvNEJci6MW1+BXyiRVyivFeYjQL6ivCflEh3seq8zoZX1FeE/KAt30eq8xWhX1FeE/KIwT30eq8z2hX1F+E/KDAd9HqvM4WV9RXhPygwQ7o9V5iSyvqK8J+USV72PVeYpmRdUaBtZ4IV8oAjODfNeaLuUsd9Iziw7QCpOjXQDbWkZyydjSupfqXmjyzFB+TI7ioshabIjqosKTZKkGCogAEkmgAFSScAAMTFZDGngkuJk+YkXh9i76tfyiEmXt1NXhJeaISpF7yLnq1fKL4FHdW/1LzQn+Ae8k56tXygwyve1/uXmj38A95Jz1avlBhh3tf7l5o5/wAe75Jz1a/lBhle9r/cvNCDIO+Sc8CvlAQ7a/3LzQhUk75JzwK+UBR2w/cvNCf4Z3ya/Ar5RJHfQX6l5oebYc8mvwK+URg1jqYfuXmiW1KveSc9Wr5RVxGoaqv9y80S0SD5+wd9Wv5RHCxmOpqf6l5oUbJfP2D3ql/KIwyXdS/1x80MuWO//wBd71S/lE7mMrKf3rzRGcsV/wAg76pfyi24tN1P9S80Rl2M/wCRc9Wr5RbcWl3fhJeaGf8Aj3h9k54FfKAorIr9S80OJl3vJOeBXyiMGsdTFfqXmh5Mu75JzwK+URg1Wqh+5eaN6ckwsXQyeQKecs1SbxAA3J2oto0VWkABFLzaH074AKq07K1iACoSpSDfABayNob4CMF3LTQMBOBx+WSsQAD9pZPg4CAAYnsnyMBABUPWctOqACMWFDVAAnRq2QAKTLqOqACUxZi1QAGOTdhUoSIACS1wEyzwHknPgVES5G2n/Nh719TAlG6FT3U3uMOKiwrNkcCpiRdLilgI8mubMy5/rN/GIpF+khvUpR0s/wD5f0NNnn85UNnhiLSADlIAFJRAB0twANLagAjusQAQX2YAIalFJgAmSdoU1wAEMhaW+AC+lZ6uuAME5LgMACHGAYAIb0jABXvWeNkAENyzRsgAR/AQAZG3ygWknCaPqmf0R1O5q6fUW7yQ8eUK0zjNf6WP24utPS/D5v7lXbMjP5YT6sZiv9pn8kQPS1+C+pHfSGW8sJ9BqmYI9Br9EZPTwXh9S6tZNTyjWmRQzR9Ux+3F400vnH6/ch2TGHssp9WMxX+0yPciLPS1+C+pHeyGP/l08Ptz6tr9EZvTw6Fu8ZcWHblsTB+heObrWptoNj0ii/gKmM5xphzRdObNQybVMNisxNqfWdWjbbQOASkKPEnsEKTlF+qsGqT8QmamgYzJFOS6FaoAK6cshuhUSAkXkkgADaScICVFt4QA29bksglLA0q+tg2O3FXZdvjJ2rwOzpuxbp+lZ6K6eP8AXxBRdqTBJOeBuCEUHCoJineM6a7HoX6fmxxi05okJS4SomgAbQSTsACb4O8Zb/ydNFZksJe1/cOsncnbSXRb7+gb6ujaU6ezNontv3Rdcb5nJ1M9BXtXDifveP7DlhaEfRBYU4lIJBKc+huClJTSleAEbYeMnHbTZX28/wDQPfhOfAYrLkaUfmx96+pgxVdC2D20mR3VRYVnIdkmqmsVkzXS15eS2stz+YZ/Fb+IQQW5btCX/Ca9jNKF8NHhziHUqqAoEpNFUIJSdh2GJawAsJiAHm24APTcopSaJcU2rUpISe8KBBEQy9c1F5az/vYBtsotRiqtLpG+uhtskDzkZtR7RvjNuSOzp1oLtuHD6Nv65KA5Szflv8G/0xXjY9/5un/b839zrOU0ylVVKDidaVJSnuKQKRKmzKzsymSxFY/3tLuTthh+6uY51V3VPmqwPv3RoppnGv0NtW/NdUV1s2fNAlTL9PMUlFOxWbXv742jKH6kJNPwBh7KG0GVZq3FIVvQ37Dm0PZDEYVszbkh5rLm0BhMn1bX6I0jVX0KOciUjlBtMYTR9Ux+3Gioq6fX7kOyQ6nlFtT/ALZ9Ux+3F1p6f2/N/cr3shX/ANi2p/2z6lj9uJ/DU/t+b+5HfTEq5QbTOM1/pY/bifw1X7fr9w76YhWXlpf9n/Ux+3Efhaun1DvZCDl1aP8A2f8AUz+iI/DV9Ce+kDRRF3ApkReIrui3MWlyLRmVcRy4xpsyu6G1NRnKvoWUidZNjTD97bZzNbirmx6WvgKmMpXKvZmir4jUMk8hpFICn1ad7qq5rQO5HS9IkbhClurlLZbGsKlEL5myABzKADAC4AboVyaleplaIAHET2aKqNALySaAb66oCUm3hFPaXKI23VLI0q+tg2O3FXZdvjOVmOR1NP2VOe9j4V8wMtbKGYmjV5wqTqQLkDgkXdpqd8YybfM9HpqKdOv+ax7fHzITZKiAASo3AAVJO4DGK4G3YkssL7CyGddot9Whb6uLpHDBPbeNkaRqb3ZyNV23XX6NS4n18P7Ct+0LNspAqUpXS4f+R9Y99CddyYaq08peqjzWq11tzzZL4eHkZ9lLypzL9USw/h2utcp4j72COy/fHRr0kY7y3OfO7oPcj8wS9NKUoqUpDZKiSSTnKvJN5MU1vqxSLU5ech9bT1WXfw1/AY5z5DlH5sfejElKuhc9jOQyBnGJF0nORZIGamM+Z04rggLshVZln8VHxCNI80c3WPNU/czVQIYPIGQZSzjjNoPraWpC88XpNK8xNxGBG43R0qoqVaTF5yakEdgcomCZpH91sfE3+ae6Mp6TxgWjb1NJsuaafQHGXEuI2pNabiMQdxvhSUXF4ZqmmTSiKkiS3ABQ21knLzFVFOY710XE/eGCvfvirgmPaftC6nbOV0f+2AO2skpiXqrN0jY6aATQecjEe0b4ycGjuaftCm7bOH0f3B8prFRxxJslbDzV1c9HVVfTgcR7t0WjNo5+o0Fdu+MP2Fqial5kZigAo9BYBqfNOB98axs6HEv0NlW/NFdOZJholbRvFaBRNBzbs3Wb6ih7xjDEbn4iLigTnkKQshSCjYk9laHA9kNQsWDKURsLjVTKOIsLjRTK8IrOi/GRg9nQcRGDtYOIMHgYlMMHaRbCZAlTUZusspE+yLAmZm9ps5nlFVS2PS14YCpjCdir5s1UHI0TJbJGUZIVMjTuDUsUaHodL0qjcIWs1c5bLY1jVFGkhLDqQKAClABcANgEKGhVT2TZHObPdABC/j35f696BiTgBx1QEpNvCKm1OURgDNab0jm03NjtxV2d8ZynjkdPTdmux/8AV8K+YD2paTsyauLqNSRcgcE/mb4ycm+Z6CnR01LFa+PiQEsKJASCSbgAKknYAMYC8ocKy+QS2VkW+uinvokbMXD2YJ7e6LqDfM5V/asK9q938gnQ7JWcm/NS5SuOc8sVA7BU7hUwxXU3yRxNRrLLfzJfDwA3KDlJfd5kuCyjWo0Lpupjgjsv3iHq9MlvLcRlb0Alx0qJUolSjeVKJKidpJvJhpbGL35iaxJGA95JT9LMfcR8SoT1nJf7ob0h5bL1GXfw1/CY575DdP5kfejGCqt0YHqpPieCdKM0FTFGx7T08Kyz0w5WJSC6zOw/YQ/mWPxUfEIsuYhqvyZ+5msGGDyRjGWQ/npj74+BMdWj8tCtnMqAI3wZtkiQtF1hekZcU2vak0ruIwUNxqIrNRksMmLa5B5YnKeq5M0j+62Papv8090IWaZfoGI2dQ4kLebdTntrStO1Jr2HYdxhWUXHZmuSxbnEmIAeBBwMAFFbWSkvMVUU6NzrooCfvJwV798UcEx7T9oXU7Zyuj/gBbWyQmGTWgcb66K3AXkqTiOyo3xm4NHco7Qpu25Po/4ZVOobTeBUKScFHXqodW/jjEG7g5HGbWdQesjqKqQBhzTiMIspNCV/Z9c9+T6osG35eYGYoAE9BdLz5pwPvjSM+hxr9DbV4ZXsKm0skCL2jTzFYdise+sMxu6iLgDU1LONHNcSUq3jHgcD2RvGWeRm44GwuNFJlcCguLKZGBQVFuJlcCyI03ILOxrCmJk/RI5mtxXNbHpa+AqYzldGHMsq2zUcmMipRqipj+YcuuUKNCmxuvO9Ko3CFLNXKW0djaNSW5oCdEsAUAAFABQADYBChqQpqwkKvTABUTNnuM1VWiReSTQAbSYCUm3hFBN8ouhqlsaVW03NjtxV2d8Uc+h0qezJy3s2XzBK18pHps1fWSNSBzUJ4JHvNTGMnJnodLVpqViEfj4leJQLICQSo3AAVJOwAYxXLN501NZzgJLM5N5tYz1/RJ6uLhHDBPbfujVQb5nD1HaFdTxU+L6FquaasoUWlCVka+c8se+ncI3rpb9VHH1Gsst/Ml8PAp7W5QnnAQ3RhN4KgQpy4X34JVfgK8djddKXrbicpvwASbtEuVrUkmpUSSVG+tSbyK30OENppGLyRM4RbiRGGezhBxIMHCuI40GAy5NJkpcfoMUI+JUKap5SNqlgNJ9t1xty400az/iYRfIapWbIr2r6mdy0sAKmFWz3FWnUd2Lee1CBImyzwRHiwvzJ9gqpMs/ioH+QiY8zHVfkT9zNYSmphg8gY1lomk/MffHwJjr6f8tClvrFEpUXlIokIrGbeS56kGAH5OacaVntrKFbUnHcRgRuMRKCktyVJoMrGy8IomYTT+ogfEj5d0Kz037TWNnUObPtlLiQttYWjak1HA7DuhVprmarctpe0QcYgCcl9Oo6/dABSW1ktLzNVFOY6emi7xJwV798VcEx7T9oXU7Zyuj/ANsAls5JTEvVWbpGx00Amg85GI9o3xk4NHd0/aFN+2cPo/4YPlAMVHXAsLPtZ1qgrno6q7+44j3bosptCF/Z1Vu+MPqglk5mUmxo1gJUfs3KUJ81WB9h3RrGw4mo7Ouq3xldUVlscmpvVLLofJrJp6K8R214iG4X/uOa4dAGtCzHWFZjzam1agoXHeki5Q3gmG4Yl6plJNEcIi/CUya3k3kZJsEKmRp3NihRof2+l6VRuEJWauctlsMRqig9Qww4AEkDYMANwhU0GHrEUL0mACG6260Co3JF5JNABvOqAlJt4RQWhyhpaqloaRe28NjtxV2d8ZufQ6dHZc5b2eivn/QH2tlK/NGrzhUnUgc1A4JHvNTGUm3zPQ6Wqihegvj4kFICyABVRuAAqSdwGMV3GnKtrLCqxuTp16inVBlHVuU4ezBPbfujSMJPmcPV9pUQ2q9J9fAt52UlbKTUuJQsi4Vznl8AL6dw4Q1XTKXqo4V+rnZ67+AKT3KRNunRsEstmtV3KcpTGp5qBtpU7DDkdMo7y3EnbnkDZqCVuLJcX9ZxSgsk804m81FRnHZshlT2xgycSumJrPNThUkC66vDHVfF04lWmNUTBiAZkczEwcEA4me0Yg4IBxM6EJg4YBmRofI2Wg7MlYu0bdPEqFNbwqMcG9OfE0q1rTZDDwSkf+Jwf4GOc+Q7p3i2PvX1MOU+ThC2D2k7nJiAIkySOxBYnWEP5lj8Vv4xFo8xfVfkT9zNolpel5hg8gYVl64P+QmaYaQfAmOpVL/mhWa9IHwIslkqOBEaKJVs7SLYIyepBgDxTBwk5LCyUuIIcbcU2qprQgZyQK3A3KvuvFL4xnBPZovGWAxkctUJGY+KGuaVoGcBS8KUjfrpgdUKT0r/AEmytXiFMnM6ROkaWHEHpJNRXfsO4wrKLi8M1TyS259acYgCU1ao1wAVtrWHKTNVU0bh6aKAk+cnBXv3xRwTH9N2jdTtnK6MCrXyaeYqRRxvro1DzkYj2jfGbg0d3T9pU3bZw+j+5S1EUH8l1Y+U78vRIVnt9Rd9B5qsU+7dF1NoR1HZ9F2+MPqgwk7ekp1OidSkE/ZugFJPmqNxOzA7o2hbh7bHB1PZttW+Mrqijtjk0bUrOl3dGNaFgrA+6rHsNeMOw1bxiSOU6V4B/msLuJoYTNhh+xU0K0OhIF5JUAAN5OEBKTbwgVn8tXJclLKtMRrvzO/pdl2+M3Yjq09kXSXFNYXz/oErXyompk1fUVJ1IFyBwSNe81MZNuXidnTQhpliMPj4+ZATMJUaZpqcABU9giMMaeoqa9LYKbByND9FPOpZR1cXD2YJ7b90XVcnzOXqu1KIbVLify/sJpuTs+zUZ2mQlRF1+e8vgBzqdwG6GqqHJ+ijgajV2WbzfwAa2eUGZXVMvVpHXNC6fyR2VO+HoaPHrbiMrugGuurUoqWSpZvUpRKlE7STeYZWVskZN5PNPlJrTcQcCDqMS5EYOOO5xqcdwoAAKADsiMoMMTdBsG56ggwg3OZog4UTlns2DhQZPZsRwhkO+SZoF2Yr1EfEqFNWsJG9JoNptJDLv4a/hMIPkN0fmx96MfELns9jtYgjJ5KawEqLZaZPgJmWCfLN/GImPMz1UUtPPPRmnT9qFZzUYQyeLMWysbP8a/XHPFfCmOpRHMExW17lWBDGEjLJ2JA9WAD0GwHonIDqXyE5t2sVpeAcQDviMBkapE4IJMhPOsKz2nFIXtScdygblDcQYpKuMlhotGbXIO7D5QEKoibbzT5VsEjipvEcU14CErNG1vA3jcvEOZWVafQHGVpcbPSQQocLsDuMJSi4vDNk8nl2QRhEEjZs1Y2wAVNp5INvVNMxzrpur94YK9++KuKY5Rrrats5XR/7YD7WySmmKqzdI2OkgE0HnJxHtG+MnFo7Wn11Vu2cPo/uUgQYrk6HCy4s3KCZYGalecnUlYzgOF9RwrSJU2hW3s+m15kt/ZsGGUGUjDZKGklx0XGtUoSd5N57O+NJWJcjlaTsmy1KU3hP4sBrRm33jz3CRWoSDRA4J/M3xk5Z5nZq0Eafy+fXxIOc4nfEbG3FdAv7MsJ1dFPDMbN/NKSsjdfQdvdF1Uc+/tlQfCo5a8gvatGy5JoqVLlIwKzVa1E6q/8AoRvXXl4icHUaqy55sfw8AIyky5DxKZVnQN9dVFOns+qjXtO8Q/Xp616zyITsfgBy+cSoqJUcSSSTxJvMNKEfBmTlLxPBs7YtwvwZXi9h7NVtgxPqGYnudsEGZBseJOyI4n0DHtOV3RHEuhOPacqIOKJPDI9UQZiRhnronMQwz1BtiPR6huHvJIEaWYzlEcxFLq9JUK6zHCsG1JodqJZ0LvPNdGvUeod0c98hyj82PvRjqc2mMLbntP8An1OhSRBuHFBCTMbBBgo7/CKJlhS6lzLAJxdbHeoRaOMi2pjKVM2+jNol5FtsYVMMHkjDsu1f/oTP4g+BMdah/wDOP+6iti9IoKxo5FMHCYjiJwJJMV4gwezojiJ4TmdBxhwnc8wd4HCd0hie8I4Doci3ehwHdLE98RwEyy7Zell6RhxTa9ZSbjuUk3KG4gxWU4SWJIlKUeRpWT/K6mgTOMgHyzQOb6TeI4prwEJWaZc4G8bOodN5Ry6gFAGhFcDgYUNRRt+X6p7oAELyhY1JPdAAOW7JyMzVWjLbp+0bFCT5ycFe/fFJQTOhpu0rqNua6MBrTsh1k6loJoFC7vSbwe+MnBo7tHalVvhh9H/R/9k='; +$string['boolean_filename_01'] = 'ENflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/lang/es/surveyprotemplate_flags.php b/template/flags/lang/es/surveyprotemplate_flags.php new file mode 100644 index 00000000000..f841aa21340 --- /dev/null +++ b/template/flags/lang/es/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

¿Reconoces esta bandera?

+

ESFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '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'; +$string['boolean_filename_01'] = 'ESflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/lang/it/surveyprotemplate_flags.php b/template/flags/lang/it/surveyprotemplate_flags.php new file mode 100644 index 00000000000..c261cccc069 --- /dev/null +++ b/template/flags/lang/it/surveyprotemplate_flags.php @@ -0,0 +1,32 @@ +. + +/** + * Strings for component 'surveyprotemplate_flags', language 'en' + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['boolean_content_01'] = '

Riconosci questa bandiera?

+

ITFlag

'; +$string['boolean_extranote_01'] = ''; +$string['boolean_filecontent_01'] = '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'; +$string['boolean_filename_01'] = 'ITflag.jpg'; +$string['pluginname'] = 'flags'; +$string['privacy:metadata'] = 'The "flags" template plugin does not store any personal data.'; + diff --git a/template/flags/pix/icon.png b/template/flags/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f0470bc8beb397ac8fa5b5fef4904b74abf5198d GIT binary patch literal 625 zcmV-%0*?KOP)<~e5aB&bz6^zoBBY3DP$_f}2M1F(h4@kN3)49G5o`12J%>`o zw8r?1clZ3bdpM|~U~t%7tq&lT1@GPq9_#CmeFAMF(|bGDei}E z7l2Xq7~2)I-S$Co*yEmOr#~|I%!u4_5Npl%&(W^O6D^zHKUrs$OBsbx;F^NC036Vl z_l|u8l5{4{`Bv5SfH~l(w#TNgXSck|`hhVo+}sW}z&I37F9QD1RKlKtG>{HNQlp#l zPurfu?gThXW&u+zFhxt>>Q=A+oB5xB1<2B0`7b~fuzd>D0EkiuLHLIRw%ns%eDIqf|7d^`c6buf#3k{!Q2;0uwJ()G-a&rkT$KgY*XV$Erx>2*+7pITM00000 LNkvXXu0mjf6VDRf literal 0 HcmV?d00001 diff --git a/template/flags/pix/icon.svg b/template/flags/pix/icon.svg new file mode 100644 index 00000000000..a1fdefde9d6 --- /dev/null +++ b/template/flags/pix/icon.svg @@ -0,0 +1,579 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/flags/template.xml b/template/flags/template.xml new file mode 100644 index 00000000000..78a3ac8d52f --- /dev/null +++ b/template/flags/template.xml @@ -0,0 +1,27 @@ + + + + + boolean_content_01 + + boolean_filename_01 + boolean_filecontent_01 + + 1 + 0 + 0 + 1 + 0 + boolean_extranote_01 + 0 + 0 + 0 + + + 2 + 1 + strfbool01 + + + + diff --git a/template/flags/version.php b/template/flags/version.php new file mode 100644 index 00000000000..ef05fb86a6e --- /dev/null +++ b/template/flags/version.php @@ -0,0 +1,30 @@ +. + +/** + * Defines the version of surveyprotemplate_flags template subplugin + * + * @package surveyprotemplate_flags + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2024042200; +$plugin->release = '1.0'; +$plugin->requires = 2024042200; // Requires this Moodle version. +$plugin->component = 'surveyprotemplate_flags'; // Full name of the plugin (used for diagnostics). diff --git a/template/oneofeachenable/classes/privacy/provider.php b/template/oneofeachenable/classes/privacy/provider.php new file mode 100644 index 00000000000..90227db75e9 --- /dev/null +++ b/template/oneofeachenable/classes/privacy/provider.php @@ -0,0 +1,44 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_oneofeachenable\privacy; + +/** + * Privacy Subsystem for template_oneofeachenable implementing null_provider. + * + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/template/oneofeachenable/classes/template.php b/template/oneofeachenable/classes/template.php new file mode 100644 index 00000000000..8f654357a59 --- /dev/null +++ b/template/oneofeachenable/classes/template.php @@ -0,0 +1,47 @@ +. + +/** + * Surveypro class to manage oneofeachenable template + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace surveyprotemplate_oneofeachenable; + +/** + * The class to manage oneofeachenable template + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template { + + /** + * Apply template settings. + * + * @param string $tablename + * @param object $record + * @param object $config + * @return [$tablename, $record] + */ + public function apply_template_settings($tablename, $record, $config) { + return [$tablename, $record]; + } +} diff --git a/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php b/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php new file mode 100644 index 00000000000..bbc4addaf17 --- /dev/null +++ b/template/oneofeachenable/lang/en/surveyprotemplate_oneofeachenable.php @@ -0,0 +1,248 @@ +. + +/** + * Strings for component 'surveyprotemplate_oneofeachenable', language 'en' + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['age_content_01'] = 'age_content_01'; +$string['age_content_02'] = 'age_content_02'; +$string['age_content_03'] = 'age_content_03'; +$string['age_content_04'] = 'age_content_04'; +$string['age_content_05'] = 'age_content_05'; +$string['age_extranote_01'] = 'age_extranote_01'; +$string['age_extranote_02'] = 'age_extranote_02'; +$string['age_extranote_03'] = 'age_extranote_03'; +$string['age_extranote_04'] = 'age_extranote_04'; +$string['age_extranote_05'] = 'age_extranote_05'; +$string['age_filecontent_01'] = 'agefilecontent01'; +$string['age_filecontent_02'] = 'agefilecontent02'; +$string['age_filename_01'] = 'age_filename_01'; +$string['age_filename_02'] = 'age_filename_02'; +$string['autofill_content_01'] = 'autofill_content_01'; +$string['autofill_content_02'] = 'autofill_content_02'; +$string['autofill_content_03'] = 'autofill_content_03'; +$string['autofill_extranote_01'] = 'autofill_extranote_01'; +$string['autofill_extranote_02'] = 'autofill_extranote_02'; +$string['autofill_extranote_03'] = 'autofill_extranote_03'; +$string['boolean_content_01'] = 'boolean_content_01'; +$string['boolean_content_02'] = 'boolean_content_02'; +$string['boolean_content_03'] = 'boolean_content_03'; +$string['boolean_content_04'] = 'boolean_content_04'; +$string['boolean_content_05'] = 'boolean_content_05'; +$string['boolean_content_06'] = 'boolean_content_06'; +$string['boolean_content_07'] = 'boolean_content_07'; +$string['boolean_extranote_01'] = 'boolean_extranote_01'; +$string['boolean_extranote_02'] = 'boolean_extranote_02'; +$string['boolean_extranote_03'] = 'boolean_extranote_03'; +$string['boolean_extranote_04'] = 'boolean_extranote_04'; +$string['boolean_extranote_05'] = 'boolean_extranote_05'; +$string['boolean_extranote_06'] = 'boolean_extranote_06'; +$string['boolean_extranote_07'] = 'boolean_extranote_07'; +$string['character_content_01'] = 'character_content_01'; +$string['character_content_02'] = 'character_content_02'; +$string['character_content_03'] = 'character_content_03'; +$string['character_defaultvalue_01'] = 'character_defaultvalue_01'; +$string['character_defaultvalue_02'] = 'character_defaultvalue_02'; +$string['character_defaultvalue_03'] = 'character_defaultvalue_03'; +$string['character_extranote_01'] = 'character_extranote_01'; +$string['character_extranote_02'] = 'character_extranote_02'; +$string['character_extranote_03'] = 'character_extranote_03'; +$string['checkbox_content_01'] = 'checkbox_content_01'; +$string['checkbox_content_02'] = 'checkbox_content_02'; +$string['checkbox_content_03'] = 'checkbox_content_03'; +$string['checkbox_defaultvalue_01'] = 'checkbox_defaultvalue_01'; +$string['checkbox_defaultvalue_02'] = 'checkbox_defaultvalue_02'; +$string['checkbox_defaultvalue_03'] = 'checkbox_defaultvalue_03'; +$string['checkbox_extranote_01'] = 'checkbox_extranote_01'; +$string['checkbox_extranote_02'] = 'checkbox_extranote_02'; +$string['checkbox_extranote_03'] = 'checkbox_extranote_03'; +$string['checkbox_labelother_01'] = 'checkbox_labelother_01'; +$string['checkbox_labelother_02'] = 'checkbox_labelother_02'; +$string['checkbox_labelother_03'] = 'checkbox_labelother_03'; +$string['checkbox_options_01'] = 'checkbox_options_01'; +$string['checkbox_options_02'] = 'checkbox_options_02'; +$string['checkbox_options_03'] = 'checkbox_options_03'; +$string['date_content_01'] = 'date_content_01'; +$string['date_content_02'] = 'date_content_02'; +$string['date_content_03'] = 'date_content_03'; +$string['date_extranote_01'] = 'date_extranote_01'; +$string['date_extranote_02'] = 'date_extranote_02'; +$string['date_extranote_03'] = 'date_extranote_03'; +$string['datetime_content_01'] = 'datetime_content_01'; +$string['datetime_content_02'] = 'datetime_content_02'; +$string['datetime_content_03'] = 'datetime_content_03'; +$string['datetime_extranote_01'] = 'datetime_extranote_01'; +$string['datetime_extranote_02'] = 'datetime_extranote_02'; +$string['datetime_extranote_03'] = 'datetime_extranote_03'; +$string['fieldset_content_01'] = 'fieldset_content_01'; +$string['fieldset_content_02'] = 'fieldset_content_02'; +$string['fieldset_content_03'] = 'fieldset_content_03'; +$string['fieldset_content_04'] = 'fieldset_content_04'; +$string['fieldset_extranote_01'] = 'fieldset_extranote_01'; +$string['fieldset_extranote_02'] = 'fieldset_extranote_02'; +$string['fieldset_extranote_03'] = 'fieldset_extranote_03'; +$string['fieldset_extranote_04'] = 'fieldset_extranote_04'; +$string['fileupload_content_01'] = 'fileupload_content_01'; +$string['fileupload_content_02'] = 'fileupload_content_02'; +$string['fileupload_content_03'] = 'fileupload_content_03'; +$string['fileupload_extranote_01'] = 'fileupload_extranote_01'; +$string['fileupload_extranote_02'] = 'fileupload_extranote_02'; +$string['fileupload_extranote_03'] = 'fileupload_extranote_03'; +$string['integer_content_01'] = 'integer_content_01'; +$string['integer_content_02'] = 'integer_content_02'; +$string['integer_content_03'] = 'integer_content_03'; +$string['integer_extranote_01'] = 'integer_extranote_01'; +$string['integer_extranote_02'] = 'integer_extranote_02'; +$string['integer_extranote_03'] = 'integer_extranote_03'; +$string['label_content_01'] = 'label_content_01'; +$string['label_content_02'] = 'label_content_02'; +$string['label_content_03'] = 'label_content_03'; +$string['label_content_04'] = 'label_content_04'; +$string['label_leftlabel_01'] = 'label_leftlabel_01'; +$string['label_leftlabel_02'] = 'label_leftlabel_02'; +$string['label_leftlabel_03'] = 'label_leftlabel_03'; +$string['label_leftlabel_04'] = 'label_leftlabel_04'; +$string['multiselect_content_01'] = 'multiselect_content_01'; +$string['multiselect_content_02'] = 'multiselect_content_02'; +$string['multiselect_content_03'] = 'multiselect_content_03'; +$string['multiselect_defaultvalue_01'] = 'multiselect_defaultvalue_01'; +$string['multiselect_defaultvalue_02'] = 'multiselect_defaultvalue_02'; +$string['multiselect_defaultvalue_03'] = 'multiselect_defaultvalue_03'; +$string['multiselect_extranote_01'] = 'multiselect_extranote_01'; +$string['multiselect_extranote_02'] = 'multiselect_extranote_02'; +$string['multiselect_extranote_03'] = 'multiselect_extranote_03'; +$string['multiselect_options_01'] = 'multiselect_options_01'; +$string['multiselect_options_02'] = 'multiselect_options_02'; +$string['multiselect_options_03'] = 'multiselect_options_03'; +$string['numeric_content_01'] = 'numeric_content_01'; +$string['numeric_content_02'] = 'numeric_content_02'; +$string['numeric_content_03'] = 'numeric_content_03'; +$string['numeric_extranote_01'] = 'numeric_extranote_01'; +$string['numeric_extranote_02'] = 'numeric_extranote_02'; +$string['numeric_extranote_03'] = 'numeric_extranote_03'; +$string['pluginname'] = 'oneofeachenable'; +$string['privacy:metadata'] = 'The "oneofeachenable" template plugin does not store any personal data.'; + +$string['radiobutton_content_01'] = 'radiobutton_content_01'; +$string['radiobutton_content_02'] = 'radiobutton_content_02'; +$string['radiobutton_content_03'] = 'radiobutton_content_03'; +$string['radiobutton_content_04'] = 'radiobutton_content_04'; +$string['radiobutton_content_05'] = 'radiobutton_content_05'; +$string['radiobutton_content_06'] = 'radiobutton_content_06'; +$string['radiobutton_defaultvalue_01'] = 'radiobutton_defaultvalue_01'; +$string['radiobutton_defaultvalue_02'] = 'radiobutton_defaultvalue_02'; +$string['radiobutton_defaultvalue_03'] = 'radiobutton_defaultvalue_03'; +$string['radiobutton_defaultvalue_04'] = 'radiobutton_defaultvalue_04'; +$string['radiobutton_defaultvalue_05'] = 'radiobutton_defaultvalue_05'; +$string['radiobutton_defaultvalue_06'] = 'radiobutton_defaultvalue_06'; +$string['radiobutton_extranote_01'] = 'radiobutton_extranote_01'; +$string['radiobutton_extranote_02'] = 'radiobutton_extranote_02'; +$string['radiobutton_extranote_03'] = 'radiobutton_extranote_03'; +$string['radiobutton_extranote_04'] = 'radiobutton_extranote_04'; +$string['radiobutton_extranote_05'] = 'radiobutton_extranote_05'; +$string['radiobutton_extranote_06'] = 'radiobutton_extranote_06'; +$string['radiobutton_labelother_01'] = 'radiobutton_labelother_01'; +$string['radiobutton_labelother_02'] = 'radiobutton_labelother_02'; +$string['radiobutton_labelother_03'] = 'radiobutton_labelother_03'; +$string['radiobutton_labelother_04'] = 'radiobutton_labelother_04'; +$string['radiobutton_labelother_05'] = 'radiobutton_labelother_05'; +$string['radiobutton_labelother_06'] = 'radiobutton_labelother_06'; +$string['radiobutton_options_01'] = 'radiobutton_options_01'; +$string['radiobutton_options_02'] = 'radiobutton_options_02'; +$string['radiobutton_options_03'] = 'radiobutton_options_03'; +$string['radiobutton_options_04'] = 'radiobutton_options_04'; +$string['radiobutton_options_05'] = 'radiobutton_options_05'; +$string['radiobutton_options_06'] = 'radiobutton_options_06'; +$string['rate_content_01'] = 'rate_content_01'; +$string['rate_content_02'] = 'rate_content_02'; +$string['rate_content_03'] = 'rate_content_03'; +$string['rate_content_04'] = 'rate_content_04'; +$string['rate_content_05'] = 'rate_content_05'; +$string['rate_content_06'] = 'rate_content_06'; +$string['rate_defaultvalue_01'] = 'rate_defaultvalue_01'; +$string['rate_defaultvalue_02'] = 'rate_defaultvalue_02'; +$string['rate_defaultvalue_03'] = 'rate_defaultvalue_03'; +$string['rate_defaultvalue_04'] = 'rate_defaultvalue_04'; +$string['rate_defaultvalue_05'] = 'rate_defaultvalue_05'; +$string['rate_defaultvalue_06'] = 'rate_defaultvalue_06'; +$string['rate_extranote_01'] = 'rate_extranote_01'; +$string['rate_extranote_02'] = 'rate_extranote_02'; +$string['rate_extranote_03'] = 'rate_extranote_03'; +$string['rate_extranote_04'] = 'rate_extranote_04'; +$string['rate_extranote_05'] = 'rate_extranote_05'; +$string['rate_extranote_06'] = 'rate_extranote_06'; +$string['rate_options_01'] = 'rate_options_01'; +$string['rate_options_02'] = 'rate_options_02'; +$string['rate_options_03'] = 'rate_options_03'; +$string['rate_options_04'] = 'rate_options_04'; +$string['rate_options_05'] = 'rate_options_05'; +$string['rate_options_06'] = 'rate_options_06'; +$string['rate_rates_01'] = 'rate_rates_01'; +$string['rate_rates_02'] = 'rate_rates_02'; +$string['rate_rates_03'] = 'rate_rates_03'; +$string['rate_rates_04'] = 'rate_rates_04'; +$string['rate_rates_05'] = 'rate_rates_05'; +$string['rate_rates_06'] = 'rate_rates_06'; +$string['recurrence_content_01'] = 'recurrence_content_01'; +$string['recurrence_content_02'] = 'recurrence_content_02'; +$string['recurrence_content_03'] = 'recurrence_content_03'; +$string['recurrence_extranote_01'] = 'recurrence_extranote_01'; +$string['recurrence_extranote_02'] = 'recurrence_extranote_02'; +$string['recurrence_extranote_03'] = 'recurrence_extranote_03'; +$string['select_content_01'] = 'select_content_01'; +$string['select_content_02'] = 'select_content_02'; +$string['select_content_03'] = 'select_content_03'; +$string['select_defaultvalue_01'] = 'select_defaultvalue_01'; +$string['select_defaultvalue_02'] = 'select_defaultvalue_02'; +$string['select_defaultvalue_03'] = 'select_defaultvalue_03'; +$string['select_extranote_01'] = 'select_extranote_01'; +$string['select_extranote_02'] = 'select_extranote_02'; +$string['select_extranote_03'] = 'select_extranote_03'; +$string['select_labelother_01'] = 'select_labelother_01'; +$string['select_labelother_02'] = 'select_labelother_02'; +$string['select_labelother_03'] = 'select_labelother_03'; +$string['select_options_01'] = 'select_options_01'; +$string['select_options_02'] = 'select_options_02'; +$string['select_options_03'] = 'select_options_03'; +$string['shortdate_content_01'] = 'shortdate_content_01'; +$string['shortdate_content_02'] = 'shortdate_content_02'; +$string['shortdate_content_03'] = 'shortdate_content_03'; +$string['shortdate_extranote_01'] = 'shortdate_extranote_01'; +$string['shortdate_extranote_02'] = 'shortdate_extranote_02'; +$string['shortdate_extranote_03'] = 'shortdate_extranote_03'; +$string['textarea_content_01'] = 'textarea_content_01'; +$string['textarea_content_02'] = 'textarea_content_02'; +$string['textarea_content_03'] = 'textarea_content_03'; +$string['textarea_content_04'] = 'textarea_content_04'; +$string['textarea_content_05'] = 'textarea_content_05'; +$string['textarea_content_06'] = 'textarea_content_06'; +$string['textarea_extranote_01'] = 'textarea_extranote_01'; +$string['textarea_extranote_02'] = 'textarea_extranote_02'; +$string['textarea_extranote_03'] = 'textarea_extranote_03'; +$string['textarea_extranote_04'] = 'textarea_extranote_04'; +$string['textarea_extranote_05'] = 'textarea_extranote_05'; +$string['textarea_extranote_06'] = 'textarea_extranote_06'; +$string['time_content_01'] = 'time_content_01'; +$string['time_content_02'] = 'time_content_02'; +$string['time_content_03'] = 'time_content_03'; +$string['time_extranote_01'] = 'time_extranote_01'; +$string['time_extranote_02'] = 'time_extranote_02'; +$string['time_extranote_03'] = 'time_extranote_03'; diff --git a/template/oneofeachenable/pix/icon.png b/template/oneofeachenable/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f0470bc8beb397ac8fa5b5fef4904b74abf5198d GIT binary patch literal 625 zcmV-%0*?KOP)<~e5aB&bz6^zoBBY3DP$_f}2M1F(h4@kN3)49G5o`12J%>`o zw8r?1clZ3bdpM|~U~t%7tq&lT1@GPq9_#CmeFAMF(|bGDei}E z7l2Xq7~2)I-S$Co*yEmOr#~|I%!u4_5Npl%&(W^O6D^zHKUrs$OBsbx;F^NC036Vl z_l|u8l5{4{`Bv5SfH~l(w#TNgXSck|`hhVo+}sW}z&I37F9QD1RKlKtG>{HNQlp#l zPurfu?gThXW&u+zFhxt>>Q=A+oB5xB1<2B0`7b~fuzd>D0EkiuLHLIRw%ns%eDIqf|7d^`c6buf#3k{!Q2;0uwJ()G-a&rkT$KgY*XV$Erx>2*+7pITM00000 LNkvXXu0mjf6VDRf literal 0 HcmV?d00001 diff --git a/template/oneofeachenable/pix/icon.svg b/template/oneofeachenable/pix/icon.svg new file mode 100644 index 00000000000..a1fdefde9d6 --- /dev/null +++ b/template/oneofeachenable/pix/icon.svg @@ -0,0 +1,579 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/oneofeachenable/template.xml b/template/oneofeachenable/template.xml new file mode 100644 index 00000000000..781d046a543 --- /dev/null +++ b/template/oneofeachenable/template.xml @@ -0,0 +1,1965 @@ + + + + + boolean_content_01 + 1 + 0 + 0 + 0 + 0 + boolean_001 + boolean_extranote_01 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + age_content_01 + 1 + 0 + 0 + 0 + 0 + age_001 + age_extranote_01 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -2138101200 + -2148555600 + -2132830800 + + + + + age_content_02 + + age_filename_01 + age_filecontent_01 + + + age_filename_02 + age_filecontent_02 + + 1 + 0 + 0 + 0 + 0 + age_002 + age_extranote_02 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -1264942800 + -1580562000 + -1141304400 + + + + + age_content_03 + 1 + 0 + 0 + 0 + 0 + age_003 + age_extranote_03 + 0 + 1 + 1 + + 1 + 1 + + + + 1 + -1359637200 + -1580562000 + -1141304400 + + + + + age_content_04 + 1 + 0 + 0 + 0 + 0 + age_004 + age_extranote_04 + 0 + 1 + 0 + + 1 + 1 + + + + 1 + -1454331600 + -1580562000 + -1141304400 + + + + + age_content_05 + 1 + 0 + 0 + 0 + 0 + age_005 + age_extranote_05 + 0 + 1 + 1 + + 1 + 1 + + + + 1 + -1233406800 + -1580562000 + -1141304400 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_02 + 1 + 0 + 0 + 0 + 0 + boolean_002 + boolean_extranote_02 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + label_content_01 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_01 + + + + + fieldset_content_01 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_01 + 0 + 0 + 0 + + + 2 + + + + + autofill_content_01 + 1 + 0 + 0 + 0 + 0 + autofill_001 + autofill_extranote_01 + 0 + 1 + 0 + + + 0 + userid + + + + + autofill_content_02 + 1 + 0 + 0 + 0 + 0 + autofill_002 + autofill_extranote_02 + 0 + 1 + 0 + + + 0 + userid + submissionid + cammello + + + + + autofill_content_03 + 1 + 0 + 0 + 0 + 0 + autofill_003 + autofill_extranote_03 + 0 + 1 + 0 + + + 0 + userid + + + + + fieldset_content_02 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_02 + 0 + 0 + 0 + + + 2 + + + + + boolean_content_03 + 1 + 0 + 0 + 0 + 0 + boolean_003 + boolean_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + 1 + 1 + strfbool01 + + + + + + boolean_content_04 + 1 + 0 + 0 + 0 + 0 + boolean_004 + boolean_extranote_04 + 0 + 1 + 0 + + 8 + 1 + + + + 1 + 1 + strfbool01 + + + + + + boolean_content_05 + 1 + 0 + 0 + 0 + 0 + boolean_005 + boolean_extranote_05 + 0 + 1 + 0 + + 8 + 1 + + + + 3 + 0 + strfbool01 + + + + + + fieldset_content_03 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_03 + 0 + 0 + 0 + + + 2 + + + + + character_content_01 + 1 + 0 + 0 + 0 + 0 + character_001 + character_extranote_01 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_01 + PATTERN_EMAIL + 0 + + + + + character_content_02 + 1 + 0 + 0 + 0 + 0 + character_002 + character_extranote_02 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_02 + 00000 + 5 + 5 + + + + + character_content_03 + 1 + 0 + 0 + 0 + 0 + character_003 + character_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + 0 + character_defaultvalue_03 + PATTERN_URL + 0 + + + + + <hr class="fieldsetendcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + checkbox_content_01 + 1 + 0 + 0 + 0 + 0 + checkbox_001 + checkbox_extranote_01 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_01 + checkbox_labelother_01 + checkbox_defaultvalue_01 + 0 + 1 + 2 + 0 + 0 + + + + + checkbox_content_02 + 1 + 0 + 0 + 0 + 0 + checkbox_002 + checkbox_extranote_02 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_02 + checkbox_labelother_02 + checkbox_defaultvalue_02 + 0 + 1 + 2 + 0 + 0 + + + + + checkbox_content_03 + 1 + 0 + 0 + 0 + 0 + checkbox_003 + checkbox_extranote_03 + 0 + 1 + 0 + + 8 + 1 + + + + checkbox_options_03 + checkbox_labelother_03 + checkbox_defaultvalue_03 + 0 + 1 + 2 + 0 + 0 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_06 + 1 + 0 + 0 + 0 + 0 + boolean_006 + boolean_extranote_06 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + date_content_01 + 1 + 0 + 0 + 0 + 0 + date_001 + date_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 952081200 + 1593252000 + + + + + date_content_02 + 1 + 0 + 0 + 0 + 0 + date_002 + date_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 5223600 + 1609412400 + + + + + date_content_03 + 1 + 0 + 0 + 0 + 0 + date_003 + date_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 31489200 + strftime05 + 951994800 + 1609412400 + + + + + datetime_content_01 + 1 + 0 + 0 + 0 + 0 + datetime_001 + datetime_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 1 + 18330600 + strftime01 + 5184000 + 20991540 + + + + + datetime_content_02 + 1 + 0 + 0 + 0 + 0 + datetime_002 + datetime_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 5 + -3600 + strftime01 + 5184000 + 28857540 + + + + + datetime_content_03 + 1 + 0 + 0 + 0 + 0 + datetime_003 + datetime_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 1 + 7825200 + strftime01 + 5184000 + 18313140 + + + + + fileupload_content_01 + 1 + 0 + 0 + 0 + 0 + fileupload_001 + fileupload_extranote_01 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + fileupload_content_02 + 1 + 0 + 0 + 0 + 0 + fileupload_002 + fileupload_extranote_02 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + fileupload_content_03 + 1 + 0 + 0 + 0 + 0 + fileupload_003 + fileupload_extranote_03 + 0 + 0 + 0 + + 27 + 1 + + + + 1 + 1048576 + .pdf,.xls, .ods, .odt + + + + + integer_content_01 + 1 + 0 + 0 + 0 + 0 + integer_001 + integer_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 17 + 10 + 20 + + + + + integer_content_02 + 1 + 0 + 0 + 0 + 0 + integer_002 + integer_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 3 + 0 + 0 + 20 + + + + + integer_content_03 + 1 + 0 + 0 + 0 + 0 + integer_003 + integer_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 1 + 64 + 0 + 128 + + + + + multiselect_content_01 + 1 + 0 + 0 + 0 + 0 + multiselect_001 + multiselect_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_01 + multiselect_defaultvalue_01 + 0 + 1 + 0 + 0 + 4 + + + + + multiselect_content_02 + 1 + 0 + 0 + 0 + 0 + multiselect_002 + multiselect_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_02 + multiselect_defaultvalue_02 + 0 + 1 + 0 + 0 + 4 + + + + + multiselect_content_03 + 1 + 0 + 0 + 0 + 0 + multiselect_003 + multiselect_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + multiselect_options_03 + multiselect_defaultvalue_03 + 1 + 1 + 0 + 0 + 4 + + + + + numeric_content_01 + 1 + 0 + 0 + 0 + 0 + numeric_001 + numeric_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + 3 + 0 + 0 + + + + + numeric_content_02 + 1 + 0 + 0 + 0 + 0 + numeric_002 + numeric_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + 185 + 0 + 178.0000000000 + 200.0000000000 + 0 + + + + + numeric_content_03 + 1 + 0 + 0 + 0 + 0 + numeric_003 + numeric_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + 3.00 + 0 + 2 + + + + + radiobutton_content_01 + 1 + 0 + 0 + 0 + 0 + radiobutton_001 + radiobutton_extranote_01 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_01 + radiobutton_labelother_01 + 1 + radiobutton_defaultvalue_01 + 1 + 0 + + + + + radiobutton_content_02 + 1 + 0 + 0 + 0 + 0 + radiobutton_002 + radiobutton_extranote_02 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_02 + radiobutton_labelother_02 + 3 + radiobutton_defaultvalue_02 + 1 + 0 + + + + + radiobutton_content_03 + 1 + 0 + 0 + 0 + 0 + radiobutton_003 + radiobutton_extranote_03 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_03 + radiobutton_labelother_03 + 1 + radiobutton_defaultvalue_03 + 1 + 0 + + + + + radiobutton_content_04 + 1 + 0 + 0 + 0 + 0 + radiobutton_004 + radiobutton_extranote_04 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_04 + radiobutton_labelother_04 + 1 + radiobutton_defaultvalue_04 + 1 + 1 + + + + + radiobutton_content_05 + 1 + 0 + 0 + 0 + 0 + radiobutton_005 + radiobutton_extranote_05 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_05 + radiobutton_labelother_05 + 3 + radiobutton_defaultvalue_05 + 1 + 1 + + + + + radiobutton_content_06 + 1 + 0 + 0 + 0 + 0 + radiobutton_006 + radiobutton_extranote_06 + 0 + 1 + 0 + + 27 + 1 + + + + radiobutton_options_06 + radiobutton_labelother_06 + 1 + radiobutton_defaultvalue_06 + 1 + 1 + + + + + <hr class="pagebreakcontent" /> + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + boolean_content_07 + 1 + 0 + 0 + 0 + 0 + boolean_007 + boolean_extranote_07 + 0 + 0 + 0 + + + 1 + 1 + strfbool01 + + + + + + rate_content_01 + 1 + 0 + 0 + 1 + 0 + rate_001 + rate_extranote_01 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_01 + rate_rates_01 + 3 + rate_defaultvalue_01 + 1 + + 0 + + + + + rate_content_02 + 1 + 0 + 0 + 1 + 0 + rate_002 + rate_extranote_02 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_02 + rate_rates_02 + 1 + rate_defaultvalue_02 + 1 + + 0 + + + + + rate_content_03 + 1 + 0 + 0 + 1 + 0 + rate_003 + rate_extranote_03 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_03 + rate_rates_03 + 1 + rate_defaultvalue_03 + 1 + + 0 + + + + + rate_content_04 + 1 + 0 + 0 + 1 + 0 + rate_004 + rate_extranote_04 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_04 + rate_rates_04 + 1 + rate_defaultvalue_04 + 1 + + 0 + + + + + rate_content_05 + 1 + 0 + 0 + 1 + 0 + rate_005 + rate_extranote_05 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_05 + rate_rates_05 + 1 + rate_defaultvalue_05 + 1 + + 0 + + + + + rate_content_06 + 1 + 0 + 0 + 1 + 0 + rate_006 + rate_extranote_06 + 0 + 0 + 0 + + 53 + 1 + + + + rate_options_06 + rate_rates_06 + 3 + rate_defaultvalue_06 + 1 + + 0 + + + + + recurrence_content_01 + 1 + 0 + 0 + 0 + 0 + recurrence_001 + recurrence_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 25009200 + strftime01 + 39600 + 31489200 + + + + + recurrence_content_02 + 1 + 0 + 0 + 0 + 0 + recurrence_002 + recurrence_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 5310000 + strftime01 + 39600 + 15588000 + + + + + recurrence_content_03 + 1 + 0 + 0 + 0 + 0 + recurrence_003 + recurrence_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 3 + 39600 + strftime01 + 5137200 + 23540400 + + + + + select_content_01 + 1 + 0 + 0 + 0 + 0 + select_001 + select_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_01 + select_labelother_01 + 1 + select_defaultvalue_01 + 1 + + + + + select_content_02 + 1 + 0 + 0 + 0 + 0 + select_002 + select_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_02 + select_labelother_02 + 3 + select_defaultvalue_02 + 1 + + + + + select_content_03 + 1 + 0 + 0 + 0 + 0 + select_003 + select_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + select_options_03 + select_labelother_03 + 1 + select_defaultvalue_03 + 1 + + + + + shortdate_content_01 + 1 + 0 + 0 + 0 + 0 + shortdate_001 + shortdate_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1238580000 + strftime01 + 1154426400 + 1312192800 + + + + + shortdate_content_02 + 1 + 0 + 0 + 0 + 0 + shortdate_002 + shortdate_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 3 + 39600 + strftime01 + 13082400 + 965124000 + + + + + shortdate_content_03 + 1 + 0 + 0 + 0 + 0 + shortdate_003 + shortdate_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 5137200 + strftime01 + 39600 + 1606820400 + + + + + fieldset_content_04 + 1 + 0 + 0 + 0 + 0 + fieldset_extranote_04 + 0 + 1 + 0 + + + 2 + + + + + textarea_content_01 + 1 + 0 + 0 + 0 + 0 + textarea_001 + textarea_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 100 + 500 + + + + + textarea_content_02 + 1 + 0 + 0 + 0 + 0 + textarea_002 + textarea_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 0 + + + + + textarea_content_03 + 1 + 0 + 0 + 0 + 0 + textarea_003 + textarea_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 10 + 60 + 0 + + + + + textarea_content_04 + 1 + 0 + 0 + 0 + 0 + textarea_004 + textarea_extranote_04 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + textarea_content_05 + 1 + 0 + 0 + 0 + 0 + textarea_005 + textarea_extranote_05 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + textarea_content_06 + 1 + 0 + 0 + 0 + 0 + textarea_006 + textarea_extranote_06 + 0 + 0 + 0 + + 53 + 1 + + + + 0 + 10 + 60 + 0 + + + + + time_content_01 + 1 + 0 + 0 + 0 + 0 + time_001 + time_extranote_01 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1 + -3600 + strftime01 + 0 + -60 + + + + + time_content_02 + 1 + 0 + 0 + 0 + 0 + time_002 + time_extranote_02 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 3 + -3600 + strftime01 + 18000 + 63000 + + + + + time_content_03 + 1 + 0 + 0 + 0 + 0 + time_003 + time_extranote_03 + 0 + 1 + 0 + + 53 + 1 + + + + 1 + 1 + 41400 + strftime01 + 28800 + 57540 + + + + + label_content_02 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_02 + + + + + label_content_03 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_03 + + + + + label_content_04 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + label_leftlabel_04 + + + diff --git a/template/oneofeachenable/version.php b/template/oneofeachenable/version.php new file mode 100644 index 00000000000..f768820f4c9 --- /dev/null +++ b/template/oneofeachenable/version.php @@ -0,0 +1,30 @@ +. + +/** + * Defines the version of surveyprotemplate_oneofeachenable template subplugin + * + * @package surveyprotemplate_oneofeachenable + * @copyright 2013 onwards kordan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2024042200; +$plugin->release = '1.0'; +$plugin->requires = 2024042200; // Requires this Moodle version. +$plugin->component = 'surveyprotemplate_oneofeachenable'; // Full name of the plugin (used for diagnostics). diff --git a/templatemaster/version.php b/templatemaster/version.php index 881a651d9e9..cfdc29df759 100644 --- a/templatemaster/version.php +++ b/templatemaster/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 1965100401; +$plugin->version = 2024042200; $plugin->release = '1.0'; -$plugin->requires = 1965100401; // Requires this Moodle version. +$plugin->requires = 2024042200; // Requires this Moodle version. $plugin->component = 'surveyprotemplate_templatemaster'; // Full name of the plugin (used for diagnostics). diff --git a/tests/behat/backup_restore.feature b/tests/behat/backup_restore.feature index cfaf2ea6daa..a55454d6a21 100644 --- a/tests/behat/backup_restore.feature +++ b/tests/behat/backup_restore.feature @@ -8,6 +8,8 @@ Feature: Backup and restore a surveypro Given the following "courses" exist: | fullname | shortname | category | numsections | | Course 1 | C1 | 0 | 3 | + And the following config values are set as admin: + | enableasyncbackup | 0 | And I log in as "admin" @javascript @@ -64,7 +66,7 @@ Feature: Backup and restore a surveypro And I should see "What do you usually get for breakfast?" And I should see "When were you born?" And I should see "Please, write down date and time of your last flight to Los Angeles." - And I should see "Please, upload your CV in PDF format" + And I should see "Please, upload your CV in PDF" And I should see "How many people does your family counts?" And I should see "What do you usually get for breakfast?" And I should see "Type the best approximation of π you know" diff --git a/tests/behat/backup_simple.feature b/tests/behat/backup_simple.feature index 21f0549b057..0257faef22b 100644 --- a/tests/behat/backup_simple.feature +++ b/tests/behat/backup_simple.feature @@ -11,6 +11,8 @@ Feature: Backup a surveypro And the following "activities" exist: | activity | course | name | intro | section | | surveypro | C1 | Test surveypro | Surveypro description | 1 | + And the following config values are set as admin: + | enableasyncbackup | 0 | And I log in as "admin" @javascript diff --git a/tests/behat/behat_mod_surveypro.php b/tests/behat/behat_mod_surveypro.php index 1d937f2fa56..3bfaaa0a9cd 100644 --- a/tests/behat/behat_mod_surveypro.php +++ b/tests/behat/behat_mod_surveypro.php @@ -41,6 +41,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class behat_mod_surveypro extends behat_base { + use core_behat_file_helper; /** * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'. @@ -184,12 +185,14 @@ public function i_should_see_items($givennumber, $status) { case 'available': $xpath = "//a[contains(@id,'makereserved')] | //img[contains(@id, 'makereserved')]"; $nodes = $container->findAll('xpath', $xpath); + $rednodes = $container->findAll('xpath', "//img[contains(@title, 'Unreservable')]"); break; case 'searchable': $nodes = $container->findAll('xpath', "//img[contains(@id, 'removefromsearch')]"); break; case 'not searchable': $nodes = $container->findAll('xpath', "//img[contains(@id, 'addtosearch')]"); + $rednodes = $container->findAll('xpath', "//img[contains(@title, 'Unsearchable')]"); break; case 'visible': $nodes = $container->findAll('xpath', "//tr[contains(@id, 'itemslist') and not(contains(@class, 'emptyrow')) and not(contains(@class, 'dimmed'))]"); @@ -200,7 +203,11 @@ public function i_should_see_items($givennumber, $status) { default: throw new Exception('Unrecognised status "' . $status . '."'); } - $tablerows = count($nodes); + if (!isset($rednodes)) { // Red because red is the outline of the icons for unchangeable settings. + $tablerows = count($nodes); + } else { + $tablerows = count($nodes) + count($rednodes); + } if (intval($givennumber) == $tablerows) { return; @@ -208,22 +215,22 @@ public function i_should_see_items($givennumber, $status) { switch ($status) { case 'reserved': - $message = sprintf('%d reserved items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d reserved items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'available': - $message = sprintf('%d available items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d available items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'searchable': - $message = sprintf('%d searchable items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d searchable items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'not searchable': - $message = sprintf('%d unsearchable items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d unsearchable items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'visible': - $message = sprintf('%d visible items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d visible items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; case 'hidden': - $message = sprintf('%d hidden items found in the "item" table, but should be %d.', $tablerows, $givennumber); + $message = sprintf('%d hidden items found in the "item" table, %d were declared.', $tablerows, $givennumber); break; default: throw new Exception('Unrecognised status "' . $status . '."'); @@ -266,7 +273,7 @@ public function surveypro_has_the_following_items($surveyproname, TableNode $dat $record = get_dummy_contents($type, $plugin, $content); // Add the item. - $item = surveypro_get_item($cm, $surveypro, 0, $type, $plugin); + $item = surveypro_get_itemclass($cm, $surveypro, 0, $type, $plugin); $item->item_save($record); } } diff --git a/tests/behat/change_of_mind.feature b/tests/behat/change_of_mind.feature index abc8a19cba7..ba374173452 100644 --- a/tests/behat/change_of_mind.feature +++ b/tests/behat/change_of_mind.feature @@ -67,7 +67,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Choose a direction" Then I should see "Question without parent" - And I set the field "id_surveypro_field_select_4" to "South" + And I set the field "id_field_select_4" to "South" And I set the field "Question without parent" to "This should remain" And I press "<< Previous page" @@ -166,17 +166,17 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Which pet do you like more?" And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_2 | 1 | + | id_field_radiobutton_4_2 | 1 | And I press "Next page >>" Then I should not see "Choose a direction" And I set the following fields to these values: - | id_surveypro_field_checkbox_7_1 | 1 | + | id_field_checkbox_7_1 | 1 | And I set the field "Question without parent" to "This should remain" And I press "<< Previous page" And I set the following fields to these values: - | id_surveypro_field_radiobutton_4_3 | 1 | + | id_field_radiobutton_4_3 | 1 | And I press "<< Previous page" And I set the field "Is it true?" to "0" @@ -187,7 +187,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Choose a direction" Then I should see "Question without parent" - And I set the field "id_surveypro_field_select_6" to "South" + And I set the field "id_field_select_6" to "South" And I press "Submit" Then I should not see "Some answers of this response have been found as unverified." @@ -277,7 +277,7 @@ Feature: Delete of no longer allowed answers on user change of mind And I set the field "Write down your email, please" to "su@nowhere.net" And I set the following fields to these values: - | id_surveypro_field_radiobutton_2_1 | 1 | + | id_field_radiobutton_2_1 | 1 | And I press "Next page >>" Then I should see "Was it carved in marble?" Then I should not see "Is it A4 format?" @@ -288,7 +288,7 @@ Feature: Delete of no longer allowed answers on user change of mind Then I should see "Which artwork did you make?" And I set the following fields to these values: - | id_surveypro_field_radiobutton_2_0 | 1 | + | id_field_radiobutton_2_0 | 1 | And I press "Next page >>" Then I should see "Is it A4 format?" Then I should not see "Was it carved in marble?" diff --git a/tests/behat/duplicate_response.feature b/tests/behat/duplicate_response.feature index b05f8d6dfb3..cea217bac7c 100644 --- a/tests/behat/duplicate_response.feature +++ b/tests/behat/duplicate_response.feature @@ -39,7 +39,7 @@ Feature: Duplicate a response Then I should see "and never modified?" And I press "Continue" - # Edit the duplicatet response + # Edit the duplicated response And I click on "//a[contains(@id,'edit_submission_row_2')]" "xpath_element" And I set the field "Is it true?" to "No" And I press "Submit" diff --git a/tests/behat/item_action.feature b/tests/behat/item_action.feature index 28e6a6f600d..b68b727aafb 100644 --- a/tests/behat/item_action.feature +++ b/tests/behat/item_action.feature @@ -42,36 +42,32 @@ Feature: Execute item actions And I follow "Layout" Then I should see "0" reserved items - # 21 and not 22 available items because pagebreak doesn't have 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 D<0K~$ literal 0 HcmV?d00001 diff --git a/tests/fixtures/usertemplate/MMM_2023103100.xml b/tests/fixtures/usertemplate/MMM_2024032800.xml similarity index 95% rename from tests/fixtures/usertemplate/MMM_2023103100.xml rename to tests/fixtures/usertemplate/MMM_2024032800.xml index 0d8fd9dbc7a..a08891df37f 100644 --- a/tests/fixtures/usertemplate/MMM_2023103100.xml +++ b/tests/fixtures/usertemplate/MMM_2024032800.xml @@ -1,52 +1,46 @@ - + - 0 - 1 - 1 - - <p><img src="@@PLUGINFILE@@/MMM_logo.png" alt="MMM" width="313" height="70" /></p> MMM_logo.png iVBORw0KGgoAAAANSUhEUgAAATkAAABGCAYAAAHA5dPHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUU0NTA5QjhCRTNDMTFFMjg1OTdDMzU0MDYyMjIwNUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUU0NTA5QjlCRTNDMTFFMjg1OTdDMzU0MDYyMjIwNUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTQ1MDlCNkJFM0MxMUUyODU5N0MzNTQwNjIyMjA1QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFRTQ1MDlCN0JFM0MxMUUyODU5N0MzNTQwNjIyMjA1QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PonyXXsAAEPRSURBVHjaxJQxLENBGMfv6GubqJ1EtYkFiVjEhETS0Wjv5CXVViJiMNpMBrSURYwNg1glokzEQIImIqGaGA0Ufa/t87/me805V5u45Nf73vfdffe/u+/KvYNx9l/tbWpTdbWAmuoQzVF6XXP+UGuFelfcqCpwh/o9EjIuCYqCO7JtKdYPvCAI/NJiCWlDYqEx5QAuNAJbwYj0faIKjEpJSuAIrNP3tjRxnmKP4AZY4Al8kpB9ZeFZkAPvkm9BczMcnIJFcCwHPeKnioOtOYy3YJiA83psmsZwdbtVh4c/zEwXzCLoMbz2vS8Vz5EYppnXpvrKiRSzy4brc2uvSBuNgQ0hnpum2dhJNpsNvSyVCnalebEYhs1su564ALrBK2h3Y770t0e3CyZ1eayKh1mx9G+1ztVdOtaa0UzXIYiQ3QvyUhIhMAAewHVgy5yQrs3tb0EfmAErrp9e8TPooDouqwvXr9jJGDgVNgzzTErMJDsi2XmyC0quMCHasqbGRN2GwIAyr1OyV0Hyx99Mrao9tUtKLh7AkEZ0UDPHrZc5afwBvXgh7hxcNcrFb6vzk6rjSwAxElFQgyzwpXbBpyH4nuFMyGq8apjQCl9HLGrc6FSplGJzHANSgmWAZm9bHDWGPRR/hfK/YamBziCxHdHMyYTJXYxchm52N6jkwua4XKRczIxceqOBZvTCE82RIFAFpWdAC3JQIe4AxKtQ0tPEQmQuKLeD4vgTkpsYwGnuN9C98ea/GbZcYWX49INw+Kvwf2K4ELZCgZX5L+vvv8y3gUUJOQ0DUGKfipa7QQ5rAeISIGZnSTD/DY+WNyenMoLKPSbG/8BaBBKQX4EFMDfrb/QCGQTuAx3GgFR2MUAdibMgRgMwhy0H4kggTofWHEJAXA0rGuKAeCEfJ9Bx3awMaEUGPjZymQmuY1jZfzOyT8mGlW8zoRaGQB0MAueB2BCI/Td5bd3oJP20DVoHg9SLA/FLII4GYm8gjgIFYxkotIAOg6U5L6Q0CMKboBU7uiPRm0Ow+hMEtiGVe2uQog3ksIWghoOhyBtY+oSZ+xJWBIIcBssQ2MqwyVANIOwHxP1IJT562w/uUGCjAMb0RBJ/B1X/BprTQS0jBtlF8TC1XFC1sEIvBSYBEIAZqwttIgjCs3fJBaTmRStI1ZeKCoKtKEKhL5WWCirG+gMiQl9KVFoREaQ+CqKIL5IqRfui2CJUQiGIKK0ULJTqQ/VBJFQUISLYVqGWaExy6+51toyTu6QVHxwYLrfZ2dudnZ35vjVJWPogEt22G09cJckh7uvGNLQX/mNZSgEgYVa2SPgh9SwBIua/WdJnFf7Ok7Z3Sq9i2NK8/JVhXNqWxec3ZjNLIqsTn/P4XEf6zbB50zaJeV+S7270IIUUlZjKHeK4fqU1fgYhFt56gKMIjt6QQXeSfjuwUAkWeeAzFrfj5z3LUabPu5ZWpU9ZW6U5BdmKqPPL9NmsNO3jlw60e4IJ7jDmsVEMuHqdTkLMKIKO0JN4gJElcBfWkMULRuFsTk6xzwCWAUokYOLIIGy/fwKcyE8vQ+ZdC8KWa/p8UVpN0sUPnAcfO4XFmc7JzPN5GVsYO5iEgutNJY3ppp05fg+hnWZDH5YAz9ixOHzPCahd7Za4PxKJhIrFYuFlegYmp6s95tZc8wkexYagOdkGIxl1gtQkHKzDxzdNwce5lXC9cQy2qWqwovfkAtHJOyDP3IB8wTakaT3ZgPlF8mQX4dRoE/S+rlOOzf3zXOed3z9vJWik78cNaUQqy/kRt2sS8XjcexGKz1qWBbZtQyKRgFRnSLRu8WwuKx1R+owY12Je0AVigg18D8O9n7V34+XDcJDzED5uMBXP6ekyTpQYIfkyR3wpvvP6X9r1As7VvfLr00KOuJEokk9zyu7yMh5zb4WHXAlycFJe/DAtr5xvsSgm0TngNgFMF5ReU1qnVM+iQek4G9MUlLBPOzDnVbE+U5jcBaJGGTC2gwsbQMBGo6UdF0rbNDd8mzt9kyJVLnPoME4qDOsZx/UuVtukCHsXK3CoXgwrx/EBM+Y+BZ9nSaQAKS5AgJqW9395wpLstok6W2KONd+oQseZ7xrWZSLkAG404NUE2D0lvHkrizQgzM6QJCMNJQCyzF1KOZjjLqN92RLt6wiCFX6iwWsfeVeEBNp80sfCrebaz/B4XyporAyBRIHyWwBqrS42iioKnzu7s9RKU6jy86JWpIs/LwRJqTGaGkR8MKKUookUkjYxankAf2IATTTR+GKMxgIxoSQiiiaiUgjKgqYm6gOJSbUPVkyDRAUqP62abmG3dLln+t3t6d070xHrQ29yMztn5tydPXvuOef7zqhJoJQNnpkyY+jxd5iS/E9reKIAtbdcXGp7oRXHPqepN6Zb57fEMZyTPr2CL1eiNppqw6Yvb3eEAqfhvo8I6IMiOO8R3jXigEMSVrUJ2bB1TwE8iTx/WkA0ey1b9qE4HxSZMY6uc/eKzwN67rZ+144ww32m5434zLXXS8KLykAI8HwU1Mir0FUhXsfHVqFnsxoKa8jzN8SarnWVgH2PiLXLcM2Po5vTJckE8a0Sx5fDWjb2Vv0HNdpKoXQn0vvfmItR2L4Qw/0vCL06lBJR4y4Y24z+CM8YFGvXgkB+PY4uIx9mJTFOietVOBpv2yKufQz6aSNIhoCL5eQwAxyoXagqBx9mCmJlVeiFCD3TryrEAPxh6xqDzIwhi9KlvuZ2ujoRhLUKgRLa9WwBHOsQXN0ql9d5+CeGXQShowC9H4H03hhxQ+p1FrPOxTIaemJ7cbsw8M+PeHavpEClrS0SXivX/sAh+y1Md6aGdDCa2WXmN7QIRsastRY7MLyOY1DPXYCUXv6OeZeo85cEzdJJuj87OWmrquwCnVi7i/QuqUYSSGigP527B3w9/X4Tncxe9b+mzvLECP3ZvMNk/i9iYl0+HgM7/bZxLHXz0ifpnppLQU+7hMhL6l2pPNr2lU+pVC5YIde6lQ4fr6bVmeU0kC0P5Cbo9jS9R0911tOXDXtJvbWBUsn8KAdefYL2LDskH+gAPL1Renh/bhrN370m6IYkvZFJN9yRB/dR3Zw+iUU5pstuH+PgtJ7fYoseciQchmFzZZ+dS5JFoJiYMVHfPZ+kxdeN6jCPxtvLhkFh8gDInr+Gbqs65/onnYaTI7Wt1VBYz4DB6LZuids6Gt8HGHsBgcQW7RIkKVcO+yBLg/St1/M1gd31DlWqUc+C53mLfN+nTCbTwTRTXuNXbbRlBtBzHBLG4UW2O+QPi5gjjVYnCIKwkcb2WRFYd8ObRs5E34/Wvdyqb7gCio6mtZVAzHY4zbOiVs3iec4iQbSCanMmgmKgL7T7lB8q+eKVgFNDDsj1gyNRHNdzXkgCsT3O3NMlIJxKbV3PoaBINzme1ci6UY68K+75GXDyMI12zNiLVmjFDhCca+CxSwG5XkRlMQsM+e+OTF+kmoJ0lp6tAoaEDcaNGm0007q7Wyh9Iowm930Xqm0pH0ZBXQP5kpDiVI4GkAXmnv2bao+aa42o2QjhpM8yIr8kcoOFGBbgR/5KY29tHcvnUiTqtYdQkigYjeBdbLRenMuu3nPG0wPD/TEw+n3sZdqA54VSX8xtUOkwAgm+7GiEbr1ALLLEeaCm8i8SvF+FiMVz8flreEhA9IqmkjH+fTDoTzjv8ZKhL0oxGtkpUJNhwA9a9+0tGm6wFNIn/2X8+Maqvs3rbJvll4XwXJ0iPhqvZDJzlz8+s/aC6pbjjJ7XWrLIAoqz9elsuS3mtzk+0rMZ521gwKPZkQVzYnNTygHoFY298Sh7s6vBshQQH8MKU8PQfirWZQp8XVNmubxnPrLrQiFbBd1akBS9AkXcBKq95D3S63e22KJbrfN1Exki8KyeV5I6RY+LP91WPFIRyMKWJyyaxovxh9gPHnTBUn6wFWomeA4+PgYO7aLVM/FdutwQUtGwp2KiB74sADvXAhtFFUXv7LaFFhQkFkpjNEKxAglgDQjVgigEMQgkRCWSolVIQH4BCeIHJRhN/CNRQP7xC0K0KQJCQZRCC/Jp/CEVRDACLZRvwdLtfpy7nMfefX2zO7TVhISbbDq78/rezLz77j333PtGRQ7DYCz3GrgoXY6Dn8+2P3saCZuGoJ1N8KBYQ1+na9JowqUhpQ9/0WDmGwq5sKHsOUtbUFtZcSZ7uYA6Lf6j58OhIZepdDGY1Gvy38p8FYPEMA7xFO6V+mQepiHo0GUIEI+TvCQUhIFB3xgARrX7yUBzstJvx7lt4nc+LhbfewpyiD9vaP0sQ/tnRJugQJorcf5FcZ598YNaPy9q95UDzrpYwPISUL/loi2HBymG+78P4YRqN8PhOT0n2lQD9b4rxu1GkXT5UdH2Z4dx3cgY5AR0aULx6ykKobQzXOESIeOBAssouhK7qbiYZQBcOr3yqXZRpwCuOGBcLfpi8LUTx+01NlW5+gzB4YfEsYrjtmMi5MOdjbYMETojXktBXKYHvAFcXyquwRKLMAD+fxsC2pXa/1dT9A6bbCyArehLZb/up0hGycJ9rQIlLRnIT3BNJejre8S8+dq4Zym6XqMXxi2Gkdgv4uULOhZ7IrOsvq71eoyt51KZX/sQYVqhIUpxbeluEA80qCc9cBMSKHZXfB4AqUzL3YDfCyi6UGenFlJd6ZPYjr/J2niTBLB+KAawtbDY1ENsI84Fcb43lGYqoiEpyQ4h3iMUnW7dJIgQxSWSiHLUZ4RQovEYew7CUZ0bqHYYd7/4vkUbN0w4T75jj+6VtlwB3j5O0fU1IRgfCwrnRnJiudca4RqPigdsqhL4RVBxVoyP2k/Xx9BHx3q6gljjrW4gtlHl0mMdzpvc19lGuO4laPOgw/8m12dcJtatOZMoEFnes6DcTEKNdIA3Sqq0hamKuAZrSqigwkxg8reA77h/pvaK4hFKTP4stT95+D6TouvWpQVUmdcQXEwhzL1awYOwgncJUmke8NPEeirbEYxXBZzTAgqShIi6TgTOuwtT7Ifvd+diqkAZqDr8IjB2bE1bNmCRqPr8k4AxrfBs+NxGuCg57lb8Pt5AqLkW3gB0cvQC8tYNxxiGcGI2V7jH6VqbNMAdRSYWg+ZehfspvlJv5bpoLmBfsNdd1ynxGEYED16qX6mUafXXGrBh2K3M6lVCM3ruuJzu8gW9tO9MC+r71TBbAe3V1OMHysvcd6kG1BOkrBXDqbw62Wmc6kaMFJNx/wEX7eo9bpIVoqpxc/V0ny43gUBlSNDPoU0NAopbASOaUaRySi2qVxEAsXsfBeWMrXQ+e9oe7+m3LUIonPGv8V/K+IeRd1BR0pe693gTiSva+fzbG0Phv7GWeI0viRKTfFe0JBj4elE4w6lJv58T5/ZYzvkEGt1pL72fsyXcHsCZrWI6Tq+D61ololg9ICH+t7QlT9HpmiT7vgJ0NQo/tcKHCig7rZw04rkAlisLAVM8aQocvg3RrXKlHvSx20A+K+GIezNc7MeX9UEk+XVJhzvhDBwXIfE2hht5y8SBAwc+KSwszA2jW1v3i6dbdHtrL3mS/LTjSDoNXjOIjl9IoTFdfqZ5fb6zzbsnGsXzRLIy8cYB+4dbl+TRoarraHiH/dSl1UmamlUaPu20ozC8af/9CRS0G/lt17Fq4Doadtvv5Pclmgg9tX+F5WsEGV8gumU5H49FZ4afvEH6y7aQ3x9Lp7zC/uS9CpTRH0igAO/j8SU6eSSmV9oBu6+FVeVcFm/zOwZXux+uVyUzP4C73wEmQk5tUzeKrCvdAjIkzdiiVVRUbM7Pz3+kRTJVPtDJQ8vHe6n2wlWx6BusdLp8VJZJT2+JiolULcLZOJgvnmVoDFE0U7GEGWfGzKcUj+uFkoqIdSkU7ziCiZmwdlJYYeXezB5QSMf7SygoKMiqra31BYPBroFAYJbP55tqHxfZv1mhUCgRFo+5mr7tUq0Tf7ySQLV+Wm8r3ACHPplmeFszz+fJuda1M7g1PYKa5tB+pYHGkJMp5SIIW7fSnCIlnCZhAvrZkZllNh700MSiHDLQGgvJOdu9+39YZFt1pWbPsLO8DfVJP+rm/xW+ewnzuI/M7w+ZgGDoUY04li9OsZzglpJ37EBhyshsD7VMptCGvSH69WjEWW2ektDq7nZWOSLEy7ALD5pBZYWh7/MUeZEOYTIWgZL51tCeWfZS8VslKBU/cEWGOPcoLJbuURnoHsKx3KMbz9KpPbamZ8Ovv/lNRnQJVqii4/LH6M9z10lLF8Di4oh9jQFmEe4lQev/IkB6rPnhgc4Z2lRQpN7GlC602NKFJs1WGwU3ggOsMrjbi1R325nJcvXX+Lkf8X2q4Z6b6YGl5OnKMlpbtGiEl14f6qXS5xPCFWL+uYndF+d6rXszLWbSuxo4tguYsIHauRGawlkU2Y+x2bAKFmkKNwdKUIloqANFCpdYVhgoF0sonCJ+/3KxujtoCleBAER9NmkTXs7Uy/SsOobrZqHccnGeFtmLBI1cV6+l0Tk7lakYB4vD479gaKfoqjSqW0liXY6MItLPwZr/Y1A4JpDXa/0yuT1fa9dVJ6TFNfwTKyMxv6zCjlo1zBkMkpV7l4ffOWXi9WKV7RzWXXmciddtv2nvYhcDXnND4cQT3UrfCQWRH1XmeAusKf19vrnJvVqCYmBZDJzHbrdEa69I7HsM15SLv0ywTsHxa4Z26h1dHzvSJkk+Sls8yk3pegYUWKU8e1Mks6TkFEXXlilZ79b/S6Vb3yrFxHY5KpkbbCFXhCI8FwJwS1dwEBhC9p8jHsAKHA/V3E2+5vZUDnMAJijkklRlK/Km+P43GPfDUOyXcaw+zXkP1NrDtzj1d5u4nidhBUw0QSdBRpPDoh0siPZiQ7vKOFmMS6a2pgm1XZYXS/HYqh3AHAyNwcR0c7jejPoo3QO7XkgM78aJgQ9inZNbiJSMxe+yInIURRLX7+F8e62fRGHFhojAoRIYTeFFNXGqXJaFk+DfgKScTNEb45IEZ6Vb4GnoZyCURL3VjWeJMzNlypLZjX4Z/V1f2n0iVbemHhHNTtdckklOYcwNVHdL6TmKvNnyMxynGtotwLnaeJN9yla8Lw+2dzrd2wX11xH4zSSfu1W6fwVg71qAo6yu8NlkN5sQESYRI1AMUEOQZwQxiNAQtEpUEFREEQWtWKyoVAUdbMtDHfoY5OGgqEWJ1aa1Asoj4zNFDSDoIKISUR7hIYiEgLLJJtndbPf8e27+89+9/2M3wcIMZ2Znk927/3//e889j++ec67r/1kZlmgCMUchqDMsz1AzqSGUDLV3P9cSmWHN3pVJYt5bnWT4qqgztWtJxvgVGaHCw8S05PZn2OSUpFnNvYBguHRy1f9h034NtWt7kh6ohGy6g8ybfJ+gijN0csnJIr+1pRhO0E027Xue5IcWtkANs9GGwWlWeec0pUM2tntPMBanUFGHeBkOySxJ+cGf4aFFsYazJAflTE7Ez0OoWc43+Q5jJd+0+f13iTDcKyZt51lcB+2vPcx7MguYvAH0QkT4mgTGzeAkgjewJCDuDogchzkEDfAgwdfAWFyDr650us4kghlEu48ZtLKRVMQB9r1cDBihlUrFc+Fv72ewwtsEr/C8i9+ZjMFq1g7HLEPRBj3bXazdW4r7riMP98+S53p/MxgO4w4vNfl8tsXvBoLD+pO8IrPAzDzk6vslrOVbYKVl2MWvIdsO6DdpEhQhXHYefYDBiplSX7oTc/hpEnGi5ejVp8mj5ahhDeg7HCJURsR2qdogIUrP9155nUrxbFeCDmzWQiyYLIIrwwq4I4Nhap3pb6+0uPBvkQLAt8cKQA9qlcfT6X0RVspOwEt9nvr8JPssm+ZCxUy4c4J7qpgTMTkRG06sDjm2XeSwj5c+9zJmOxv0WuMihl8EYk4jZttH359D75+ZLQSCS4qYZHRR/+oZcwn1KyblZYiNChlEbThe9wD7vg/oxQ9WMbPibSYN0+l7KxtXhOVngo4VZtOkAGM2kW6fBjomKZyxFMZsmWw8R8Zx32OkFgc0tQi6IS3NUXnhWjAmUgNphZ2Ktig0XqB7TnYqQmWGEzsEl0mf50iMJ0hsh6DUuZiwNHwheCrqsfRlqlGG6PvZ9M8rveO1ELj9mtSouB+qAVGA8CO2+kNg3Fq6A4x7vAiw8mI719H3D7MV7GPf/wdiSwwL6ir9L7afsFbAEKaajrN+X8xsYxxLkZyTTxKLq+HlJveVkf7+7L7Rh+79BQTrHdWa9UNsYAFqgynSZ2FCE/Li1dmqvc5ttOpvI/Uktn5UAy0qZ863uIcomfKphaMw0mF/JzD1a3b4Ql/GJKstJCgwiSZTvkWf7wJn+7k1TPJPZQvMrN9XMFNBVdHlIVAXUJL1pI/dV6P9vrN4mYe21P/+YMwQAzJD5D1elJjl0nxhsvviOHmtFzoeKoYbQXp8GTHcw2z1m1F/C4OximwUs1DO43F0Oo3ZjWblegLMHrMLH92fgGFdl8BvhK12FakiMwatsFF3CdF7e7MhjPZbtBLicWJGH8FOfPF8RE4Ip26SPT8CYqOI0HbEuLmhpFV2EA+FyN68StjAKobbx9RtIRO1qoHGC+eSirMbkMEmn4+LY+zeIXsBH2y6RbsuDq9ntki+J1XihdiDQiYlMOeYdHI1jdXTFu2+JfMlBWITka5PlOEwrbDwjdGw7ro3eGm7dhB7mMnXxDwe5uxVKSQe2rcCKH6W5gS1wUpa7B6y06tI9Q63gkWAufRlzNBV0SiG38j0Eol7vPEHZHvNlNrcDfHVyVrJnJB06TtRLW1CC+B2wxgYKpsgTyZwvaX0vkhhlPcCPSJmFJtU2dZekujD4MWzW59Q2Wu7Fc+TI0nac2hxB8lbPYdgqjAx52SyidHexUidGTQ/08l232yHwwmu5WQW94QrAgvktAG9NshckpITqZNVoFeSm0X40kwy1p9LYPx6M1vlVbpWKeiBmKtVkivTWxfPYQgVZMCLzHoMhS8GB1EZFjSEee7LaCzeZU4L/r2dnqkVG8+XwD7l0JLap/nhlSveVT1/H2IQHkGzU3JEbqR+uMnEChF/5JJ54IpH6lvVMdvGAFYruoUMWiF5MDSnE3lkKZL6+oS8uVm0shF0fYbZXo1sUQKb4HoJ8e7C1PEsBp+0J+9OGN8BxKAuOPsnODhpqZZWRxWdxffBIFV5xpdUs2MM6OezTGeY4DATY12mkNT3cnpm4fzMZI5CBrM3x5PXL8ZzIv1dlMh9MVn805teAzo5UWU3loF1NOQLbD5EkZtl5DhUxqtNnCdMN2JCsb25IOFvVsZ/SyUfm17L4wrD7tuL4dzUuui5YckhOOJPg/s+LIBVlZ0hK7Lyy298HUTyYaWvNeS/NlYrDq2AZwLQQkfPxDEGKcQMCd0XF9uqa9bC8E62TvVbZNhfCOpqDCMIjztCff6eFj06GLgrJKpgLSPVuopszpAjhsNATDqpGsPNIe8XjXBJdgje2OaGqhqXlkidmU7nDtbobU8FauUOagWz/zZoA0y4cHtSIOjme4OVJGq7uZND4TAmYDcmVXJVuSfCdBe+Mj6aW3saU2M4CVYUlQpmc5PqLIbYNAAndD1po80k0VBTXULSD2Ei3A5FULyEzC/EAC8nKT5HyXDhyGXatwnDyN5B7ZINoahEE3X5tcauaHY+tk32pES3CvYDbNwdzeY3W2WY9ayF8sYRAIiqjm/FYDZSK2+9OG1Qfa+6VAhPmxf5I1moTjkdUJV3nc2hAQwhn1I+BJZszWsqkX86EqpS7bDDaPaW8DrTyfa9izkydnQVSUAXmUtzCXFYT5oMr/0VMxc4bSHzqik82j24awgOHHdpUiyjVVgrCcHVKF/nyGjIfJidH6L6EH06oFHqg9Kv08HXkGIo1dBQ74UDk16AjmedgEMnWsPSih5QvKM7HPSlQy0OBDKV8awUQKkTkUqwa+Iy+OeOXPjwYAftrIE5+R9rmfyPrh8M87b2NfwGmbpdRG2uGr0CAnWeZkoGFzx9WTk8W/hfWPFtDszYeCnsON5W66sn8mwu12kZuBJgNlsavaNnKWrCccLdg63MQfODnu8wl9T7eoJ5PAzOUVE/ukYNOY/FVqUg7qUf/JK4FF8ePNqguLi4i8/n09TT1EKA+WOTNW70Rxhl2obLYPHWPK2PwQcWQGPQaKxiPZEklFz4ijzG8m+6wY1rr9Gk4JxBG+FX5x2EgvP3N5UvkAshI6M9tS0Ppq8fpDHB4I7fwZtXr4WMiPQLxEq/uCWcTFp/cRFFrl0eYf6F2/pq9t+pTrhwZ1+yGaZftMXMO7+PYBqBQuwhR2AogfznkfOC+BqW6hKmCU5oWwnAHkDtVLil0YZTMBy6wTGHW+NRrfv27SspLS3VgNqCHBese9StOhYiesh4KMnMM1K2bwy446rsiNs1Xdv8GJHCSVZwR7MZTqaPDnWA4Wuu5bgLPxjd7sCTkeTtroHYQz9bnHA8n8jfBNPyPrMaozyyuXDn5gkSMFOYp4zQSQGpzTIwT2zH3SSRTdfbCcN1JAwmVW6UmpoaKCkpWX7kyJFbruwRUTlj3XBBO1AeH3SKUYsznMcbANdTv+f2XSrzNrF8glUQYj15nu+C8QiiliK8NkbHbBBIATLdjH5b4E8DNmtSzyHtJKgG927F3u9Qcg7k8987ATvph8biHrMFhScBIVVEXgciUixVHDqN506h+oyozs2LFi2qiTDbzR43LH17qhu6ZGrM1pFQ5kUE/GXZPAR6McsJpJ3sYIcB9RZui6wgBLuXTftUkh6Iy41u5sSNJY9rLXl3TVtlWI9t4dB1Zr9bacP8KSd5gY0jBiniJsHjm/IjtnIwnuuMINVZBsbgVJnZhkvMJnYmXjKVcFlZWYMDgUBdOBw+2tDQUNvY2HhP5P/RoVAomYrcNFVD/2q2G3IyXfxcBpnqIDZgEMX0Yyb3V610RNl/tGBIjOyVt5zk0lKCMPTnqTgk3DNgXpYV/SeMjfNHpdyDESlXL0s4fg+ZPmS7DSdLwmGEz8ugFwBXeax2VEoM67KYO3Qq+oMevX0vA/CBnIp/MxtRl3CHDx8ur66u7nvs2LE9NTU1h/1+/5XBYLBPhNl6cmYre0hjNjGgXgspwyfzHQtmQ8JIguMSs9XYSD+5dFSVCbOBxGxOBpozWy0xMjBjGT/zRqWcWZSRaVDBEBsQGLe0dpN9186kHUpazGLD7cHnJObOBj0WLp+8ymj1AaMq7U59nE92WTUYjwDAawjv6w9km6WQxhGBqhcxMBpVpxyqhPGUC5Uqld41dPm6vkkw9fKkF6/tkwReN3cYYHFhrmuK4vcPUwcWSJ8XEWr9a4kxMoipePVz3IcVkcbV0nV+Sw87RvpciHH8nIeq8+MXR8XBbOeBsTjPdMKsBtK1uNrQgNOJ3Stkp0joLNXBLJMYLCHTPcTI44ihMPTqB8V1BEPi1hpuD95Nky4kJU6wiGR+jNS7thVV1GUPBKPSrQ0hD38lp6AnzUkb0KOLsyShsZrGYS9heFMVc6SiMaA47UiwPkaefupb4IEUNyyKfHif2xOdatcdAbzZpvCLHgjUxuybKQ81hOj+6wAwhgnJqqZWUr/p0oTgRPAICUSu32P/55Ab72JYk2wjLQRjUolKpZ5P0qLIoq8uMG4vuTS1Ou9BPMNKqNSfSDK3AmMZMWAAKaq6VUyl9iApI5j+sOTojCbPbxoxiY8WWAN5kyL0ux31AYUCbjdhtM86+j5wW7cd8GzBB4mo6K4QexzCEpob+UR2lSmBDszjBLP4uIQ7W+wk4MRrx7lEpg+rX9Yv9mwquTMZmU0MHPe4TOEridlUxrScXXSn9L8cjvO+Qmrwh5ymuMcjDga1TpLEYTCW7sKXHKg5IFoJt1FWiyK2bw37PIMBpN9I1xHM5gE9oNTHnkuMmwjRb83mYBfoBXt20mI9yDRAhQ74JgRWd6Z7yMGWNytMnu0m19hAgsInq1S8QPLeaoVXEenrDf2S4u2s/ISVijbynl52nPeQK7OoonedxNqFpHYuckz4S/bOck2uJfI2ecK4yMa6C2JPgRFmRNDEyRBSAkCdvnkU9EKRplT2Xad464p8TkAwMrR8VnAbiA3TWuf0woKT0N66aP+xsNP2diRPtKqklGxjvRUnw70n/T/eBJeyI6+Emq+g1S2/stlrpcIYFyTyJObS+0B6l/cuRc7BFgssDBiI+o1JO9s6L3tPtIYqv6Nz4sU5pDNo4cnh8H8E9eb/6ngZDgel1gGQ6xQ5TAdjHF0uGLOaksCYKPyDQmXKR5fLZU1xL/BL9r8Ke9vuBMsFY42468FYE068MOphNr0ym8R/LN1M77jRLWpxfKJo9xMDVFU0WHpus4P2bOvgoXTr+a9b7CJg/MzzXWvSZo6J8PghXoZDsb794uwWizNyQeyphbtI9K6A2DipXAVT9aJBWEjQydWSyA8q4BBxTtcosomyHPb3LwroRWTy54Eeuj6RGHtfQ8BtxnB+Zt8KNWiWgHSUtEG+9Pm5BEmFmYdcqICjRJ7sZrsHPFqXCodr0s2+ziPGtdIyr9JzbbdYHI4ZTjO4W3tbHIjMkf4vUEii2xkWd60EQaSSc8FtlBrQ8yFxcu+QrreAVMO5cfaVV2hqD/pRTJ9J9l5bXE33fjDU6hCTW6XfHDJpJ/A2DG6cRQ7GA8yB6MhMHuHg/IbaLSRwFRQMq5RyS77qaWVz22W4jVM4EMBgtR7xMFxtRoT5U1MMHQhbdM7se/lzUcrzC0XbIzTgcomwTqBvHIOCmWTDexl5xD7p80Og2Be2MBN20N9m+RuPCNs02ROAv2/ro1LNgpab4FTJzKMV4yUW00ySeAuY7XaITeggZkocZV6+V9EHpbM0e9NA8Ki3uD63GaP+oKf/qegdh+YLO4fz0iR4/tZk+BnIFaef7oHmJa+0OFVUZ0C/18c0Hd3UQtSL7Lkvbby+YSRNypxOchMYiCX1cYsr6I63bzgH8yE2Az9u+p8A7V0JeBRVtj69hkCAEMIalBBAQAWVRUEQWRSVRUREBQdFQXRkxB31zcxDcBxcUEFcnoK4ouKI4AIoCrLDyDossoOIokAIIUCSTi81dbr/om5VV1VXLwH05Xxff5Durtt1b937n/+ce+45+hDzRsLqKAQKJSsNhBVdQtGbvWeCTCPt+dhzyfpQcoVUyBknHIjcKjufVl4/g9JkAzHBQs6plMEwuBefzpsQXWu8TbYbLp/tsHavS7J95sD7hDb5/1ecgfNDTCzAzvyQwMcLBHrK43N2xXKqkAqxJfp6Qacd5IyMGK4UkJdg270pOpZEcRb8XoT97jV0THeo8Hd/ne0+uGJeV8gfQDgJ3gbdXI9X3gNhmHu6OxPLUGYz82vY7r442s0l1Tv5e5a+YLP98cDe0/ku9IohULE+KuQPIJzNk/egOY/bIFhfdp2BbCPzfjW7qVokeR8cSc0Jb65NphE73kD+ET5cYjdXmRfoXTmJ++KdhY4ASzdMRj4DuSPB9toAqDm2jKP82Hv+b5ugNIvUNLOxWGk8LJVZIe8LZ+M6NuU5liyRij+8c8F7m2dhvNifynF362xen4XreS/ZhXvYSMa7RUZSDdo/Vc+LpRbaVO6Jz7ywn3R9gtYAb2NehL7ypsKPGO/jCbRVRZifPN8PY6y3JtHfmmizvvAMt6Hd06E8ORETb7/ypgPveC2zcU0rjCk//5ZJWG1K8PGEZAHOLsix9AOq2qkVMo0Sq1zUhSK5UuxUR+R7eZzMkzbxPv6rZJwiVy/zyDzsj7dmd5EaSKLkdHnXxDSdrmOwnPxSDHTmQ1GP2hh3Bjw+KK+vy6FEgMcrnB3/LoquLmBXnsfEE7U5B01zpfJzbFw/BYxAUXzLSA04eYC0Z5+UwtuxhJXU7WS+QeTFfdvZnduO8Vlo8Z3LMI525jbPjxtM+svzYWIC/V2D/m48hUDHc40jGdvZADk+4TsGyqgT/o3HPOYd0FugYJU61SkRq5je0aTNZ82T8eYY7Y0jbQKEmXjgVsLalcMTvxMAjjUin1NqDA3XDe0oi+xBmM/P6dryALQOCADHgTicaLQt2mINw742Zee4B1lvhojZjJUNig/BVvXxu8wy5uCz2QJIPYF7/6sAcJww4iowFmYEtwrtnQX2WEba6DOJjLMrH4Z5kYv2+MiyGJc7HIupPUWflWPZD/8Lb6pwVCH7U8W0Nw/hd+sC1I5gnBWAY9Y4DCCcjef1jvC8humYvXiyVx+qoSz4vbjvhmizE8BBeQa8KfQD5ph+QbyG+fEXYdymUiTKsCbm2XCBeZ2D+ccLUx941QxjtlgAuO24vgna64L2FeZyawL9/QVtNkKbnTC/SwVrhP1kn5sCQMgZzrqT5vHHk//VSpRAwljlHV8htXYRu3hi5bbgefYmqb5sDl8ej35lUXRO3nIDuRLcsBitx2GtZqF915O2PDJPhAFkHah2Gxa2UlLmM3S0BVjdbkyw7/Bdvt+egn/wYVKLailn764U7r81TN+/QRNyW5sAxrUxofYnMG5zcR9jde8zxe6Fz3rDN/ElqRm2g+iHUuqGgSIfC/o9UmsSfCiA9hKyPpI2FiDwGtrJhx/1WiyWzRjXi+Fr0Z94YMDPwSJlBnkQAN0Di5+1+Ue4t24woZRJz/eWBlcAT9o9AFx+XkPwvIZSfDFqEp5hLubAT2iTmcT9uH9xPK4D61XYGwOXUi7Hh2eh3MdCzIFdaLsFxnuBYHZvJrVIyCC0p2w+rUV/m+H6XWhvEdp3U2KbT/3hw5oMM7oA/R2F/oon7vsI/VWdwTKoZaaX0NSuC8KdTVE0XYkNnGAT9c+C5WJ1SFUpUrcXSlMp+9SX1LxxKRerm0/DYPfWaZ05FL0tfA5p66EX42FYUfH6FJ06oC9F13vXv+aQNvr1EjClJ4XJyMywqQ2f1I9YoIfKaXzvA+iJ4/2OjT4O1LUzBoxGX0NjC6kVgIykAP27DiCvfxbfk3rqzEh2gK0MhFZ/Q/iMmV5nip3neSrFV3uCT4x9G+M7b5E2dYhSGfEp0h7t9GK+xBrvbgbukDY6s3IR3ovV3/dJe/45lrAC/jTGd9426e9JrRAKuGmKDHCNso7oM0W4YAY+R+rJQrtSJIC/mSgZMEoNLCtFuuE2H8Y6dQCoi+kUiJ0jqAvh/xKp5jcCZa4EzS8eDx1C5kcsRWBMVQxNJ91EXUU26shCjlAcRy7jlJa6uZiM7/Q8Awf0WkouMj+eIM2muuc1LY5rF1F0sRsr31O8ooztBQYLMBFJw3wSw4cWxHH9mlPU35Od5KzGN391Dc3dnRfJFar1+U2DTzUEtn6AjEvm6mW54FIyk//A1OSjOUaB/o1IPaj5IHx35SGZAM6AwMRtgxzL06TNd9iB1IpSc0m7WTCGDBK6GshB0qaPeUfQCvG+rtAN8Nlkf1PFYWGCJyv6h94lwf65wUgyUnx/8ezaHSLtblmrOK6trwMMK0km6+p+3eJumuB4Z2BhiiDZ5Azsr3Yhu0LU64s+NG9PLnk8hrrve/h7xwHAFsRQBMvgnuhM0aW0RWEAvcYET7qACJVaKFUHGPzPNli32WsN/q0MLIkb5FjuIu0BxxHQCl2E9z6G6WhH2Gn8vM4/97DNa3kCvUvaI+9P61iHXc07lWycNE5QxgtOWAfMksY2r+0FP1cOnRnyA2lzrbJWHmnzWc0lezuIyQr76k4IZhrPgVo2rx0Cv2aW0F8xmH0wGafwMurvl6eovzqgk8jhCtJVn/elDQfqhEszmcgEmLBd4Uc1U56l+M52AMcEk+/VBLF4Cn7F0WDCmZgz54LNrwYQjReuvR5APxZz/Q34IeNVTLyuXjZyJ8QDcmW4cdE30EDnHxoS53MZRWpRMcUxye3fbvJ9noAvwdfEk24Wvt8AC6m10MnLMKCvUPTuUDp8IYEE7jke4Ris5qQmvOHJsBNa1CyR9sVYYLxQ7oB2+zAek9dvXW4gGbmTtJstE2HuG2W3ykMfCsAeToUcwFxQwmTOgsUwh8zr7HaFIuLFyBsWhwXf0kM6xfss/FR3GLSTCyVWgP+fcikr89K9528i6b6J1DI7P1Zpiw/wPBuCpTc1+d6v8HPyhPqroAREOQwX1mNok62+QZgbEoDrFsFq6oX3F2P9KpEbDpCp0lSOi9MC8IwAsICMEwbxTXEsXYkNv59+9f0DoPMB/q4OdmVESQ+TurMUABhmCmbhOvhTRgqm2D3CYCuvYjhAlVlwTHe/Dptj5LAxZiUArnYCq2Nzf6NJHzn+S4kU30aq419p3/R+yvzecKWoDQM/pAmdlkYyQETfryNBJafIaJgEMwVfyHsG/dhF6qaLT+c7jGdMzcwbszYKodV7CH6xawB8RuO9QABhVkZ1dIyNrQ3e5VbiH6uSNvxBee0hNZ9TUOcKKM/+Rp69L41Gt19JE7ouDBd7sipdJ8gUAHslsLW/xvj+CdKGILmw1nZgDBTfPe+eDsN9L6SIzzwfZu8PmN8PgojMB8CW2wkpMQtJVUxKL+jjN6QmmNLLRfDJhNARRuQfTb7LGr0jvlcExmV1RIwp61CYwTmkpr05gon0FcxiO5VZvQCIfriPDDC9nzH4k9HH+mCp/NB+wcRXfCXtQLf5IbKjX0yXyIudQxSqAOi/pNgJsggP+3awuRoYmxJo1E0A/BUmk70LTINgUHIsDpZ5f8qtcYRub7GFRrTaQDUrlYTT2njcQdpakEU3f30V7S+uTMdlwCvxpTldHj8v/jpyQ0F5ISygkHN/zcrF5HEGSRLWG5e747J+fJ3XOuVhA2jvzhhHD5TGTvhmp2PsGNiV7HjsG9qqm3dpuG6ODU3ON3o5WEgI88+qgOfVYP7NAcqKojsIxciOebshDDlgcl3RXy/uexcsiw8AcO3BgPT9rYL+pqeiv5x5pKonQNN6fE198naT3+9OBAfqY84rO9OPgbXGu1n2HZ6/GNvJgLYBfuXNAm6wcGiSknHy3xS9W+/E9x1glL8lC3KmIknKxLf+DtfBzKoihQuwHjruOFmMVRR9DlinM4WhzX9Q4RgoLqoVTvTPZqg8sdvW/Y3Gy2zt8ob7xGKyURIuncg5yDgDtXzttiM1yBc2YxyUU+U41cw4EW6Pn1/Uc5CBckt+Nl07uzftLMw0KqtdIadJwuDmDtBHV39FPRvvDtfvSpF0BSlgxb4fPna7p2RaAtA6kroz2xq+OAcUwfkCqOvLIt0FYJtE1huHKwHEi5IGuTBoVZbosiZBSpd/8pejDjp4zEFHS7nUt8xx3diKSpOoVU6IsjMkCgQj8O+Rb9Un/3+/fE0w5CCPS5IXHFHdTDe5UG6aAW6dbMAt3x35LJnS56EwCEhnVPl0zueVTJLDoOSUtXQZfXvtZ9SoWlHYx1LF46eM9FKlPCgz0zVgU5JO8zNjFk+fMFvpb+I3ZGa+z+w+PJX89N6mc+nWuTJp9frI6wxVoMzpBDiZXU/uPp+GXbiR/CUevYXwOphkPgDDD5/YHErsnK5dqQE22BiWRiHM4O9JDaUar3MF6GvqrYGbIRMWlZHFxyA5Cn5gB/o1kiyOO7pDUjS7YvZ1Xr0QXZwbDIOP8nnzShI1rwON71AZ3snBD4iaJvK9nOraTMFuFzM8FYlaywT8kkYO2ih36dttDgoFZWBwBW2DA/siWtU5QFO7f0uFvko0Y1djmrWnEf16IiPMUMgRKVjNhavDjg2HlDBzjBT18cjAXxz2eRRxuQTxPmVQ83r91LnefhrYbBu1r/srjVvdjt7ffB65vWWaSuuxNg6kgIcy04tpRf8Z1CyrgAJcjBthAUqBbUg6GSdD0GcV95BxHT9/LL8QV4If1HQ7DW6+hfYdq0bTdzShlzdcQHuPIqMxPy8e4yTGtkLsz0Gec7lVi4wCgBZTdOYPD0xoxefFTIs33ezGhmbDrPYZvM8nHW4RzFx213QHwLFJPkOYcyt0ADeTogsXOOGWKrC4H3bn3IpXOhjdVjC/RTCz54k+Ucc9dw8nJlYSTE7+f1BKuEZ0OvxeteDA5YHgHcXaXq+3WVFRUf7SpUvHFRYW/iayxVJ5meVkOui56wLU74Ji2lVQVQaqPPp4R1Nan1+LgvICd8jU3AMGwUvJX+alm5ptpTdljVZFZjtieuXw91xA2aAMRmVplF9SiY77vXTE55X/9tLWwhr08/EMyi+NAKNPvl5Jnq+AGcEEdHoC1K7WQRrR6j80uMXWSN0apUKXuIvJICb/zYCkLHeXUwpf/8LqNvTQ4s7klH9DLF4U/i2+d/m6vMxCGtFyI93UdAflZET2QmKkjc6AI9do95InXB/hb/ZjDjBhcudRHLW0T46xO0Lbj8tjyH4/NoW5sPvGwzVp1cHaVCArIInvX/6uRWGCCkmAyT3RfiWNvnQlBX3ueHbSu4JNtRbeWwr2N5uMM+B0gB9YPBmjVIrzGbA53pi6l7SbI2NJPdqYCwZnVAyDTwi9lMTQ1IaZrfSPN+42OYYPH263AXaw3gPktFUaRgY2Kikp2bt48eJ7d+zY8YXWVySPRDcnPdTDRQ0YBoOR0odR/iQGKxko9hdVo5m78+ijbc2oX5Od9MBF60gKsSnsTGrCKNHiBTIre2dLC5q4rjX1abyLJnX9LvKYGI/4d2RWmExYBrMclzdAs3fl0bD53WUAqETdGuyje2Xg7HHWvnBtcUkGx0B8/TltIBdzTJ0RBk1pEi3bk0OdPhkQDlCtYHqpc4UEZbb/TKclNKrdagrI7F6KzzNSFb433gXtZMLme8Ec5AD/VqStBsSmaF8AWkeDazcD3JTaafVN2JsItl1g6vKpCN7QO4F5zJEQCR+9jAVyvLP4KNlLWRTR8B4PlZWV7Vm1atU/169f/6Zoq2bLS/IRGdTu7+4kbxqbQYmBBTvhpXKaPLw4GcxC5ZgfPxyk6WD/pSvclyTkjAQ5vaI6KjOPrrP60YZDtchjzOj0Ka0I7OLuJH+ezbfLdAvpsj8U2MlKkV/PdFxGo9qulo00802oJOU1PI+PAEJ2cgUyGRoBH5pVUbYvSD23LgqDJ+/QcxmzhRQ52RRMFuQyYGczbbQdae92y5Q5FPp57dq1q+VXo0AgcAFs8F5XNnccmfeoO+L5CbH5VaGFUyhnPMgpQFcqL7y2/7qRtsimrIHpyiDHcYP6o1McS/Vigj/7LEWfUFAqx/9e5DrSFmPng/+GyQtYKQd8adT3nO00o+ecsJumHLaHLoKiEH3A7D/bCb8dH+TnjYcsm+0VoU+ximlyphw+TcG7vBeSNq7VBnFxOlmzjZJBqpckhQlvkcPhcMl/H5ZfZfyS/z4hA1cZXn75a0GZrQXk9wOHDh3yrVmzpr7P5+MMDeIJiA6tGzoOz77fPSNUTG8EpfAE4wyjd2HxWZ3t4/gljjniXSG7B5gvh6bhtmMd/OegT2aZU+LUDJ1gsvcmNT2UoYLFZHyT7J3jVaQyxofjsMxORJTChBgPRSKV80K7Bvd0FcWu78iA+RlY2BLRtKokM+Tvb/gXdfy0P200Z3R64Wwgq8W2bMpQsncE60wX/RwzLQzOcY0kj+kDF6wnlzNI/mBK2Rwr0R8psqHAivIA1mZrANrFcbb3HRgen5KaBj/d2xSJWzWSf1LkSCkrbo5r5N3aErs/preVGIQ4z9n9MWi/pdTLdNC8+1x0/lmOhExSA3mRjLMSZ2OQktHODKh8BGW+hTPzY4BoosK7PxyUbBZwehV+o1oCbbPCdqaYydUGg7g0yef2LX6zUGR0HWYMoI352bLZHojF5Ahamyf1Xpu/2Rrg7zX4LB4m54KJ5afU1GBNw3MqjUMxDRB8WpZMTtnA+qbvLLqi4d7Ixpk94XHiL7txj1kwDznwuA1cVfXwXU4jxUHsoobKhBnJwfQcAJ2H9oJ47psATIuwxoIGiv0H/B5/nzcOzKpidwAWFWFO2MoFqV8cHBNgdMZvny3ElCFz8m2uX/e/6KZmtWwD3G7Q1YMW33kAlFjUbKPhjLSatDxYa8k6ZXhtTJzvSVsdWgHXAzEA7iAektWAN8eDnmmwkDjTw1cWAFeAyTUStH1JjGeYrIxAn80AbiomonL8rRqYp9HE5MnPO3Z/URhdZY+fpnadL5sQQQrZ24aoClZvJ5Q/E0DmTaDfnUg9QC5hIbPju0x4by9IgB0ZSdpylrwaiqGUlPfmmQD7B/j8YwOQFo+S/UP0zeVWL6JzswpI0p5ZVY445mPuTIRPbRReHIz7FtjVctzTFKw5TkT7BHyl/LAGU3TgSjrucwhFjsBlwpLiecGbCD1JDeswspqKST0LzNcOsxjTFTCH3VDK7WyZq7q/D8MJSFkyvu55ykPVMsOPZVWY7ciPx+eT0eaQRMt2SzRzfYgWbZOoJHIQY4Ns7HbOL6SjcAb8H2lLx+vFzLFsxhq5cw9h0Jkq32nS7gkA33KDz3jgF0BD6YUHjM/vtcCEnG4xoQvwG0amdANorHNMfCzLASAKwJllQFkGza2n5eME83xeggvaysx72eQzHrfuJkzrLbx4980oAeQkgOJLzDba1P2Nbmi8kz7c2oK8XsMclIehnJTkk+yH4ZirvjHu/0udP+h1MGgrhnwbadOIKYprCdglM4wuUP5nk1rHgwHm7wZKix3zN+je3wIQOYjn3RH3xP3bgTl7NanlBgrBHp2kzWYSEFigRGpSy3DSzC71f6b6VY+JLC4TAPQSlZ88AgA8QtE1SRThcWpq8fwWYF4/bsOf9xPI2J0gJqwA+XC/zy6Tc0KLU93qDvLKf4XkJeYvoZZ+/tcX+cI5Mku7/RInfXm3m4pf8bS9rX34CMMF6R46OvBiJ0kRcv+qhb/Lb+FQfjqG47ONBdrvA7VebuHobEvmCR9zYRa3tQC4LdBsZr5CPhfbjMxzZzHl/hMmtRnAfQNmYeV3WARATkUUewAm41gLk/jvWJhWLwbdT0zaYPZQS3GSXJ7zayz2NkzHZK4lbfJWvUwhbSjDK2AW1Szm/gIdwE3Cgq0DoBoDlpGH90Wl/DdYF0qGG34WRwWA8+EZO8B8R6C9nliklQVQqAJQVbKf3APlpc/u0hvve2FaPqvpUHSwOYPlb+UEbpUB3IqV1cpiLp4Hv53VDutzmO92swVPxtj2g4viRtJmhTYFuWpgG3TomEQn/JHgYFNnkBQGPuebg10kTfFQ8aseqi8/vkDgJJAFLRaNmV/Cyl9RBrvf7K5mkr2dl/ctPmtnoIn15pqdGrSTLD7rHcMEfiMOf+KRFEzYUgB7fQtAWIZFbPU6bjF2NUlIv+11BrWnRaJ9xWkwj/boHNBGbOBu0hZCXg0T2SrJKG/cdNU9k1j58V4H4BUJ1sVbcHN8SuqG1x4wkq8t2irBWntSeO9hnYXiMfCfWaxHR3kfBE/DuO4H+6yL9dIU7NtIOgPsd8VYN0fgNjqQwH2tgELcZgfkskDvax+Sp+uqvZItT0gY7EojTK+cxRGDudS22Y7V945aPDBlsdqR3Bjg9FsK+hGi1OyuOtFvyUK5HMPYJ/o6IYAAuWMfcXPjd3uRNjPFNNImHm2nM8eOCkDotGAhYuwnM//ZNseKAexz3SL+k45FfBAHI5lE2hyN/RJ5gGz2v72pJT2xogN50lKaSOF6jI/iV+TddiU3XAsoFDOpR2rN4mds/BYz692pBg39JGgLR+KFEfqbVNtuSn121MpAbDMnP9vmt8Zog7fDX7D4/F2wNbNtEw6OviLGbzQl61z2/BtzY1B3O/U974CfKFlRdjdXmny+FSy/ahKvDPirwrI2P1t7JM5ctujMNsW085K60eARQL8Lxd5185G2Lmh2nL7NDJ2iOaqzWjLiHHuvjlUnJN40H41Z2YFGL08a6NhXqGya3AiGqeQi7AUzNZYwwHHYRw0AnJ2zskvM2FgqQY41JJ/+n5/m5rRJDqIzK+GEBzT/BgtTmNM0b4KGFaUJWMBPFmxsHLQJM7mbLNjkN9Bu+sIpefBJbSfzOLrHof22wPdiBub8+UQTP0YuzMdJKZ4HQ8i4GlUrjFss4L2fzHPwLz/ZF3kEM9Piov0ca/g/ugXEzOsr+LdEs9VOXjieO+IGC28SPWbzXgYoLh3IdJiq84T3hpP9GhivkTa49sVkHqTX66OxMpt7ckX7RICO58EqKPLGmOs3k7mP20yY1fKGSi2sB7tjW4MSC6OKC+Smw6EX5APzzWSjSQrSmSgrYNJttnB0LtItMh70QRZm39W6hfQ5QMssfKYDFpQ+G25/C78X7xo/rZvgXSx8FSNJjavSZ6G9tBzGdTtYzWYTBryF1AzNqzDGa3H/ksUCvQX36/N4ArRuf116anU7cnvjWoSsgMQQHGbTl+j8ZZPjaO8N0qY2HwNTqaXJ93PQX3Ez5ENSC1hfR2p4TzpYzLtkHsDbk9RsHaKpuiTZh8iM7n+XX0oT1rSOF+iYPDxIauhPItIe86cKLKIBcVw7iOzVDUkK5D7Cw6ab2jopQ+YigdBJ9pKK9mO9H097Sk3RehQdf2ZXdmCSsVn9tYn/5WyA5tIEf2MX6H+6SRuLYLIMpPh3wtjkPWDBOK3+Nnv/mDCuZvVAs+DaYLZ8kYmptx0L3wEfVfiUw7oDdcKnHkIyJjrjdycOIuMzk5zV4s8JPJvnweoVM53DRDYIyiSf1Di5nwXr4FeweFFp+vF5T8HHNhi+OSUTcb7Q9myBhc4Cy52VqoXNBW0+2d2YSn0e2ym+AODJgGwGmJsLYzs0zuvvAItsk0qQM5z4g9o5adpdLjGYtyEmg2RwLdvQRim/02HeOAyuC4EVGDGY6qDKksG98q7WTislBu2uZDZVfC1BLN49MDW/pcS31vn+eFeuN8ycTDxU7tNx/MZ8TOJEfyOP1BCTeujDCbDKBWj/MKlpsdMNxpg3N9boTIhsg+/x2Kyj2DvGOVjY7fH/6uh3APfCfjsOm/nByK/ESQm2H6lBbT8ZQCcCbv3GgxOLor0AIsPIOK9YHlwSLlKLGg8i42BkHrs3YQbxD35G1g7wm8Ak2lH0zuYWkIAXyF7YDs+LR8Bk9EViymACTowBbOwbfwn3UgYg/8HuJOLCNr0b76Iv+nxBAb+73M//YX6wdfM9nuUp+MkEQe629k56e6jrVOyWVsj/E2GQ46Nc7WUWx+nXk8mYXCE2Qc7voSsb7qV5fWdRIOA+VYjTC6x23pkyDv8F/yYX/DeiGCwAAAAASUVORK5CYII= 1 - 1 - 1 - - - - + 0 0 1 - 0 + 1 + 1 + + + + <p>This is a demo survey to quickly see some features of the items. This not a real survey, question are silly or non complete or meaningless (and, for sure, written in a bad English), but they are examples of what you can get playing with this module.</p> <p>I divided this survey in several pages. Each page is focused on a specific field element.<br />The four format elements are used here and there on needs.</p> <p>Of course you can even submit a survey... but I do not think you will never get a good outcome from its analysis. :-)</p> <p>Enjoy it.</p> 1 0 + 0 + 1 + 0 + + 1 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -60,19 +54,19 @@ 0 age_001 This is a mandatory question. You MUST provide an answer. + 0 + 0 + 0 + + 2 -1 -570715200 1004616000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -86,19 +80,19 @@ 0 age_002 This is an optional question. You CAN provide an answer but you can also check the "No answer" box. + 0 + 0 + 0 + + 2 -1 -2148552000 -2119608000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -112,19 +106,19 @@ 0 age_003 Here the default has been set to 72 years and 7 months. You are not forced to read this question because it was already answered. You can fly. + 0 + 0 + 0 + + 1 -2130235200 -2148552000 -2119608000 - + - 0 - 0 - 0 - - <p><img style="float:left;" src="@@PLUGINFILE@@/anziano.jpg" alt="old man" width="120" height="120" />How old is the person shown in the picture, in your personal opinion?</p> anziano.jpg @@ -138,25 +132,24 @@ 0 age_004 Here the default is "No answer" and the question can not be mandatory. Here you are not forced to read this question because it was already answered. You can fly too. + 0 + 0 + 0 + + 3 -2148552000 -2119608000 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>user ID</p> 1 0 @@ -164,24 +157,23 @@ III autofill_005 This type of field was added to allow relations between output of different surveys + 0 + 0 + 0 + + 0 userid - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -190,19 +182,19 @@ 4.1 boolean_001 First instance of boolean question using radio buttons as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -211,19 +203,19 @@ 4.2 boolean_002 The same boolean question using drop down menu as user interface and "yes" as default + 0 + 0 + 0 + + 1 1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -232,19 +224,19 @@ 4.3 boolean_003 The same boolean question using drop down menu as user interface and "No answer" as default + 0 + 0 + 0 + + 3 1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -253,19 +245,19 @@ 4.4 boolean_004 Still boolean question but using horizontal radio button menu as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + - 0 - 0 - 0 - - <p>Do you live in NY?</p> 1 0 @@ -274,26 +266,25 @@ 4.5 boolean_005 Still boolean question but using vertical radio button menu as user interface + 0 + 0 + 0 + + 2 -1 strfbool01 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -302,6 +293,11 @@ 5 0 checkbox_001 + 0 + 0 + 0 + + milk coffee butter @@ -315,13 +311,8 @@ milk 1 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -330,6 +321,11 @@ milk 5 0 checkbox_002 + 0 + 0 + 0 + + 1::milk 2::coffee 3::butter @@ -345,20 +341,14 @@ Apple juice 0 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>When did you get your last car?</p> 1 0 @@ -366,19 +356,19 @@ Apple juice 0 0 shortdate_001 + 0 + 1 + 0 + + 2 strftime01 946728000 1378036800 - + - 0 - 0 - 0 - - <p>When did you get your last car?</p> 1 0 @@ -386,26 +376,25 @@ Apple juice 0 1 shortdate_002 + 0 + 0 + 0 + + 3 strftime01 43200 1380628800 - + 0 - 0 0 - + - 0 - 0 - 0 - - <p>Date of birth</p> 1 0 @@ -413,6 +402,11 @@ Apple juice 0 0 date_001 + 0 + 0 + 0 + + 2 43200 strftime01 @@ -420,13 +414,8 @@ Apple juice 1262347200 - + - 0 - 0 - 0 - - <p>Date of birth</p> 1 0 @@ -434,6 +423,11 @@ Apple juice 0 0 date_002 + 0 + 0 + 0 + + 3 43200 strftime01 @@ -441,20 +435,14 @@ Apple juice 1262347200 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>In which day and at what time do you remember the event?</p> 1 0 @@ -462,6 +450,11 @@ Apple juice 0 0 datetime_001 + 0 + 0 + 0 + + 1 2 0 @@ -470,20 +463,14 @@ Apple juice 1609459140 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Please, attach your Curriculum Vitae.</p> 1 0 @@ -492,18 +479,17 @@ Apple juice two.one fileupload_001 only one file in a the format you prefer + 0 + 0 + + 1 0 * - + - 0 - 0 - 0 - - <p>Please, attach your Curriculum Vitae.</p> 1 0 @@ -512,25 +498,23 @@ Apple juice two.two fileupload_002 only one file in pdf or compressed in zip format + 0 + 0 + + 1 0 .pdf, .zip - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>How many days do you foreseen for your Easter holidays?</p> 1 0 @@ -538,19 +522,19 @@ Apple juice 0 1 integer_001 + 0 + 0 + 0 + + 3 0 0 13 - + - 0 - 0 - 0 - - <p>How many days do you foreseen for your Easter holidays?</p> 1 1 @@ -558,26 +542,25 @@ Apple juice 0 1 integer_002 + 0 + 0 + 0 + + 2 -1 0 13 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>What do you usually get for breakfast?</p> 1 0 @@ -585,6 +568,11 @@ Apple juice 0 0 multiselect_001 + 0 + 0 + 0 + + milk sugar jam @@ -598,20 +586,14 @@ chocolate 4 - + 1 - 0 0 - + - 1 - 1 - 0 - - <p>Which is the mean room temperature you prefer?</p> 1 0 @@ -619,33 +601,37 @@ chocolate 0 0 numeric_001 - 25 + 1 + 1 + 0 + + + 25.0 0 - 12 - 30 + 12.0000000000 + 30.0000000000 1 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 radiobutton_001 + 0 + 1 + 0 + + Sea Mountain Hill @@ -656,19 +642,19 @@ Lake 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 radiobutton_002 + 0 + 0 + 0 + + Sea Mountain Hill @@ -680,19 +666,19 @@ Lake 0 - + - 0 - 0 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 1 0 0 radiobutton_003 + 0 + 0 + 0 + + Sea Mountain Hill @@ -704,20 +690,14 @@ Lake 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -725,6 +705,10 @@ Lake 1 1 rate_001 + 0 + 0 + + Italian English Spanish @@ -742,13 +726,8 @@ Optimum 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 1 @@ -756,6 +735,10 @@ Optimum 1 1 rate_002 + 0 + 0 + + Italian English Spanish @@ -778,13 +761,8 @@ Good 0 - + - 0 - 0 - 0 - - <p>How confident are you with the following languages?</p> 1 0 @@ -792,6 +770,10 @@ Good 1 1 rate_003 + 0 + 0 + + Italian English Spanish @@ -809,20 +791,14 @@ Optimum 0 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>When do you usually celebrate your name-day?</p> 1 0 @@ -830,6 +806,11 @@ Optimum 0 0 recurrence_001 + 0 + 1 + 0 + + 2 43200 strftime01 @@ -837,26 +818,25 @@ Optimum 31492800 - + 1 - 0 0 - + - 1 - 1 - 0 - - <p>Where do you usually spend your summer holidays?</p> 1 0 0 0 select_001 + 1 + 1 + 0 + + sea mountain lake @@ -866,20 +846,14 @@ hill 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Write a short description of yourself.</p> 1 0 @@ -887,21 +861,21 @@ hill 0 0 textarea_001 + 0 + 0 + 0 + + + 0 1 10 60 - 0 0 1000 - + - 0 - 0 - 0 - - <p>Write a short description of yourself.</p> 1 0 @@ -909,28 +883,27 @@ hill 0 0 textarea_002 + 0 + 0 + 0 + + + 0 0 10 60 - 0 0 1000 - + 1 - 0 0 - + - 0 - 1 - 0 - - <p>At what time do you usually get up in the morning in a working day?</p> 1 0 @@ -938,6 +911,11 @@ hill 0 0 time_001 + 0 + 1 + 0 + + 1 2 0 @@ -946,13 +924,8 @@ hill 35940 - + - 0 - 0 - 0 - - <p>At what time do you usually get up in the morning in a working day?</p> 1 0 @@ -960,6 +933,11 @@ hill 0 0 time_002 + 0 + 0 + 0 + + 1 2 0 @@ -968,20 +946,14 @@ hill 14340 - + 1 - 0 0 - + - 0 - 0 - 0 - - <p>Enter your VISA card number.</p> 1 0 @@ -989,19 +961,19 @@ hill 0 0 character_001 + 0 + 0 + 0 + + 1 0000000000000000 16 16 - + - 0 - 0 - 0 - - <p>Enter your email address.</p> 1 0 @@ -1009,18 +981,18 @@ hill 0 0 character_002 + 0 + 0 + 0 + + 1 PATTERN_EMAIL 0 - + - 0 - 0 - 0 - - <p>Enter the URL of your favourite site.</p> 1 0 @@ -1028,54 +1000,59 @@ hill 0 0 character_003 + 0 + 0 + 0 + + 1 PATTERN_URL 0 - + - 1 - 0 + 0 0 - + - 0 - 0 - 0 - - <p>Do you have the driving licence?</p> 1 1 0 0 boolean_006 + 0 + 0 + 0 + + 2 -1 strfbool01 - + + With driving licence 0 - 0 0 - - 60 - 1 - - With driving licence 2 - + + <p>Please specify the category?</p> + 1 + 0 + 1 + 0 + select_002 0 0 0 @@ -1085,12 +1062,6 @@ hill - <p>Please specify the category?</p> - 1 - 0 - 1 - 0 - select_002 A::for motorcycles B::for cars C::for tracks @@ -1098,23 +1069,24 @@ C::for tracks 0 - + + Without driving licence 0 - 0 0 - - 60 - 0 - - Without driving licence 2 - + + <p>When did you plan to get it?</p> + 1 + 0 + 1 + 0 + select_003 0 0 0 @@ -1124,12 +1096,6 @@ C::for tracks - <p>When did you plan to get it?</p> - 1 - 0 - 1 - 0 - select_003 soon with the time when I will be allowed by the law (I am still not 18) diff --git a/tests/fixtures/usertemplate/item_action_test.xml b/tests/fixtures/usertemplate/item_action.xml similarity index 92% rename from tests/fixtures/usertemplate/item_action_test.xml rename to tests/fixtures/usertemplate/item_action.xml index 2a9267d5e02..78afbc87b4d 100644 --- a/tests/fixtures/usertemplate/item_action_test.xml +++ b/tests/fixtures/usertemplate/item_action.xml @@ -1,25 +1,20 @@ - + + <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4></h4><h4>First part of the test</h4> + 1 + 0 0 0 0 - <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4></h4><h4>First part of the test</h4> - 1 - 0 0 - + - 0 - 0 - 0 - - Very first parent<br /> 1 1 @@ -27,6 +22,11 @@ 0 1 veryfirstparent + 0 + 0 + 0 + + 0::Ambiguous answer 1::Positive answer 2::Negative answer @@ -35,8 +35,15 @@ 1 - + + <p>Second generation, first parent question<br /></p> + 1 + 1 + 1 + 0 + 1.a + vfp_a 0 0 0 @@ -46,21 +53,22 @@ - <p>Second generation, first parent question<br /></p> - 1 - 1 - 1 - 0 - 1.a - vfp_a 2 1 strfbool01 - + + <p>Third generation, first cousin<br /></p> + 1 + 1 + 2 + 0 + 1.a.1 + 0 + vfp_a_one 0 0 0 @@ -70,14 +78,6 @@ - <p>Third generation, first cousin<br /></p> - 1 - 1 - 2 - 0 - 1.a.1 - 0 - vfp_a_one 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -88,8 +88,15 @@ 0 - + + <p>Fourth generation first brother question<br /></p> + 1 + 1 + 3 + 0 + 1.a.1.first + vfp_a_one_1st 0 0 0 @@ -99,13 +106,6 @@ - <p>Fourth generation first brother question<br /></p> - 1 - 1 - 3 - 0 - 1.a.1.first - vfp_a_one_1st 4thpositive::positive 4thneutral::neutral 4thnegative::negative @@ -114,8 +114,15 @@ 0 - + + <p>Fourth generation second brother question<br /></p> + 1 + 1 + 3 + 0 + 1.a.1.second + vfp_a_one_2nd 0 0 0 @@ -125,13 +132,6 @@ - <p>Fourth generation second brother question<br /></p> - 1 - 1 - 3 - 0 - 1.a.1.second - vfp_a_one_2nd 4thpositive::positive 4thneutral::neutral 4thnegative::negative @@ -140,8 +140,16 @@ 0 - + + <p>Second generation, second parent question<br /></p> + 1 + 1 + 1 + 0 + 1.b + 0 + vfp_b 0 0 0 @@ -151,14 +159,6 @@ - <p>Second generation, second parent question<br /></p> - 1 - 1 - 1 - 0 - 1.b - 0 - vfp_b 2ndpositive::positive 2ndneutral::neutral 2ndnegative::negative @@ -169,8 +169,15 @@ 0 - + + Third generation, second cousin<br /> + 1 + 1 + 2 + 0 + 1.b.1 + vfp_b_one 0 0 0 @@ -180,13 +187,6 @@ - Third generation, second cousin<br /> - 1 - 1 - 2 - 0 - 1.b.1 - vfp_b_one 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -195,8 +195,15 @@ 1 - + + <p>Fourth generation unique question<br /></p> + 1 + 1 + 3 + 0 + 1.b.1.a + vfp_b_one_1st 0 0 0 @@ -206,13 +213,6 @@ - <p>Fourth generation unique question<br /></p> - 1 - 1 - 3 - 0 - 1.b.1.a - vfp_b_one_1st 3rdpositive::positive 3rdneutral::neutral 3rdnegative::negative @@ -221,32 +221,32 @@ 0 - + + <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4>Second part of the test<br /></h4> + 1 + 0 0 0 0 - <p><br /></p><p><br /></p><p><br /></p><p><br /></p><h4>Second part of the test<br /></h4> - 1 - 0 0 - + - 0 - 0 - 0 - - <div>Simple parent</div> 1 1 0 0 first + 0 + 0 + 0 + + 0::Ambiguous answer 1::Positive answer 2::Negative answer @@ -255,8 +255,14 @@ 1 - + + <p>Second generation, first question<br /></p> + 1 + 1 + 1 + 0 + firstone 0 0 0 @@ -266,20 +272,21 @@ - <p>Second generation, first question<br /></p> - 1 - 1 - 1 - 0 - firstone 2 1 strfbool01 - + + <p>Second generation, second question<br /></p> + 1 + 1 + 1 + 0 + 0 + firsttwo 0 0 0 @@ -289,13 +296,6 @@ - <p>Second generation, second question<br /></p> - 1 - 1 - 1 - 0 - 0 - firsttwo 22positive::positive 22neutral::neutral 22negative::negative @@ -306,8 +306,14 @@ 0 - + + <p>Second generation, third question<br /></p> + 1 + 1 + 1 + 0 + firstthree 0 0 0 @@ -317,12 +323,6 @@ - <p>Second generation, third question<br /></p> - 1 - 1 - 1 - 0 - firstthree 23positive::positive 23neutral::neutral 23negative::negative diff --git a/tests/fixtures/usertemplate/parent-child_2023103100.xml b/tests/fixtures/usertemplate/parent-child_2024032800.xml similarity index 91% rename from tests/fixtures/usertemplate/parent-child_2023103100.xml rename to tests/fixtures/usertemplate/parent-child_2024032800.xml index 89c44566325..5b2a51efbd3 100644 --- a/tests/fixtures/usertemplate/parent-child_2023103100.xml +++ b/tests/fixtures/usertemplate/parent-child_2024032800.xml @@ -1,12 +1,7 @@ - + - 0 - 0 - 0 - - <p>Before starting I need to let you know few details at general level.</p> <p>In a parent child relation almost each item can be a child while only few items can be parent.</p> <p>Almost each field and each formats (with exception of autofill and page-break) can be child. On the contrary, only "boolean", "checkbox", "integer", "multiselect", "radio button" and "select" can be parent.</p> @@ -27,16 +22,16 @@ <p>A closing note: of course, you can not evaluate the presence of a child item in "second" pages when you are in preview mode because data submitted by items in the "first" page are not saved to database. In preview mode case, each child will be shown in "second" pages.</p> 1 0 - 1 - - - - 0 0 0 - + + 1 + + + + Example with boolean item: Is this true or false?</p> 1 0 @@ -44,30 +39,25 @@ 0 1 boolean_001 + 0 + 0 + 0 + + 2 -1 strfbool01 - + 1 - 0 0 - + - 0 - 0 - 0 - - 2 - 1 - - - Enter you name<br>(Just a detail: I marked this question as mandatory question. The attribute is actually considered ONLY if the parent item allows his child otherwise the attribute is neglected). 1 0 @@ -77,22 +67,22 @@ 0 character_001 This item is allowed if the answer to its parent is TRUE - 1 - PATTERN_FREE - 0 - - - - 0 0 0 2 - 0 + 1 - + + 1 + PATTERN_FREE + 0 + + + + Number of friends you would like to invite to your next birthday party. 1 0 @@ -102,32 +92,36 @@ 0 integer_001 This item is allowed if the answer to its parent is FALSE + 0 + 0 + 0 + + 2 + 0 + + + 2 -1 0 105 - + + As you can see, by answering "No answer" to the parent item you get disabled the first such as the second child too. + 1 + 0 0 0 0 - As you can see, by answering "No answer" to the parent item you get disabled the first such as the second child too. - 1 - 0 0 - + - 0 - 0 - 0 - - Example with checkbox item: What do you always want to find on your desk in the office? 1 0 @@ -136,6 +130,11 @@ 2 0 checkbox_001 + 0 + 0 + 0 + + rubber pen pencil @@ -147,24 +146,14 @@ A4 paper 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 7 - 1;1;1;0 - - - Write something. 1 0 @@ -174,22 +163,22 @@ A4 paper 0 character_002 child item displayed only if 'rubber & pen & pencil' is answered to the parent item - 1 - PATTERN_FREE - 0 - - - - 0 0 0 7 - 0;1;0;0 + 1;1;1;0 - + + 1 + PATTERN_FREE + 0 + + + + Please describe the best motor you have ever seen. 1 0 @@ -199,20 +188,24 @@ A4 paper 0 textarea_001 This item should be enabled if the answer to the parent item is "pen" ONLY but this is a missing funtionality as described in MDL-25067 + 0 + 0 + 0 + + 7 + 0;1;0;0 + + + + 0 1 10 60 - 0 0 - + - 0 - 0 - 0 - - Example with numeric (small integer) item: Enter an integer value. 1 0 @@ -221,30 +214,25 @@ A4 paper 3 0 integer_002 + 0 + 0 + 0 + + 2 -1 0 30 - + 1 - 0 0 - + - 0 - 0 - 0 - - 11 - 11 - - - Enter you name. 1 0 @@ -254,22 +242,22 @@ A4 paper 0 character_003 This item is enabled if the answer to the parent item is 11 - 1 - PATTERN_FREE - 0 - - - - 0 0 0 11 - 22 + 11 - + + 1 + PATTERN_FREE + 0 + + + + Number of friends you would like to invite to your next birthday party. 1 0 @@ -279,19 +267,23 @@ A4 paper 0 integer_003 This item is enabled if the answer to the parent item is 22 + 0 + 0 + 0 + + 11 + 22 + + + 2 -1 0 105 - + - 0 - 0 - 0 - - Example with multiselect item: What do you eat for breakfast? (click or shift-click to change the selection). 1 0 @@ -300,6 +292,11 @@ A4 paper 4 0 multiselect_001 + 0 + 0 + 0 + + b::bread m::milk j::jam @@ -314,24 +311,14 @@ ham 4 - + 1 - 0 0 - + - 0 - 0 - 0 - - 15 - 3;0 - - - You preferred room temperature? 1 0 @@ -341,22 +328,22 @@ ham 0 numeric_001 This item is allowed when the answer to its parent is "ham bread" - 27 - 0 - 2 - - - - 0 0 0 15 - 2;3;4 + 3;0 - + + 27.00 + 0 + 2 + + + + Enter a full date. 1 0 @@ -366,6 +353,15 @@ ham 0 date_001 This item is allowed when the answer to its parent is "jam ham tomatoes" + 0 + 0 + 0 + + 15 + 2;3;4 + + + 2 43200 strftime01 @@ -373,13 +369,8 @@ ham 1609416000 - + - 0 - 0 - 0 - - Example with radio button item: which countryside do you like more for your summer holidays? 1 0 @@ -387,6 +378,11 @@ ham 0 5 radiobutton_001 + 0 + 0 + 0 + + Mountain Hill Sea @@ -398,24 +394,14 @@ City 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 19 - 3 - - - When did you buy your last car? 1 0 @@ -425,23 +411,23 @@ City 0 shortdate_001 This item is allowed when the answer to its parent is "Lake" - 2 - strftime01 - 43200 - 1606824000 - - - - 0 0 0 19 - 0 + 3 - + + 2 + strftime01 + 43200 + 1606824000 + + + + Order the following languages as you better can make use of them. 1 0 @@ -451,6 +437,14 @@ City 0 rate_001 This item is allowed when the answer to its parent is "Mountain" + 0 + 0 + + 19 + 0 + + + English Greek Spanish @@ -471,13 +465,8 @@ bad 0 - + - 0 - 0 - 0 - - Example with select item: Indicate your preferred direction. 1 0 @@ -485,6 +474,11 @@ bad 0 6 select_001 + 0 + 0 + 0 + + top bottom right @@ -493,24 +487,14 @@ left 0 - + 1 - 0 0 - + - 0 - 0 - 0 - - 23 - 1 - - - How old were you when you first travelled alone? 1 0 @@ -520,23 +504,23 @@ left 0 age_001 This item is allowed If your answer to previous question was "bottom" - 2 - -1 - -2635200 - 3339835200 - - - - 0 0 0 23 - 0 + 1 - + + 2 + -1 + -2635200 + 3339835200 + + + + Please attach your curriculum vitae. 1 0 @@ -545,6 +529,14 @@ left 6.b fileupload_001 This item is allowed only by answering "Top" to its parent. I asked for the option to disable it in MDL-28194. That issue is still open but, in spite of this, the item can be disabled. + 0 + 0 + + 23 + 0 + + + 1 0 * diff --git a/tests/generator_test.php b/tests/generator_test.php index 7e9e62f37f4..71cd1d64231 100644 --- a/tests/generator_test.php +++ b/tests/generator_test.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace mod_surveypro; + /** * PHPUnit data generator test. * @@ -29,14 +31,14 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class generator_test extends advanced_testcase { +final class generator_test extends \advanced_testcase { /** * Test_create_instance. * * @return void */ - public function test_create_instance() { + public function test_create_instance(): void { global $DB; $this->resetAfterTest(); @@ -61,7 +63,7 @@ public function test_create_instance() { * * @return void */ - public function test_apply_mastertemplate() { + public function test_apply_mastertemplate(): void { global $DB; $this->resetAfterTest(); diff --git a/tests/lib_test.php b/tests/lib_test.php index 82db4c79428..a776a5b6e36 100644 --- a/tests/lib_test.php +++ b/tests/lib_test.php @@ -18,6 +18,11 @@ use advanced_testcase; +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/mod/surveypro/lib.php'); + /** * The class to verify all the lib.php global functions do work as expected. * @@ -25,7 +30,7 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class lib_test extends advanced_testcase { +final class lib_test extends advanced_testcase { /** * surveypro_cutdownstring provider @@ -35,9 +40,9 @@ class lib_test extends advanced_testcase { public function surveypro_cutdownstring_provider(): array { return [ 'plain_short_string' => ['Hello world!', 60, 'Hello world!'], - 'utf8_short_string' => ['Hello 🌍 !', 60, 'Hello 🌍 !'], + 'utf8_short_string' => ['Hello 🌍 !', 60, 'Hello 🌍 !'], 'plain_cut_string' => ['Hello world!', 10, 'Hello w...'], - 'utf8_cut_string' => ['Hello 🌍 !', 9, 'Hello 🌍 !'], + 'utf8_cut_string' => ['Hello 🌍 !', 9, 'Hello 🌍 !'], ]; } @@ -50,7 +55,7 @@ public function surveypro_cutdownstring_provider(): array { * @param int $maxlength The length passed * @param string $expected The expected result */ - public function test_surveypro_cutdownstring($plainstring, $maxlength, $expected) { + public function test_surveypro_cutdownstring($plainstring, $maxlength, $expected): void { // Let's test that surveypro_cutdownstring() works as expected. $this->assertSame($expected, surveypro_cutdownstring($plainstring, $maxlength)); } @@ -116,7 +121,7 @@ public function surveypro_pre_process_checkboxes_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_surveypro_pre_process_checkboxes($userinput, $expected) { + public function test_surveypro_pre_process_checkboxes($userinput, $expected): void { // Let's test that surveypro_pre_process_checkboxes() works as expected. surveypro_pre_process_checkboxes($userinput); $this->assertEquals($expected, $userinput); diff --git a/tests/mastertemplate_test.php b/tests/mastertemplate_test.php index 3dbc2a1d643..a6ba95e9a24 100644 --- a/tests/mastertemplate_test.php +++ b/tests/mastertemplate_test.php @@ -26,7 +26,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \mod_surveypro\mastertemplate */ -class mastertemplate_test extends advanced_testcase { +final class mastertemplate_test extends advanced_testcase { /** * Data provider for surveyprotemplate_get_plugin_name_provider() @@ -51,7 +51,7 @@ public function surveyprotemplate_get_plugin_name_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_surveyprotemplate_get_plugin_name($userinput, $expected) { + public function test_surveyprotemplate_get_plugin_name($userinput, $expected): void { $this->resetAfterTest(); $this->setAdminUser(); diff --git a/tests/separator_test.php b/tests/separator_test.php index a09156ebed5..a3c82f3f649 100644 --- a/tests/separator_test.php +++ b/tests/separator_test.php @@ -32,7 +32,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \surveyprofield_radiobutton */ -class separator_test extends advanced_testcase { +final class separator_test extends advanced_testcase { /** * Data provider for test_userform_get_separator() @@ -53,90 +53,84 @@ class separator_test extends advanced_testcase { public function userform_get_separator_provider(): array { $userinput = []; $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
']; $test01 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', '
']; $test02 = [$userinput, $expected]; // Test03: defaultoption = SURVEYPRO_NOANSWERDEFAULT is not compatible with required = 1 $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', ' ']; $test04 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 1; - $userinput['options'] = 'mum\ndad'; - $expected = ['
', ' ', '
']; + $expected = ['
', '
', ' ']; $test05 = [$userinput, $expected]; // Test06: defaultoption = SURVEYPRO_NOANSWERDEFAULT is not compatible with required = 1 $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; $expected = ['
']; $test07 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', '
']; $test08 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_NOANSWERDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = ''; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; $expected = ['
']; $test09 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_CUSTOMDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', ' ', '
']; $test10 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_INVITEDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', '
', ' ', '
']; $test11 = [$userinput, $expected]; $userinput['defaultoption'] = SURVEYPRO_NOANSWERDEFAULT; + $userinput['options'] = "mum\ndad"; $userinput['labelother'] = 'Other (please, specify)'; $userinput['required'] = 0; - $userinput['options'] = 'mum\ndad'; - $expected = ['
']; + $expected = ['
', ' ', '
']; $test12 = [$userinput, $expected]; return [ - $test01, - $test02, - $test04, - $test05, - $test07, - $test08, - $test09, - $test10, - $test11, - $test12, + $test01, $test02, + $test04, $test05, + $test07, $test08, $test09, + $test10, $test11, $test12, ]; } @@ -147,7 +141,7 @@ public function userform_get_separator_provider(): array { * @param object $userinput The passed user input * @param object $expected The expected result */ - public function test_userform_get_separator($userinput, $expected) { + public function test_userform_get_separator($userinput, $expected): void { $this->resetAfterTest(); $this->setAdminUser(); @@ -161,9 +155,9 @@ public function test_userform_get_separator($userinput, $expected) { // Define parameters. $itemman->set_defaultoption($userinput['defaultoption']); // Needed to define $invitation. + $itemman->set_options($userinput['options']); // Needed to define $labels. $itemman->set_labelother($userinput['labelother']); // Needed to define $addother. $itemman->set_required($userinput['required']); // Needed to define $mandatory. - $itemman->set_options($userinput['options']); // Needed to define $labels. $returned = $itemman->userform_get_separator(); $this->assertEquals($expected, $returned); diff --git a/tests/setup_test.php b/tests/setup_test.php index 7949ca11ce0..c263b71506f 100644 --- a/tests/setup_test.php +++ b/tests/setup_test.php @@ -29,14 +29,14 @@ * @copyright 2015 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class setup_test extends advanced_testcase { +final class setup_test extends advanced_testcase { /** * Test that all the global settings are stored properly and with expected defaults. * * Any new setting and/or change of default will require a change here. */ - public function test_global_config_defaults() { + public function test_global_config_defaults(): void { $this->assertCount(0, (array)get_config('surveypro')); $this->assertCount(4, (array)get_config('mod_surveypro')); diff --git a/tools.php b/tools.php index 1f3ae31dd92..8a5a8d0c466 100644 --- a/tools.php +++ b/tools.php @@ -37,8 +37,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('tools'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); diff --git a/utemplates.php b/utemplates.php index 075913be640..4193873fe3a 100644 --- a/utemplates.php +++ b/utemplates.php @@ -41,8 +41,8 @@ $defaultsection = surveypro_get_defaults_section_per_area('utemplates'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); +$s = optional_param('s', 0, PARAM_INT); $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); @@ -255,25 +255,46 @@ $applyman->prevent_direct_user_input(); $utemplates = $applyman->get_utemplates_items(); - // Begin of: define $applyutemplate return url. - $formurl = new \moodle_url('/mod/surveypro/utemplates.php', ['s' => $cm->instance, 'section' => 'apply']); - // End of: define $applyutemplate return url. - - // Begin of: prepare params for the form. - $formparams = new \stdClass(); - $formparams->utemplates = $utemplates; - $formparams->inlineform = false; - $applyutemplate = new utemplate_applyform($formurl, $formparams); - // End of: prepare params for the form. - - // Begin of: manage form submission. - if ($applyman->formdata = $applyutemplate->get_data()) { - // Here I don't need to execute validate_xml because xml was validated at upload time - // Here I only need to verfy that plugin versions still match - // $applyman->check_items_versions(); - $applyman->apply_template(); + if ($action != SURVEYPRO_APPLYUTEMPLATE) { + // Begin of: define $applyutemplate return url. + $formurl = new \moodle_url('/mod/surveypro/utemplates.php', ['s' => $cm->instance, 'section' => 'apply']); + // End of: define $applyutemplate return url. + + // Begin of: prepare params for the form. + $formparams = new \stdClass(); + $formparams->utemplates = $utemplates; + $formparams->inlineform = false; + $applyutemplate = new utemplate_applyform($formurl, $formparams); + // End of: prepare params for the form. + + // Begin of: manage form submission. + if ($applyman->formdata = $applyutemplate->get_data()) { + // Bloody scenario. + // I upload a usertemplate on monday. + // I update surveypro on tuesday. This may make monday's usertemplates obsolete. + // I arrive here and I try to apply an OBSOLETE usertemplate. + // Somebody has to tell me I can not carry on. + // $applyman->check_items_versions(); + $applyman->lastminute_template_check(); + $xmlvalidationoutcome = $applyman->get_xmlvalidationoutcome(); + if (!isset($xmlvalidationoutcome->key)) { + $applyman->apply_template(); + } + } + // End of: manage form submission. + } else { + if ($confirm == SURVEYPRO_CONFIRMED_YES) { + $applyman->lastminute_template_check(); + $xmlvalidationoutcome = $applyman->get_xmlvalidationoutcome(); + if (!isset($xmlvalidationoutcome->key)) { + $applyman->apply_template(); + + $paramurl = ['s' => $this->cm->instance, 'section' => 'itemslist']; + $returnurl = new \moodle_url('/mod/surveypro/layout.php', $paramurl); + redirect($returnurl); + } + } } - // End of: manage form submission. // Set $PAGE params. $paramurl = ['s' => $surveypro->id, 'area' => 'utemplates', 'section' => 'apply']; @@ -293,7 +314,10 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_utemplates_action_bar(); - $applyman->friendly_stop(); + $applyman->lastminute_stop(); + if ($action == SURVEYPRO_APPLYUTEMPLATE) { + $applyman->ask_for_confirmation(); + } $riskyediting = ($surveypro->riskyeditdeadline > time()); $utilitylayoutman = new utility_layout($cm, $surveypro); diff --git a/version.php b/version.php index 5e3d0b2e9be..72e7402a51f 100644 --- a/version.php +++ b/version.php @@ -26,6 +26,6 @@ $plugin->component = 'mod_surveypro'; $plugin->maturity = MATURITY_BETA; -$plugin->version = 2024022700; -$plugin->release = '4.4dev'; -$plugin->requires = 2023100900; +$plugin->version = 2024070600; +$plugin->release = '4.4'; +$plugin->requires = 2024042200; diff --git a/view.php b/view.php index 82f0db0ae74..3c0a4f52014 100644 --- a/view.php +++ b/view.php @@ -24,28 +24,27 @@ use mod_surveypro\utility_layout; use mod_surveypro\utility_page; -use mod_surveypro\utility_mform; use mod_surveypro\view_cover; -use mod_surveypro\view_submissionlist; -use mod_surveypro\view_submissionform; -use mod_surveypro\view_submissionsearch; +use mod_surveypro\view_responselist; +use mod_surveypro\view_responsesubmit; +use mod_surveypro\view_responsesearch; -use mod_surveypro\local\form\userform; -use mod_surveypro\local\form\usersearch; +use mod_surveypro\local\form\response_submitform; +use mod_surveypro\local\form\response_searchform; require_once(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/lib.php'); $defaultsection = surveypro_get_defaults_section_per_area('surveypro'); -$id = optional_param('id', 0, PARAM_INT); // Course_module id. -$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. +$id = optional_param('id', 0, PARAM_INT); // Course_module id. +$s = optional_param('s', 0, PARAM_INT); // Surveypro instance id. $section = optional_param('section', $defaultsection, PARAM_ALPHAEXT); // The section of code to execute. $edit = optional_param('edit', -1, PARAM_BOOL); // Verify I used correct names all along the module code. -$validsections = ['cover', 'submissionslist', 'submissionform', 'searchsubmissions']; +$validsections = ['cover', 'submissionslist', 'responsesubmit', 'responsesearch']; if (!in_array($section, $validsections)) { $message = 'The section param \''.$section.'\' is invalid.'; debugging('Error at line '.__LINE__.' of file '.__FILE__.'. '.$message , DEBUG_DEVELOPER); @@ -138,7 +137,7 @@ } // Calculations. - $submissionlistman = new view_submissionlist($cm, $context, $surveypro); + $submissionlistman = new view_responselist($cm, $context, $surveypro); $submissionlistman->setup($submissionid, $action, $mode, $confirm, $searchquery); if ($action == SURVEYPRO_RESPONSETOPDF) { @@ -178,13 +177,13 @@ } } -// MARK submissionform. +// MARK responsesubmit. // This section serves the page to... // - add a new submission [$mode = SURVEYPRO_NEWRESPONSEMODE]; // - edit existing submissions [$mode = SURVEYPRO_EDITMODE]; // - view in readonly mode [$mode = SURVEYPRO_READONLYMODE]; // - preview submission form [$mode = SURVEYPRO_PREVIEWMODE]; -if ($section == 'submissionform') { +if ($section == 'responsesubmit') { // Get additional specific params. $submissionid = optional_param('submissionid', 0, PARAM_INT); $formpage = optional_param('formpage', 1, PARAM_INT); // Form page number. @@ -193,16 +192,14 @@ $overflowpage = optional_param('overflowpage', 0, PARAM_INT); // Went the user to a overflow page? // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - - $submissionformman = new view_submissionform($cm, $context, $surveypro); - $submissionformman->setup($submissionid, $formpage, $mode); + $responsesubmitman = new view_responsesubmit($cm, $context, $surveypro); + $responsesubmitman->setup($submissionid, $formpage, $mode); $utilitylayoutman = new utility_layout($cm, $surveypro); $utilitylayoutman->add_custom_css(); - // Begin of: define $user_form return url. - $paramurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionform']; + // Begin of: define responsesubmit return url. + $paramurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'responsesubmit']; $formurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); // End of: define $user_form return url. @@ -212,80 +209,87 @@ $formparams->surveypro = $surveypro; $formparams->submissionid = $submissionid; $formparams->mode = $mode; - $formparams->userformpagecount = $submissionformman->get_userformpagecount(); + $formparams->userformpagecount = $responsesubmitman->get_userformpagecount(); $formparams->canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $context); - $formparams->userfirstpage = $submissionformman->get_userfirstpage(); // The user first page - $formparams->userlastpage = $submissionformman->get_userlastpage(); // The user last page + $formparams->userfirstpage = $responsesubmitman->get_userfirstpage(); // The user first page + $formparams->userlastpage = $responsesubmitman->get_userlastpage(); // The user last page $formparams->overflowpage = $overflowpage; // Went the user to a overflow page? // End of: prepare params for the form. if ($begin == 1) { - $submissionformman->next_not_empty_page(true, 0); // True means direction = right. - $nextpage = $submissionformman->get_nextpage(); // The page of the form to select subset of fields - $submissionformman->set_formpage($nextpage); + $responsesubmitman->next_not_empty_page(true, 0); // True means direction = right. + $nextpage = $responsesubmitman->get_nextpage(); // The page of the form to select subset of fields + $responsesubmitman->set_formpage($nextpage); } - $formparams->formpage = $submissionformman->get_formpage(); // The page of the form to select subset of fields + $formparams->formpage = $responsesubmitman->get_formpage(); // The page of the form to select subset of fields // End of: prepare params for the form. $editable = ($mode == SURVEYPRO_READONLYMODE) ? false : true; - $userform = new userform($formurl, $formparams, 'post', '', ['id' => 'userentry'], $editable); + $attributes = ['id' => 'userentry', 'class' => 'narrowlines']; + $userform = new response_submitform($formurl, $formparams, 'post', '', $attributes, $editable); // Begin of: manage form submission. if ($userform->is_cancelled()) { + // If the submission was canceled + // and the surveypro_submission record (1) exists and (2) has not the creation time, add it. + if ($DB->record_exists('surveypro_submission', ['id' => $submissionid, 'timecreated' => null])) { + $timenow = time(); + $DB->set_field('surveypro_submission', 'timecreated', $timenow, ['id' => $submissionid]); + } $localparamurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionslist']; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $localparamurl); redirect($redirecturl, get_string('usercanceled', 'mod_surveypro')); } - if ($submissionformman->formdata = $userform->get_data()) { - $submissionformman->save_user_data(); // SAVE SAVE SAVE SAVE. + if ($responsesubmitman->formdata = $userform->get_data()) { + $responsesubmitman->save_user_response(); // SAVE SAVE SAVE SAVE. // If "pause" button has been pressed, redirect. - $pausebutton = isset($submissionformman->formdata->pausebutton); + $pausebutton = isset($responsesubmitman->formdata->pausebutton); if ($pausebutton) { $localparamurl = ['s' => $cm->instance, 'mode' => $mode, 'section' => 'submissionslist']; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $localparamurl); redirect($redirecturl); // Go somewhere. } - $paramurl['submissionid'] = $submissionformman->get_submissionid(); - $paramurl['section'] = 'submissionform'; + $paramurl['submissionid'] = $responsesubmitman->get_submissionid(); + $paramurl['section'] = 'responsesubmit'; // If "previous" button has been pressed, redirect. - $prevbutton = isset($submissionformman->formdata->prevbutton); + $prevbutton = isset($responsesubmitman->formdata->prevbutton); if ($prevbutton) { - $submissionformman->next_not_empty_page(false); - $paramurl['formpage'] = $submissionformman->get_nextpage(); - $paramurl['overflowpage'] = $submissionformman->get_overflowpage(); + $responsesubmitman->next_not_empty_page(false); + $paramurl['formpage'] = $responsesubmitman->get_nextpage(); + $paramurl['overflowpage'] = $responsesubmitman->get_overflowpage(); $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); // Redirect to the first non empty page. } // If "next" button has been pressed, redirect. - $nextbutton = isset($submissionformman->formdata->nextbutton); + $nextbutton = isset($responsesubmitman->formdata->nextbutton); if ($nextbutton) { - $submissionformman->next_not_empty_page(true); - $paramurl['formpage'] = $submissionformman->get_nextpage(); - $paramurl['overflowpage'] = $submissionformman->get_overflowpage(); + $responsesubmitman->next_not_empty_page(true); + $paramurl['formpage'] = $responsesubmitman->get_nextpage(); + $paramurl['overflowpage'] = $responsesubmitman->get_overflowpage(); $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); // Redirect to the first non empty page. } // Surveypro has been submitted. Notify people. - $submissionformman->notifypeople(); + $responsesubmitman->notifypeople(); // If none redirected you, reload THE RIGHT page WITHOUT $paramurl['mode']. // This is necessary otherwise if the user switches language using the corresponding menu // just after a new response is submitted - // the browser redirects to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&view=1&lang=it§ion=submissionform + // the browser redirects to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&view=1&lang=it§ion=responsesubmit // and not to http://localhost/head_behat/mod/surveypro/view.php?s=xxx&lang=it§ion=collectedsubmissions // alias it goes to the page to get one more response // instead of remaining in the view submissions page. $paramurl = []; $paramurl['s'] = $surveypro->id; - // $paramurl['responsestatus'] = $submissionformman->get_responsestatus(); - $paramurl['justsubmitted'] = 1 + $submissionformman->get_userdeservesthanks(); - $paramurl['formview'] = $submissionformman->get_mode(); // In which way am I using this form? + // $paramurl['responsestatus'] = $responsesubmitman->get_responsestatus(); + $paramurl['justsubmitted'] = 1 + $responsesubmitman->get_userdeservesthanks(); + $paramurl['formview'] = $responsesubmitman->get_mode(); // In which way am I using this form? $paramurl['section'] = 'submissionslist'; $redirecturl = new \moodle_url('/mod/surveypro/view.php', $paramurl); redirect($redirecturl); @@ -293,7 +297,7 @@ // End of: manage form submission. // Set $PAGE params. - $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'submissionform', 'mode' => $mode]; + $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'responsesubmit', 'mode' => $mode]; if (!empty($submissionid)) { $paramurl['submissionid'] = $submissionid; } @@ -338,28 +342,28 @@ $actionbar = new \mod_surveypro\output\action_bar($cm, $context, $surveypro); echo $actionbar->draw_view_action_bar(); - $submissionformman->noitem_stopexecution(); - $submissionformman->nomoresubmissions_stopexecution(); - $submissionformman->warning_submission_copy(); - $submissionformman->display_page_x_of_y(); + $responsesubmitman->noitem_stopexecution(); + $responsesubmitman->nomoresubmissions_stopexecution(); + $responsesubmitman->warning_submission_copy(); + $responsesubmitman->display_page_x_of_y(); // Begin of: calculate prefill for fields and prepare standard editors and filemanager. // If sumission already exists. - $prefill = $submissionformman->get_prefill_data(); - $prefill['formpage'] = $submissionformman->get_formpage(); + $prefill = $responsesubmitman->get_prefill_data(); + $prefill['formpage'] = $responsesubmitman->get_formpage(); // End of: calculate prefill for fields and prepare standard editors and filemanager. $userform->set_data($prefill); $userform->display(); - // If surveypro is multipage and $submissionformman->tabpage == SURVEYPRO_READONLYMODE. + // If surveypro is multipage and $responsesubmitman->tabpage == SURVEYPRO_READONLYMODE. // I need to add navigation buttons manually // Because the surveypro is not displayed as a form but as a simple list of graphic user items. - $submissionformman->add_readonly_browsing_buttons(); + $responsesubmitman->add_readonly_browsing_buttons(); } -// MARK searchsubmissions. -if ($section == 'searchsubmissions') { +// MARK responsesearch. +if ($section == 'responsesearch') { // Get additional specific params. $formpage = optional_param('formpage', 1, PARAM_INT); // Form page number. @@ -367,12 +371,10 @@ require_capability('mod/surveypro:searchsubmissions', $context); // Calculations. - mod_surveypro\utility_mform::register_form_elements(); - - $submissionsearchman = new view_submissionsearch($cm, $context, $surveypro); + $responsesearchman = new view_responsesearch($cm, $context, $surveypro); // Begin of: define $searchform return url. - $paramurl = ['s' => $cm->instance, 'section' => 'searchsubmissions']; + $paramurl = ['s' => $cm->instance, 'section' => 'responsesearch']; $formurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); // End of: define $searchform return url. @@ -381,7 +383,7 @@ $formparams->cm = $cm; $formparams->surveypro = $surveypro; $formparams->canaccessreserveditems = has_capability('mod/surveypro:accessreserveditems', $context); - $searchform = new usersearch($formurl, $formparams, 'post', '', ['id' => 'usersearch']); + $searchform = new response_searchform($formurl, $formparams, 'post', '', ['id' => 'usersearch', 'class' => 'narrowlines']); // End of: prepare params for the form. // Begin of: manage form submission. @@ -391,11 +393,11 @@ redirect($returnurl); } - if ($submissionsearchman->formdata = $searchform->get_data()) { + if ($responsesearchman->formdata = $searchform->get_data()) { // In this routine I do not execute a real search. // I only define the param searchquery for the url. $paramurl = ['s' => $cm->instance, 'section' => 'submissionslist']; - if ($searchquery = $submissionsearchman->get_searchparamurl()) { + if ($searchquery = $responsesearchman->get_searchparamurl()) { $paramurl['searchquery'] = $searchquery; } $returnurl = new \moodle_url('/mod/surveypro/view.php', $paramurl); @@ -404,7 +406,7 @@ // End of: manage form submission. // Set $PAGE params. - $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'searchsubmissions']; + $paramurl = ['s' => $surveypro->id, 'area' => 'surveypro', 'section' => 'responsesearch']; $url = new \moodle_url('/mod/surveypro/view.php', $paramurl); $PAGE->set_url($url); $PAGE->set_context($context);