Exercise::class, 'foreign_key' => 'task_id' ]; $config['belongs_to']['test'] = [ 'class_name' => VipsTest::class, 'foreign_key' => 'test_id' ]; parent::configure($config); } /** * Set value for the "exercise" relation (to avoid SORM errors). */ public function setExercise(Exercise $exercise): void { $this->task_id = $exercise->id; $this->relations['exercise'] = $exercise; } /** * Delete entry from the database. */ public function delete() { $ref_count = self::countBySql('task_id = ?', [$this->task_id]); if ($ref_count == 1) { $this->exercise->delete(); } return parent::delete(); } /** * Copy the referenced exercise into the given test at the specified * position (or at the end). Returns the new exercise reference. * * @param string $test_id test id * @param int $position exercise position (optional) */ public function copyIntoTest(string $test_id, ?int $position = null): VipsExerciseRef { $db = DBManager::get(); if ($position === null) { $stmt = $db->prepare('SELECT MAX(position) FROM etask_test_tasks WHERE test_id = ?'); $stmt->execute([$test_id]); $position = $stmt->fetchColumn() + 1; } $new_exercise = Exercise::create([ 'type' => $this->exercise->type, 'title' => $this->exercise->title, 'description' => $this->exercise->description, 'task' => $this->exercise->task, 'options' => $this->exercise->options, 'user_id' => $GLOBALS['user']->id ]); if ($this->exercise->folder) { $folder = Folder::findTopFolder($new_exercise->id, 'ExerciseFolder', 'task'); foreach ($this->exercise->folder->file_refs as $file_ref) { FileManager::copyFile($file_ref->getFileType(), $folder->getTypedFolder(), User::findCurrent()); } } return VipsExerciseRef::create([ 'task_id' => $new_exercise->id, 'test_id' => $test_id, 'points' => $this->points, 'position' => $position ]); } /** * Move the referenced exercise into the given test (at the end). * * @param string $test_id test id */ public function moveIntoTest(string $test_id): void { $db = DBManager::get(); $old_test_id = $this->test_id; $old_position = $this->position; if ($old_test_id != $test_id) { $stmt = $db->prepare('SELECT MAX(position) FROM etask_test_tasks WHERE test_id = ?'); $stmt->execute([$test_id]); $this->position = $stmt->fetchColumn() + 1; $this->test_id = $test_id; $this->store(); // renumber following exercises $sql = 'UPDATE etask_test_tasks SET position = position - 1 WHERE test_id = ? AND position > ?'; $stmt = $db->prepare($sql); $stmt->execute([$old_test_id, $old_position]); } } }