<?php defined('SYSPATH') || die('No direct script access.'); /** * @property-read $ID int * @property $AuthorID int * @property $GradeID int * @property $GradeNum int * @property Model_Faculty $Faculty * @property $FacultyID int * @property $FacultyName string * @property $Degree string bachelor / master * @property $SubjectID int * @property $SubjectName string * @property $SubjectAbbr string * @property $SemesterID int * @property $Lectures int * @property $Practice int * @property $Labs int * @property $Type string * @property $Subtype string * @property $IsLocked bool * @property $IsBonus bool * @property $IsMapCreated bool * @property $Milestone int * @property $CompoundDiscID int * @property $CompoundDiscName string */ class Model_Discipline extends Model_Container { const EXAM = 'exam'; const CREDIT = 'credit'; const GRADING_CREDIT = 'grading_credit'; public function __get($name) { if ($name === 'Faculty' && !isset($this->data[$name])) $this->data[$name] = Model_Faculty::with(parent::__get('FacultyID')); return parent::__get($name); } /** * @param $id int discipline id * @return array data from <tt>view_disciplines</tt> table * @throws HTTP_Exception if discipline does not exist */ protected function getRawData($id) { $sql = 'SELECT * FROM Discipline_GetInfo(:id)'; $info = DB::query(Database::SELECT, $sql) ->param(':id', $id)->execute(); if ($info->count() == 0) throw new InvalidArgumentException(Error::DISCIPLINE_NOT_FOUND); return $info->offsetGet(0); } /** * @param $id int submodule id * @return array data from <tt>view_disciplines</tt> table * @throws HTTP_Exception if discipline does not exist */ protected function getRawDataBySubmoduleID($id) { $sql = 'SELECT * FROM Discipline_GetInfoBySubmodule(:id)'; $info = DB::query(Database::SELECT, $sql) ->param(':id', $id)->execute(); if ($info->count() == 0) throw new InvalidArgumentException(Error::DISCIPLINE_NOT_FOUND); return $info->offsetGet(0); } /** * Creation of new discipline from raw data. * @return Model_Helper_DisciplineBuilder * todo: may be we need a factory pattern */ static public function make() { return new Model_Helper_DisciplineBuilder(); } /** * Create new discipline in db, based on $data. */ protected function create() { $sql = 'SELECT * FROM Discipline_Create(AuthorID, GradeID, SubjectID, Type, Lectures, Practice, Labs, FacultyID, SemesterID, Subtype) AS "ID"'; $this->data[self::$ID_FIELD] = DB::query(Database::SELECT, $sql) ->parameters($this->data) ->execute()[0]['ID']; } public function delete() { $sql = 'SELECT * FROM Discipline_Delete(:id)'; DB::query(Database::SELECT, $sql)->param(':id', $this->ID)->execute(); } public function getInternalInfo() { $sql = 'SELECT * FROM discipline_get_internals(:id)'; return DB::query(Database::SELECT, $sql) ->param(':id', $this->ID) ->execute()->as_array(); } // todo: should return Model_Group[] public function getGroups() { $sql = 'SELECT * FROM GetGroupsForDiscipline(:id)'; return DB::query(Database::SELECT, $sql) ->param(':id', $this->ID) ->execute()->as_array(); } /** Get groups with separately attached students. */ public function getAllGroups() { // http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/50 // для получения списка групп для всех дисциплин на странице преподавателя // нужно сделать несколько запросов к GetGroupsForDisciplineAll // за одно подключение к базе данных // но тогда функция возвращает один и тот же ответ // поэтому каждый раз подключаемся заново $db = Kohana_Database::instance(); $db->disconnect(); $sql = 'SELECT * FROM GetGroupsForDisciplineAll(:id)'; return DB::query(Database::SELECT, $sql)->param(':id', $this->ID)->execute(); } /** @return Model_Student[] */ public function getStudents() { return Model_Students::ofDiscipline($this); } // todo: should return Model_Teacher[] public function getTeachers() { $sql = 'SELECT * FROM GetTeachersForDiscipline(:id)'; return DB::query(Database::SELECT, $sql) ->param(':id', $this->ID)->execute(); } public function hasTeacher($teacherID) { $sql = 'SELECT * FROM InternalIsTeacherBound(:teacher, :discipline) AS "res"'; return DB::query(Database::SELECT, $sql) ->param(':discipline', $this->ID) ->param(':teacher', $teacherID) ->execute()->get('res'); } public function bind(Model_Teacher $teacher) { if ($this->ID == $teacher->ID) return; $sql = 'SELECT * FROM Discipline_BindTeacher(:id, :teacher)'; DB::query(Database::SELECT, $sql) ->param(':teacher', $teacher->ID) ->param(':id', $this->ID) ->execute(); } public function unbind(Model_Teacher $teacher) { if ($this->ID == $teacher->ID) return; $sql = 'SELECT * FROM Discipline_UnbindTeacher(:id, :teacher)'; DB::query(Database::SELECT, $sql) ->param(':teacher', $teacher->ID) ->param(':id', $this->ID) ->execute(); } /** * Bind teacher and delegate him the discipline. * @param Model_Teacher $teacher */ public function delegateTo(Model_Teacher $teacher) { if ($this->ID == $teacher->ID) return; $sql = 'SELECT * FROM Discipline_Delegate(:id, :teacher)'; DB::query(Database::SELECT, $sql) ->param(':teacher', $teacher->ID) ->param(':id', $this->ID) ->execute(); } public function changeGradeUnsafe($grade) { if ($this->GradeID == $grade) return 0; $sql = 'SELECT * FROM Discipline_SetGradeUnsafe(:discipline, :grade) AS "ErrorCode"'; return DB::query(Database::SELECT, $sql) ->parameters([ ':discipline' => $this->ID, ':grade' => $grade, ])->execute()->get('"ErrorCode"'); } public function changeGrade($teacherID, $grade) { if (($this->AuthorID == $teacherID) && $this->IsLocked !== true){ return $this->changeGradeUnsafe($grade); } return -1; } /** * Time machine for discipline. * @param $stage int number from 0 to 3 */ public function setMilestone($stage) { if ($stage < 0 || $stage > 3) throw new LogicException('Milestone argument is incorrect!'); $this->Milestone = $stage; $sql = 'SELECT * FROM RestrictAfterMilestone(:discipline, :milestone)'; DB::query(Database::SELECT, $sql) ->parameters([ ':discipline' => $this->ID, ':milestone' => $stage, ])->execute(); } // ищет межфакультетские дисциплины по семестру, ведущему факультету, предмету и типу // межфакультетскими считает все дисциплины, которые не связаны с учебными планами public static function find_global($semesterID, $subjectID, $type, $facultyID) { $sql = 'SELECT * FROM Discipline_Find_Global(:semesterID, :subjectID, :type, :facultyID) AS "ID"'; $data = DB::query(Database::SELECT, $sql) ->parameters([ ':semesterID' => $semesterID, ':subjectID' => $subjectID, ':type' => $type, ':facultyID' => $facultyID ])->execute(); $cnt = count($data); if ($cnt > 1) { throw new Database_Exception('There are '.$cnt.' global disciplines found, but only one was expected!'); } elseif ($cnt == 1) { return Model_Discipline::load($data[0]['ID']); } return null; } public static function find($studyPlanID, $semesterID, $subjectID, $type) { $sql = 'SELECT * FROM Discipline_Find(:studyPlanID, :semesterID, :subjectID, :type) AS "ID"'; $data = DB::query(Database::SELECT, $sql) ->parameters([ ':studyPlanID' => $studyPlanID, ':semesterID' => $semesterID, ':subjectID' => $subjectID, ':type' => $type, ])->execute(); $cnt = count($data); if ($cnt > 1) { throw new Database_Exception('There are '.$cnt.' disciplines found, but only one was expected!'); } elseif ($cnt == 1) { return Model_Discipline::load($data[0]['ID']); } return null; } // TODO: доделать этот метод http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/362 public function update() { throw new BadMethodCallException('Method is not implemented yet!'); // тут нужно делать апдейт записи в БД по полям уже указанным в модели // $sql = 'SELECT * FROM Discipline_ChangeInfo(ID, AuthorID, GradeID, SubjectID, Type, Lectures, Practice, // Labs, FacultyID, SemesterID, Subtype) AS "Success"'; // $res = DB::query(Database::SELECT, $sql) // ->parameters($this->getRawData($this->ID)) // ->execute(); // return $res['Success']; } public function clearModules($teacherID) { $map = Model_Map::of($this); $modules = $map->getModules('all'); try { foreach ($modules as $record) { if ($record['Type'] != 'extra' && $record['Type'] != 'exam') { $deleted = Model_Map::deleteModule($teacherID, $record['ID']); if ($deleted) { return 1; } } } } catch (Exception $e) { return 0; } return 1; } public function hasModules() { $sql = 'SELECT * FROM Discipline_hasMap(:discipline) as "Num"'; $res = DB::query(Database::SELECT, $sql) ->parameters([ ':discipline' => $this->ID ])->execute()->get("Num"); return $res; } public function setInactive() { $sql = 'SELECT * FROM Discipline_setInactive(:discipline) as "Num"'; $res = DB::query(Database::SELECT, $sql) ->parameters([ ':discipline' => $this->ID ])->execute()->get("Num"); return $res; } public function setActive() { $sql = 'SELECT * FROM Discipline_setActive(:discipline) as "Num"'; $res = DB::query(Database::SELECT, $sql) ->parameters([ ':discipline' => $this->ID ])->execute()->get("Num"); return $res; } public function copyDisciplineMapFrom($disciplineToID, $disciplineFromID) { $sql = 'SELECT * FROM copy_map(:from, :to) as "Num"'; return DB::query(Database::SELECT, $sql) ->parameters([ ':from' => $disciplineFromID, ':to' => $disciplineToID, ])->execute()->get("Num"); } public function copyDisciplineStructureFrom($teacherID, $disciplineFromID) { $mapFrom = Model_Map::getRoadmap($disciplineFromID, 'all'); $mapTo = Model_Map::of($this); $prevModuleID = 0; $moduleID = null; foreach ($mapFrom as $record) { // проверка повтотрения модуля if ($prevModuleID != (int)$record['ModuleID']) { $prevModuleID = (int)$record['ModuleID']; // копируем текущий модуль if ($record['ModuleType'] == 'regular') { $moduleID = $mapTo->addModule($teacherID, $record['ModuleName']); } elseif ($record['ModuleType'] == 'bonus') { $moduleID = $mapTo->addModuleBonus($teacherID); } else { break; } } // копируем текуще мероприятие (Submodule) Model_Map::addSubmodule($teacherID, $moduleID, $record['SubmoduleType'], $record['MaxRate'], $record['SubmoduleName']); } } public function isTaskOpen($recordbook, $modulenumber) { $sql = 'SELECT * FROM CheckTaskOpen(:discipline, :modulenumber, :recordbookid) AS "res"'; return DB::query(Database::SELECT, $sql) ->param(':discipline', $this->ID) ->param(':modulenumber', $modulenumber) ->param(':recordbookid', $recordbook) ->execute()->get('res'); } }