Differences Between: [Versions 310 and 400] [Versions 39 and 400]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * Scheduled allocator that internally executes the random allocation later 20 * 21 * @package workshopallocation_scheduled 22 * @subpackage mod_workshop 23 * @copyright 2012 David Mudrak <david@moodle.com> 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once (__DIR__ . '/../lib.php'); // interface definition 30 require_once (__DIR__ . '/../../locallib.php'); // workshop internal API 31 require_once (__DIR__ . '/../random/lib.php'); // random allocator 32 require_once (__DIR__ . '/settings_form.php'); // our settings form 33 34 /** 35 * Allocates the submissions randomly in a cronjob task 36 */ 37 class workshop_scheduled_allocator implements workshop_allocator { 38 39 /** workshop instance */ 40 protected $workshop; 41 42 /** workshop_scheduled_allocator_form with settings for the random allocator */ 43 protected $mform; 44 45 /** 46 * @param workshop $workshop Workshop API object 47 */ 48 public function __construct(workshop $workshop) { 49 $this->workshop = $workshop; 50 } 51 52 /** 53 * Save the settings for the random allocator to execute it later 54 */ 55 public function init() { 56 global $PAGE, $DB; 57 58 $result = new workshop_allocation_result($this); 59 60 $customdata = array(); 61 $customdata['workshop'] = $this->workshop; 62 63 $current = $DB->get_record('workshopallocation_scheduled', 64 array('workshopid' => $this->workshop->id), '*', IGNORE_MISSING); 65 66 $customdata['current'] = $current; 67 68 $this->mform = new workshop_scheduled_allocator_form($PAGE->url, $customdata); 69 70 if ($this->mform->is_cancelled()) { 71 redirect($this->workshop->view_url()); 72 } else if ($settings = $this->mform->get_data()) { 73 if (empty($settings->enablescheduled)) { 74 $enabled = false; 75 } else { 76 $enabled = true; 77 } 78 if (empty($settings->reenablescheduled)) { 79 $reset = false; 80 } else { 81 $reset = true; 82 } 83 $settings = workshop_random_allocator_setting::instance_from_object($settings); 84 $this->store_settings($enabled, $reset, $settings, $result); 85 if ($enabled) { 86 $msg = get_string('resultenabled', 'workshopallocation_scheduled'); 87 } else { 88 $msg = get_string('resultdisabled', 'workshopallocation_scheduled'); 89 } 90 $result->set_status(workshop_allocation_result::STATUS_CONFIGURED, $msg); 91 return $result; 92 } else { 93 // this branch is executed if the form is submitted but the data 94 // doesn't validate and the form should be redisplayed 95 // or on the first display of the form. 96 97 if ($current !== false) { 98 $data = workshop_random_allocator_setting::instance_from_text($current->settings); 99 $data->enablescheduled = $current->enabled; 100 $this->mform->set_data($data); 101 } 102 103 $result->set_status(workshop_allocation_result::STATUS_VOID); 104 return $result; 105 } 106 } 107 108 /** 109 * Returns the HTML code to print the user interface 110 */ 111 public function ui() { 112 global $PAGE; 113 114 $output = $PAGE->get_renderer('mod_workshop'); 115 116 $out = $output->container_start('scheduled-allocator'); 117 // the nasty hack follows to bypass the sad fact that moodle quickforms do not allow to actually 118 // return the HTML content, just to display it 119 ob_start(); 120 $this->mform->display(); 121 $out .= ob_get_contents(); 122 ob_end_clean(); 123 $out .= $output->container_end(); 124 125 return $out; 126 } 127 128 /** 129 * Executes the allocation 130 * 131 * @param bool $checksubmissionphase Check that the workshop is in submission phase before doing anything else. 132 * @return workshop_allocation_result 133 */ 134 public function execute(bool $checksubmissionphase = true) { 135 global $DB; 136 137 $result = new workshop_allocation_result($this); 138 139 // Execution can occur in multiple places. Ensure we only allocate one at a time. 140 $lockfactory = \core\lock\lock_config::get_lock_factory('mod_workshop_allocation_scheduled_execution'); 141 $executionlock = $lockfactory->get_lock($this->workshop->id, 1, 30); 142 if (!$executionlock) { 143 $result->set_status(workshop_allocation_result::STATUS_FAILED, 144 get_string('resultfailed', 'workshopallocation_scheduled')); 145 } 146 147 try { 148 // Make sure the workshop itself is at the expected state. 149 150 if ($checksubmissionphase && $this->workshop->phase != workshop::PHASE_SUBMISSION) { 151 $executionlock->release(); 152 $result->set_status(workshop_allocation_result::STATUS_FAILED, 153 get_string('resultfailedphase', 'workshopallocation_scheduled')); 154 return $result; 155 } 156 157 if (empty($this->workshop->submissionend)) { 158 $executionlock->release(); 159 $result->set_status(workshop_allocation_result::STATUS_FAILED, 160 get_string('resultfaileddeadline', 'workshopallocation_scheduled')); 161 return $result; 162 } 163 164 if ($this->workshop->submissionend > time()) { 165 $executionlock->release(); 166 $result->set_status(workshop_allocation_result::STATUS_VOID, 167 get_string('resultvoiddeadline', 'workshopallocation_scheduled')); 168 return $result; 169 } 170 171 $current = $DB->get_record('workshopallocation_scheduled', 172 array('workshopid' => $this->workshop->id, 'enabled' => 1), '*', IGNORE_MISSING); 173 174 if ($current === false) { 175 $executionlock->release(); 176 $result->set_status(workshop_allocation_result::STATUS_FAILED, 177 get_string('resultfailedconfig', 'workshopallocation_scheduled')); 178 return $result; 179 } 180 181 if (!$current->enabled) { 182 $executionlock->release(); 183 $result->set_status(workshop_allocation_result::STATUS_VOID, 184 get_string('resultdisabled', 'workshopallocation_scheduled')); 185 return $result; 186 } 187 188 if (!is_null($current->timeallocated) and $current->timeallocated >= $this->workshop->submissionend) { 189 $executionlock->release(); 190 $result->set_status(workshop_allocation_result::STATUS_VOID, 191 get_string('resultvoidexecuted', 'workshopallocation_scheduled')); 192 return $result; 193 } 194 195 // So now we know that we are after the submissions deadline and either the scheduled allocation was not 196 // executed yet or it was but the submissions deadline has been prolonged (and hence we should repeat the 197 // allocations). 198 199 $settings = workshop_random_allocator_setting::instance_from_text($current->settings); 200 $randomallocator = $this->workshop->allocator_instance('random'); 201 $randomallocator->execute($settings, $result); 202 203 // Store the result in the instance's table. 204 $update = new stdClass(); 205 $update->id = $current->id; 206 $update->timeallocated = $result->get_timeend(); 207 $update->resultstatus = $result->get_status(); 208 $update->resultmessage = $result->get_message(); 209 $update->resultlog = json_encode($result->get_logs()); 210 211 $DB->update_record('workshopallocation_scheduled', $update); 212 213 } catch (\Exception $e) { 214 $executionlock->release(); 215 $result->set_status(workshop_allocation_result::STATUS_FAILED, 216 get_string('resultfailed', 'workshopallocation_scheduled')); 217 218 throw $e; 219 } 220 221 $executionlock->release(); 222 223 return $result; 224 } 225 226 /** 227 * Delete all data related to a given workshop module instance 228 * 229 * @see workshop_delete_instance() 230 * @param int $workshopid id of the workshop module instance being deleted 231 * @return void 232 */ 233 public static function delete_instance($workshopid) { 234 // TODO 235 return; 236 } 237 238 /** 239 * Stores the pre-defined random allocation settings for later usage 240 * 241 * @param bool $enabled is the scheduled allocation enabled 242 * @param bool $reset reset the recent execution info 243 * @param workshop_random_allocator_setting $settings settings form data 244 * @param workshop_allocation_result $result logger 245 */ 246 protected function store_settings($enabled, $reset, workshop_random_allocator_setting $settings, workshop_allocation_result $result) { 247 global $DB; 248 249 250 $data = new stdClass(); 251 $data->workshopid = $this->workshop->id; 252 $data->enabled = $enabled; 253 $data->submissionend = $this->workshop->submissionend; 254 $data->settings = $settings->export_text(); 255 256 if ($reset) { 257 $data->timeallocated = null; 258 $data->resultstatus = null; 259 $data->resultmessage = null; 260 $data->resultlog = null; 261 } 262 263 $result->log($data->settings, 'debug'); 264 265 $current = $DB->get_record('workshopallocation_scheduled', array('workshopid' => $data->workshopid), '*', IGNORE_MISSING); 266 267 if ($current === false) { 268 $DB->insert_record('workshopallocation_scheduled', $data); 269 270 } else { 271 $data->id = $current->id; 272 $DB->update_record('workshopallocation_scheduled', $data); 273 } 274 } 275 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body