dirroot.'/repository/lib.php'); use local_treestudyplan\aggregator; use local_treestudyplan\studyplan; use local_treestudyplan\studyplanpage; use local_treestudyplan\courseservice; use local_treestudyplan\form\text_integer; use local_treestudyplan\local\helpers\webservicehelper; use local_treestudyplan\studyplanservice; use moodle_exception; use stdClass; /** * Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor * in the studyplan description */ class studyplanpage_editform extends formbase { /** * Capability required to edit study plans * @var string */ const CAP_EDIT = "local/treestudyplan:editstudyplan"; /** * Translate parameters into customdata. * * @param object $params The parameters for form initialization * @return array Form data based on parameters */ public static function init_customdata(object $params) { $customdata = new stdClass; $customdata->create = $params->mode=='create'?true:false; if($customdata->create){ $customdata->plan = studyplan::find_by_id($params->studyplan_id); } else { $customdata->page = studyplanpage::find_by_id($params->page_id); $customdata->plan = $customdata->page->studyplan(); $customdata->simplemodel = $customdata->page->simple_model(); } $customdata->context = $customdata->plan->context(); $customdata->editoroptions = [ 'trusttext' => true, 'subdirs' => true, 'maxfiles' => 20, 'maxbytes' => 20*1024*1024, 'context' => \context_system::instance(), // Keep the files in system context ]; $customdata->fileoptions = [ 'subdirs' => 0, 'maxbytes' => 10*1024*1024, // Max 10MiB should be sufficient for a picture. 'areamaxbytes' => 10485760, 'maxfiles' => 1, // Just one file 'accepted_types' => ['.jpg', '.png'], 'return_types' => \FILE_INTERNAL | \FILE_EXTERNAL, ]; return $customdata; } /** * Validate security access for this form based on the customdata generated by init_customdata * Return true if validation passes, false or throw an exception if it does not. * * @param object $customdata The customdata for this form * @return bool True if security validation passes. * @throws \moodle_exception if access denied for a specific reason. */ public static function check_security(object $customdata) { /*webservicehelper::require_capabilities(self::CAP_EDIT,$customdata->context); */ } /** * Generate form data from parameters * Also validate parameters and access permissions here * * @param object $customdata The parameters for form initialization * @return array Form data based on parameters */ public function init_formdata(object $customdata) { global $DB; /* Use direct database retrieval to avoid our abstractions causing trouble with existing moodle code assumptions. The form API does seem needlessly convoluted in it's use, but we need the editor... */ if($customdata->create) { $plan = $customdata->plan; $entry = new stdClass; $entry->studyplan_id = $plan->id(); // By default, make the start date of a new page, continue 1 day after the last page's start date; $otherpages = $plan->pages(); if(count($otherpages) > 0){ $lastpage = $otherpages[count($otherpages) -1]; // Propose 1 year after the last page's start date, if no end date is set. if ($lastpage->enddate(false) == null) { $entry->startdate = $lastpage->startdate()->add(new \DateInterval("P1Y"))->format("U"); } else { // Otherwise, propose 1 day after the last page's end date $entry->startdate = $lastpage->enddate()->add(new \DateInterval("P1D"))->format("U"); } } else { // Determine the next august 1st for default value purposes. Only if no other page is available $august = strtotime("first day of august this year"); if($august < time()) { $august = strtotime("first day of august next year"); } $entry->startdate = $august; } $entry->enddate = $entry->startdate + (364*24*60*60); // Not bothering about leap years here. $entry->periods = 4; } else { $entry = $DB->get_record(studyplanpage::TABLE, ['id' => $customdata->page->id()]); $entry->startdate = strtotime($entry->startdate); $entry->enddate = strtotime($entry->enddate); } // Prepare the editor $entry = file_prepare_standard_editor( $entry, 'description', $customdata->editoroptions, \context_system::instance(), 'local_treestudyplan', 'studyplanpage', ($customdata->create)?null:$customdata->page->id() ); return $entry; } /** * Set up the form definition */ public function definition() { $mform = $this->_form; $customdata = (object)$this->_customdata; // Register integer type text_integer::Register(); // Define the form $field = 'fullname'; $mform->addElement('text',$field, get_string('studyplan_name','local_treestudyplan'), []); $mform->addRule($field, null, 'required', null, 'client'); $field = 'shortname'; $mform->addElement('text',$field, get_string('studyplan_shortname','local_treestudyplan'), []); $mform->addRule($field, null, 'required', null, 'client'); $timeless = \get_config("local_treestudyplan","timelessperiods"); if ( !$timeless) { $field = 'startdate'; $mform->addElement('date_selector',$field, get_string('studyplan_startdate','local_treestudyplan'), []); $mform->addRule($field, null, 'required', null, 'client'); $field = 'enddate'; $mform->addElement('date_selector',$field, get_string('studyplan_startdate','local_treestudyplan'), []); $mform->addRule($field, null, 'required', null, 'client'); } $field = 'periods'; $mform->addElement('text_integer',$field, get_string( ($timeless)?'studyplan_slots':'studyplan_periods','local_treestudyplan'), ["unsigned" => true, "nonzero" => true]); $mform->setType($field, PARAM_INT); $mform->addRule($field, null, 'required', null, 'client'); $field = 'description_editor'; $mform->addElement('editor', $field, get_string('studyplan_description', 'local_treestudyplan'), null, $customdata->editoroptions); $mform->setType($field, PARAM_RAW); } /** * Process the submitted data and perform necessary actions * @param object $entry The processed form data; * @return bool false if submission not successful * @throws \moodle_exception if an error must be given for a specific reason. */ protected function process_submitted_data($entry) { $customdata = (object)$this->_customdata; if($customdata->create) { // Use our own abstraction to update the record, so caches are maintained $page = studyplanpage::add(['fullname' => $entry->fullname, 'shortname' => $entry->shortname, 'startdate' => date("Y-m-d",$entry->startdate), 'enddate' => date("Y-m-d",$entry->enddate), 'periods' => $entry->periods, 'studyplan_id' => $customdata->plan->id(), ]); // Process the provided files in the description editor $entry = file_postupdate_standard_editor($entry, 'description', $customdata->editoroptions, \context_system::instance(), 'local_treestudyplan', 'studyplanpage', $page->id()); // Update the description $page->edit([ 'description' => $entry->description, 'descriptionformat' => $entry->descriptionformat, ]); } else { $page = $customdata->page; // Process the provided files in the description editor $entry = file_postupdate_standard_editor($entry, 'description', $customdata->editoroptions, \context_system::instance(), 'local_treestudyplan', 'studyplanpage', $page->id()); // Use our own abstraction to update the record, so caches are maintained $page->edit(['fullname' => $entry->fullname, 'shortname' => $entry->shortname, 'description' => $entry->description, 'descriptionformat' => $entry->descriptionformat, 'startdate' => date("Y-m-d",$entry->startdate), 'enddate' => date("Y-m-d",$entry->enddate), 'periods' => $entry->periods, ]); } /* Return the editor structure of the new / edited page Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass) so we return it in a consistent way */ return studyplanservice::clean_returnvalue(studyplanpage::editor_structure(),$page->editor_model()); } }