Exercise::class, 'assoc_foreign_key' => 'id', 'thru_table' => 'etask_test_tasks', 'thru_key' => 'test_id', 'thru_assoc_key' => 'task_id', 'order_by' => 'ORDER BY position' ]; $config['has_many']['assignments'] = [ 'class_name' => VipsAssignment::class, 'assoc_foreign_key' => 'test_id' ]; $config['has_many']['exercise_refs'] = [ 'class_name' => VipsExerciseRef::class, 'assoc_foreign_key' => 'test_id', 'on_delete' => 'delete', 'order_by' => 'ORDER BY position' ]; $config['belongs_to']['user'] = [ 'class_name' => User::class, 'foreign_key' => 'user_id' ]; parent::configure($config); } public function addExercise(Exercise $exercise): VipsExerciseRef { $attributes = [ 'task_id' => $exercise->id, 'test_id' => $this->id, 'position' => count($this->exercise_refs) + 1, 'points' => $exercise->itemCount() ]; $exercise_ref = VipsExerciseRef::create($attributes); $this->resetRelation('exercises'); $this->resetRelation('exercise_refs'); return $exercise_ref; } public function removeExercise(int $exercise_id): void { $db = DBManager::get(); $exercise_ref = VipsExerciseRef::find([$this->id, $exercise_id]); $position = $exercise_ref->position; if ($exercise_ref->delete()) { // renumber following exercises $sql = 'UPDATE etask_test_tasks SET position = position - 1 WHERE test_id = ? AND position > ?'; $stmt = $db->prepare($sql); $stmt->execute([$this->id, $position]); } $this->resetRelation('exercises'); $this->resetRelation('exercise_refs'); } public function getExerciseRef(int $exercise_id): ?VipsExerciseRef { return $this->exercise_refs->findOneBy('task_id', $exercise_id); } /** * Return the maximum number of points a person can get on this test. * * @return integer number of maximum points */ public function getTotalPoints(): int { $points = 0; foreach ($this->exercise_refs as $exercise_ref) { $points += $exercise_ref->points; } return $points; } }