| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | /**
 | 
        
           |  |  | 18 |  * Bulk course upload step 2.
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package    tool_uploadcourse
 | 
        
           |  |  | 21 |  * @copyright  2011 Piers Harding
 | 
        
           |  |  | 22 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | require_once($CFG->dirroot . '/course/lib.php');
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | /**
 | 
        
           |  |  | 30 |  * Specify course upload details.
 | 
        
           |  |  | 31 |  *
 | 
        
           |  |  | 32 |  * @package    tool_uploadcourse
 | 
        
           |  |  | 33 |  * @copyright  2011 Piers Harding
 | 
        
           |  |  | 34 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 35 |  */
 | 
        
           |  |  | 36 | class tool_uploadcourse_step2_form extends tool_uploadcourse_base_form {
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 |     /**
 | 
        
           |  |  | 39 |      * The standard form definiton.
 | 
        
           |  |  | 40 |      * @return void.
 | 
        
           |  |  | 41 |      */
 | 
        
           |  |  | 42 |     public function definition() {
 | 
        
           |  |  | 43 |         global $CFG;
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 |         $mform   = $this->_form;
 | 
        
           |  |  | 46 |         $data    = $this->_customdata['data'];
 | 
        
           |  |  | 47 |         $courseconfig = get_config('moodlecourse');
 | 
        
           |  |  | 48 |   | 
        
           |  |  | 49 |         // Import options.
 | 
        
           |  |  | 50 |         $this->add_import_options();
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |         // Course options.
 | 
        
           |  |  | 53 |         $mform->addElement('header', 'courseoptionshdr', get_string('courseprocess', 'tool_uploadcourse'));
 | 
        
           |  |  | 54 |         $mform->setExpanded('courseoptionshdr', true);
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 |         $mform->addElement('text', 'options[shortnametemplate]', get_string('shortnametemplate', 'tool_uploadcourse'),
 | 
        
           |  |  | 57 |             'maxlength="100" size="20"');
 | 
        
           |  |  | 58 |         $mform->setType('options[shortnametemplate]', PARAM_RAW);
 | 
        
           |  |  | 59 |         $mform->addHelpButton('options[shortnametemplate]', 'shortnametemplate', 'tool_uploadcourse');
 | 
        
           |  |  | 60 |         $mform->hideIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE);
 | 
        
           |  |  | 61 |         $mform->hideIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_UPDATE_ONLY);
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |         // Restore file is not in the array options on purpose, because formslib can't handle it!
 | 
        
           |  |  | 64 |         $contextid = $this->_customdata['contextid'];
 | 
        
           |  |  | 65 |         $mform->addElement('hidden', 'contextid', $contextid);
 | 
        
           |  |  | 66 |         $mform->setType('contextid', PARAM_INT);
 | 
        
           |  |  | 67 |         $mform->addElement('filepicker', 'restorefile', get_string('templatefile', 'tool_uploadcourse'));
 | 
        
           |  |  | 68 |         $mform->addHelpButton('restorefile', 'templatefile', 'tool_uploadcourse');
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 |         $mform->addElement('text', 'options[templatecourse]', get_string('coursetemplatename', 'tool_uploadcourse'));
 | 
        
           |  |  | 71 |         $mform->setType('options[templatecourse]', PARAM_TEXT);
 | 
        
           |  |  | 72 |         $mform->addHelpButton('options[templatecourse]', 'coursetemplatename', 'tool_uploadcourse');
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |         $mform->addElement('selectyesno', 'options[reset]', get_string('reset', 'tool_uploadcourse'));
 | 
        
           |  |  | 75 |         $mform->setDefault('options[reset]', 0);
 | 
        
           |  |  | 76 |         $mform->hideIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
 | 
        
           |  |  | 77 |         $mform->hideIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
 | 
        
           |  |  | 78 |         $mform->disabledIf('options[reset]', 'options[allowresets]', 'eq', 0);
 | 
        
           |  |  | 79 |         $mform->addHelpButton('options[reset]', 'reset', 'tool_uploadcourse');
 | 
        
           |  |  | 80 |   | 
        
           |  |  | 81 |         // Default values.
 | 
        
           |  |  | 82 |         $mform->addElement('header', 'defaultheader', get_string('defaultvalues', 'tool_uploadcourse'));
 | 
        
           |  |  | 83 |         $mform->setExpanded('defaultheader', true);
 | 
        
           |  |  | 84 |   | 
        
           |  |  | 85 |         $displaylist = core_course_category::make_categories_list('tool/uploadcourse:use');
 | 
        
           |  |  | 86 |         $mform->addElement('autocomplete', 'defaults[category]', get_string('coursecategory'), $displaylist);
 | 
        
           |  |  | 87 |         $mform->addRule('defaults[category]', null, 'required', null, 'client');
 | 
        
           |  |  | 88 |         $mform->addHelpButton('defaults[category]', 'coursecategory');
 | 
        
           |  |  | 89 |   | 
        
           |  |  | 90 |         $choices = array();
 | 
        
           |  |  | 91 |         $choices['0'] = get_string('hide');
 | 
        
           |  |  | 92 |         $choices['1'] = get_string('show');
 | 
        
           |  |  | 93 |         $mform->addElement('select', 'defaults[visible]', get_string('coursevisibility'), $choices);
 | 
        
           |  |  | 94 |         $mform->addHelpButton('defaults[visible]', 'coursevisibility');
 | 
        
           |  |  | 95 |         $mform->setDefault('defaults[visible]', $courseconfig->visible);
 | 
        
           |  |  | 96 |   | 
        
           |  |  | 97 |         if ($CFG->downloadcoursecontentallowed &&
 | 
        
           |  |  | 98 |                 has_capability('moodle/course:configuredownloadcontent', context::instance_by_id($contextid))) {
 | 
        
           |  |  | 99 |   | 
        
           |  |  | 100 |             $downloadchoices = [
 | 
        
           |  |  | 101 |                 DOWNLOAD_COURSE_CONTENT_DISABLED => get_string('no'),
 | 
        
           |  |  | 102 |                 DOWNLOAD_COURSE_CONTENT_ENABLED => get_string('yes'),
 | 
        
           |  |  | 103 |             ];
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 |             $sitedefaultstring = $downloadchoices[$courseconfig->downloadcontentsitedefault];
 | 
        
           |  |  | 106 |             $downloadchoices[DOWNLOAD_COURSE_CONTENT_SITE_DEFAULT] = get_string('sitedefaultspecified', '', $sitedefaultstring);
 | 
        
           |  |  | 107 |             $downloadselectdefault = $courseconfig->downloadcontent ?? DOWNLOAD_COURSE_CONTENT_SITE_DEFAULT;
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 |             $mform->addElement('select', 'defaults[downloadcontent]', get_string('enabledownloadcoursecontent', 'course'),
 | 
        
           |  |  | 110 |                 $downloadchoices);
 | 
        
           |  |  | 111 |             $mform->addHelpButton('defaults[downloadcontent]', 'downloadcoursecontent', 'course');
 | 
        
           |  |  | 112 |             $mform->setDefault('defaults[downloadcontent]', $downloadselectdefault);
 | 
        
           |  |  | 113 |         }
 | 
        
           |  |  | 114 |   | 
        
           |  |  | 115 |         $mform->addElement('date_time_selector', 'defaults[startdate]', get_string('startdate'));
 | 
        
           |  |  | 116 |         $mform->addHelpButton('defaults[startdate]', 'startdate');
 | 
        
           |  |  | 117 |         $mform->setDefault('defaults[startdate]', time() + 3600 * 24);
 | 
        
           |  |  | 118 |   | 
        
           |  |  | 119 |         $mform->addElement('date_time_selector', 'defaults[enddate]', get_string('enddate'), array('optional' => true));
 | 
        
           |  |  | 120 |         $mform->addHelpButton('defaults[enddate]', 'enddate');
 | 
        
           |  |  | 121 |   | 
        
           |  |  | 122 |         $courseformats = get_sorted_course_formats(true);
 | 
        
           |  |  | 123 |         $formcourseformats = new core\output\choicelist();
 | 
        
           |  |  | 124 |         $formcourseformats->set_allow_empty(false);
 | 
        
           |  |  | 125 |         foreach ($courseformats as $courseformat) {
 | 
        
           |  |  | 126 |             $definition = [];
 | 
        
           |  |  | 127 |             $component = "format_$courseformat";
 | 
        
           |  |  | 128 |             if (get_string_manager()->string_exists('plugin_description', $component)) {
 | 
        
           |  |  | 129 |                 $definition['description'] = get_string('plugin_description', $component);
 | 
        
           |  |  | 130 |             }
 | 
        
           |  |  | 131 |             $formcourseformats->add_option(
 | 
        
           |  |  | 132 |                 $courseformat,
 | 
        
           |  |  | 133 |                 get_string('pluginname', "format_$courseformat"),
 | 
        
           |  |  | 134 |                 [
 | 
        
           |  |  | 135 |                     'description' => $definition,
 | 
        
           |  |  | 136 |                 ],
 | 
        
           |  |  | 137 |             );
 | 
        
           |  |  | 138 |         }
 | 
        
           |  |  | 139 |         $mform->addElement(
 | 
        
           |  |  | 140 |             'choicedropdown',
 | 
        
           |  |  | 141 |             'defaults[format]',
 | 
        
           |  |  | 142 |             get_string('format'),
 | 
        
           |  |  | 143 |             $formcourseformats,
 | 
        
           |  |  | 144 |         );
 | 
        
           |  |  | 145 |         $mform->setDefault('defaults[format]', $courseconfig->format);
 | 
        
           |  |  | 146 |   | 
        
           |  |  | 147 |         if (!empty($CFG->allowcoursethemes)) {
 | 
        
           |  |  | 148 |             $themeobjects = get_list_of_themes();
 | 
        
           |  |  | 149 |             $themes=array();
 | 
        
           |  |  | 150 |             $themes[''] = get_string('forceno');
 | 
        
           |  |  | 151 |             foreach ($themeobjects as $key => $theme) {
 | 
        
           |  |  | 152 |                 if (empty($theme->hidefromselector)) {
 | 
        
           |  |  | 153 |                     $themes[$key] = get_string('pluginname', 'theme_'.$theme->name);
 | 
        
           |  |  | 154 |                 }
 | 
        
           |  |  | 155 |             }
 | 
        
           |  |  | 156 |             $mform->addElement('select', 'defaults[theme]', get_string('forcetheme'), $themes);
 | 
        
           |  |  | 157 |         }
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 |         $languages = array();
 | 
        
           |  |  | 160 |         $languages[''] = get_string('forceno');
 | 
        
           |  |  | 161 |         $languages += get_string_manager()->get_list_of_translations();
 | 
        
           |  |  | 162 |         $mform->addElement('select', 'defaults[lang]', get_string('forcelanguage'), $languages);
 | 
        
           |  |  | 163 |         $mform->setDefault('defaults[lang]', $courseconfig->lang);
 | 
        
           |  |  | 164 |   | 
        
           |  |  | 165 |         $options = range(0, 10);
 | 
        
           |  |  | 166 |         $mform->addElement('select', 'defaults[newsitems]', get_string('newsitemsnumber'), $options);
 | 
        
           |  |  | 167 |         $mform->addHelpButton('defaults[newsitems]', 'newsitemsnumber');
 | 
        
           |  |  | 168 |         $mform->setDefault('defaults[newsitems]', $courseconfig->newsitems);
 | 
        
           |  |  | 169 |   | 
        
           |  |  | 170 |         $mform->addElement('selectyesno', 'defaults[showgrades]', get_string('showgrades'));
 | 
        
           |  |  | 171 |         $mform->addHelpButton('defaults[showgrades]', 'showgrades');
 | 
        
           |  |  | 172 |         $mform->setDefault('defaults[showgrades]', $courseconfig->showgrades);
 | 
        
           |  |  | 173 |   | 
        
           |  |  | 174 |         $mform->addElement('selectyesno', 'defaults[showreports]', get_string('showreports'));
 | 
        
           |  |  | 175 |         $mform->addHelpButton('defaults[showreports]', 'showreports');
 | 
        
           |  |  | 176 |         $mform->setDefault('defaults[showreports]', $courseconfig->showreports);
 | 
        
           |  |  | 177 |   | 
        
           |  |  | 178 |         if (!empty($CFG->legacyfilesinnewcourses)) {
 | 
        
           |  |  | 179 |             $mform->addElement('select', 'defaults[legacyfiles]', get_string('courselegacyfiles'), $choices);
 | 
        
           |  |  | 180 |             $mform->addHelpButton('defaults[legacyfiles]', 'courselegacyfiles');
 | 
        
           |  |  | 181 |             if (!isset($courseconfig->legacyfiles)) {
 | 
        
           |  |  | 182 |                 $courseconfig->legacyfiles = 0;
 | 
        
           |  |  | 183 |             }
 | 
        
           |  |  | 184 |             $mform->setDefault('defaults[legacyfiles]', $courseconfig->legacyfiles);
 | 
        
           |  |  | 185 |         }
 | 
        
           |  |  | 186 |   | 
        
           |  |  | 187 |         $choices = get_max_upload_sizes($CFG->maxbytes);
 | 
        
           |  |  | 188 |         $mform->addElement('select', 'defaults[maxbytes]', get_string('maximumupload'), $choices);
 | 
        
           |  |  | 189 |         $mform->addHelpButton('defaults[maxbytes]', 'maximumupload');
 | 
        
           |  |  | 190 |         $mform->setDefault('defaults[maxbytes]', $courseconfig->maxbytes);
 | 
        
           |  |  | 191 |   | 
        
           |  |  | 192 |         $choices = array();
 | 
        
           |  |  | 193 |         $choices[NOGROUPS] = get_string('groupsnone', 'group');
 | 
        
           |  |  | 194 |         $choices[SEPARATEGROUPS] = get_string('groupsseparate', 'group');
 | 
        
           |  |  | 195 |         $choices[VISIBLEGROUPS] = get_string('groupsvisible', 'group');
 | 
        
           |  |  | 196 |         $mform->addElement('select', 'defaults[groupmode]', get_string('groupmode', 'group'), $choices);
 | 
        
           |  |  | 197 |         $mform->addHelpButton('defaults[groupmode]', 'groupmode', 'group');
 | 
        
           |  |  | 198 |         $mform->setDefault('defaults[groupmode]', $courseconfig->groupmode);
 | 
        
           |  |  | 199 |   | 
        
           |  |  | 200 |         $mform->addElement('selectyesno', 'defaults[groupmodeforce]', get_string('groupmodeforce', 'group'));
 | 
        
           |  |  | 201 |         $mform->addHelpButton('defaults[groupmodeforce]', 'groupmodeforce', 'group');
 | 
        
           |  |  | 202 |         $mform->setDefault('defaults[groupmodeforce]', $courseconfig->groupmodeforce);
 | 
        
           |  |  | 203 |   | 
        
           |  |  | 204 |         // Completion tracking.
 | 
        
           |  |  | 205 |         if (!empty($CFG->enablecompletion)) {
 | 
        
           |  |  | 206 |             $mform->addElement('selectyesno', 'defaults[enablecompletion]', get_string('enablecompletion', 'completion'));
 | 
        
           |  |  | 207 |             $mform->setDefault('defaults[enablecompletion]', $courseconfig->enablecompletion);
 | 
        
           |  |  | 208 |             $mform->addHelpButton('defaults[enablecompletion]', 'enablecompletion', 'completion');
 | 
        
           |  |  | 209 |         }
 | 
        
           |  |  | 210 |   | 
        
           |  |  | 211 |         $mform->addElement('selectyesno', 'defaults[showactivitydates]', get_string('showactivitydates'));
 | 
        
           |  |  | 212 |         $mform->addHelpButton('defaults[showactivitydates]', 'showactivitydates');
 | 
        
           |  |  | 213 |         $mform->setDefault('defaults[showactivitydates]', $courseconfig->showactivitydates);
 | 
        
           |  |  | 214 |   | 
        
           |  |  | 215 |         // Add custom fields to the form.
 | 
        
           |  |  | 216 |         $handler = \core_course\customfield\course_handler::create();
 | 
        
           |  |  | 217 |         $handler->instance_form_definition($mform, 0, 'defaultvaluescustomfieldcategory', 'tool_uploadcourse');
 | 
        
           |  |  | 218 |   | 
        
           |  |  | 219 |         // Hidden fields.
 | 
        
           |  |  | 220 |         $mform->addElement('hidden', 'importid');
 | 
        
           |  |  | 221 |         $mform->setType('importid', PARAM_INT);
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         $mform->addElement('hidden', 'previewrows');
 | 
        
           |  |  | 224 |         $mform->setType('previewrows', PARAM_INT);
 | 
        
           |  |  | 225 |   | 
        
           |  |  | 226 |         $mform->addElement('hidden', 'categoryid');
 | 
        
           |  |  | 227 |         $mform->setType('categoryid', PARAM_INT);
 | 
        
           |  |  | 228 |   | 
        
           |  |  | 229 |         $this->add_action_buttons(true, get_string('uploadcourses', 'tool_uploadcourse'));
 | 
        
           |  |  | 230 |   | 
        
           |  |  | 231 |         // Prepare custom fields data.
 | 
        
           |  |  | 232 |         $data = (object) $data;
 | 
        
           |  |  | 233 |         $handler->instance_form_before_set_data($data);
 | 
        
           |  |  | 234 |   | 
        
           |  |  | 235 |         $this->set_data($data);
 | 
        
           |  |  | 236 |     }
 | 
        
           |  |  | 237 |   | 
        
           |  |  | 238 |     /**
 | 
        
           |  |  | 239 |      * Add actopm buttons.
 | 
        
           |  |  | 240 |      *
 | 
        
           |  |  | 241 |      * @param bool $cancel whether to show cancel button, default true
 | 
        
           |  |  | 242 |      * @param string $submitlabel label for submit button, defaults to get_string('savechanges')
 | 
        
           |  |  | 243 |      * @return void
 | 
        
           |  |  | 244 |      */
 | 
        
           |  |  | 245 |     public function add_action_buttons($cancel = true, $submitlabel = null) {
 | 
        
           |  |  | 246 |         $mform =& $this->_form;
 | 
        
           |  |  | 247 |         $buttonarray = array();
 | 
        
           |  |  | 248 |         $buttonarray[] = &$mform->createElement('submit', 'showpreview', get_string('preview', 'tool_uploadcourse'));
 | 
        
           |  |  | 249 |         $buttonarray[] = &$mform->createElement('submit', 'submitbutton', $submitlabel);
 | 
        
           |  |  | 250 |         $buttonarray[] = &$mform->createElement('cancel');
 | 
        
           |  |  | 251 |         $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
 | 
        
           |  |  | 252 |         $mform->closeHeaderBefore('buttonar');
 | 
        
           |  |  | 253 |     }
 | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 |     /**
 | 
        
           |  |  | 256 |      * Sets the enddate default after set_data is called.
 | 
        
           |  |  | 257 |      */
 | 
        
           |  |  | 258 |     public function definition_after_data() {
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 |         $mform = $this->_form;
 | 
        
           |  |  | 261 |   | 
        
           |  |  | 262 |         // The default end date depends on the course format.
 | 
        
           |  |  | 263 |         $format = course_get_format((object)array('format' => get_config('moodlecourse', 'format')));
 | 
        
           |  |  | 264 |   | 
        
           |  |  | 265 |         // Check if course end date form field should be enabled by default.
 | 
        
           |  |  | 266 |         // If a default date is provided to the form element, it is magically enabled by default in the
 | 
        
           |  |  | 267 |         // MoodleQuickForm_date_time_selector class, otherwise it's disabled by default.
 | 
        
           |  |  | 268 |         if (get_config('moodlecourse', 'courseenddateenabled')) {
 | 
        
           |  |  | 269 |             $enddate = $format->get_default_course_enddate($mform, array('startdate' => 'defaults[startdate]'));
 | 
        
           |  |  | 270 |             $mform->setDefault('defaults[enddate]', $enddate);
 | 
        
           |  |  | 271 |         }
 | 
        
           |  |  | 272 |   | 
        
           |  |  | 273 |         // Tweak the form with values provided by custom fields in use.
 | 
        
           |  |  | 274 |         \core_course\customfield\course_handler::create()->instance_form_definition_after_data($mform);
 | 
        
           |  |  | 275 |     }
 | 
        
           |  |  | 276 |   | 
        
           |  |  | 277 |     /**
 | 
        
           |  |  | 278 |      * Validation.
 | 
        
           |  |  | 279 |      *
 | 
        
           |  |  | 280 |      * @param array $data
 | 
        
           |  |  | 281 |      * @param array $files
 | 
        
           |  |  | 282 |      * @return array the errors that were found
 | 
        
           |  |  | 283 |      */
 | 
        
           |  |  | 284 |     public function validation($data, $files) {
 | 
        
           |  |  | 285 |         global $DB;
 | 
        
           |  |  | 286 |   | 
        
           |  |  | 287 |         $errors = parent::validation($data, $files);
 | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 |         if ($errorcode = course_validate_dates($data['defaults'])) {
 | 
        
           |  |  | 290 |             $errors['defaults[enddate]'] = get_string($errorcode, 'error');
 | 
        
           |  |  | 291 |         }
 | 
        
           |  |  | 292 |   | 
        
           |  |  | 293 |         // Custom fields validation.
 | 
        
           |  |  | 294 |         array_merge($errors, \core_course\customfield\course_handler::create()->instance_form_validation($data, $files));
 | 
        
           |  |  | 295 |   | 
        
           |  |  | 296 |         return $errors;
 | 
        
           |  |  | 297 |     }
 | 
        
           |  |  | 298 | }
 |