Skip to content
Snippets Groups Projects
Forked from it-lab / grade
Source project has a limited visibility.
Discipline.php 8.07 KiB
<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Class Model_Discipline
 *
 * @property-read $ID int
 * @property $authorID int
 * @property $gradeID int
 * @property $gradeNum int
 * @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 $milestone mixed
 */
class Model_Discipline extends Model implements JsonSerializable, ArrayAccess
{
    private $data;

    /**
     * @var bool
     * Indicates whether data was loaded from db.
     */
    private $loaded = false;

    /**
     * @var bool
     * Allow to load data from database, if current
     * object instance does not contains some fields.
     */
    private $lazy = true;

    /**
     * @param $data array
     * Source data for building the object.
     * @param $associated bool
     * Indicates whether object exists in db.
     * @param $lazyLoading bool
     * Indicates whether lazy loading can be used.
     */
    function __construct(array & $data, $associated = true, $lazyLoading = true) {
        $this->data = $data;
        $this->lazy = $lazyLoading;
        if (!$associated || !isset($data['ID']))
            $this->create();
    }

    /**
     * Creation of new discipline from raw data.
     * @return Model_Helper_DisciplineBuilder
     */
    static public function make() {
        return new Model_Helper_DisciplineBuilder();
    }

    /**
     * Load the discipline from database.
     * @param $id int  discipline id
     * @return $this  new instance
     */
    static public function load($id) {
        if (!is_numeric($id) || $id <= 0)
            throw new InvalidArgumentException(Error::ID_IS_INCORRECT);

        // lazy loading
        $data['ID'] = (int) $id;
        return new self($data, true);
    }

    /**
     * Create new discipline in db, based on $data.
     */
    private function create() {
        $sql = "SELECT `Discipline_Create`(authorID, gradeID, subjectID, type, lectures, practice, labs, facultyID, semesterID, NULL) AS `Num`;";

        $this->data['ID'] = DB::query(Database::SELECT, $sql)
            ->parameters($this->data)
            ->execute()[0]['Num'];

        $this->data['subtype'] = null;
        $this->data['isLocked'] = false;
//        $this->data['milestone'] = 0;     # todo: what is it?
    }

    public function delete() {
        $sql = "SELECT `Discipline_Delete`(:id);";
        DB::query(Database::SELECT, $sql)->param(':id', $this->ID)->execute();
    }

    // todo: should return Model_Group[]
    public function getGroups() {
        $sql = "CALL `GetGroupsForDiscipline`(:id);";
        return DB::query(Database::SELECT, $sql)
            ->param(':id', $this->data['ID'])
            ->execute()->as_array();
    }

    // todo: should return Model_Teacher[]
    public function getTeachers() {
        $sql = "CALL `GetTeachersForDiscipline`(:id)";
        return DB::query(Database::SELECT, $sql)
            ->param(':id', $this->data['ID'])->execute();
    }

    public function bind(Model_Teacher $teacher) {
        if ($this->ID == $teacher->ID)
            return;

        $sql = "SELECT `Discipline_BindTeacher`(:id, :teacher)";
        DB::query(Database::SELECT, $sql)
            ->param(':teacher', $teacher->ID)
            ->param(':id', $this->data['ID'])
            ->execute();
    }

    public function unbind(Model_Teacher $teacher) {
        if ($this->ID == $teacher->ID)
            return;

        $sql = "SELECT `Discipline_UnbindTeacher`(:id, :teacher)";
        DB::query(Database::SELECT, $sql)
            ->param(':teacher', $teacher->ID)
            ->param(':id', $this->data['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 `Discipline_Delegate`(:id, :teacher)";
        DB::query(Database::SELECT, $sql)
            ->param(':teacher', $teacher->ID)
            ->param(':id', $this->data['ID'])
            ->execute();
    }


    function __get($name) {
        // if value has already been loaded
        if (array_key_exists($name, $this->data))
            return $this->data[$name];

        // if no, then make query to db
        $this->loadData();
        if (array_key_exists($name, $this->data))
            return $this->data[$name];

        throw new ErrorException('No such field or property');
    }

    function __set($name, $value) {
        if ($name == 'ID')
            throw new BadMethodCallException();
        $this->data[$name] = $value;
    }

    private function loadData() {
        if (!$this->loaded && $this->lazy) {
            $this->data = array_merge($this->data, self::getInfo($this->data['ID']));
            $this->loaded = true;
        }
    }

    /**
     * Specify data which should be serialized to JSON
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
     * @return mixed data which can be serialized by <b>json_encode</b>,
     * which is a value of any type other than a resource.
     */
    function jsonSerialize($forceLoad = true) {
        if ($forceLoad)
            $this->loadData();
        return $this->data;
    }

    public function offsetExists($name) {
        if (array_key_exists($name, $this->data))
            return true;

        $this->loadData();
        return array_key_exists($name, $this->data);
    }

    public function offsetGet($offset) {
        return $this->__get($offset);
    }

    public function offsetSet($offset, $value) {
        $this->__set($offset, $value);
    }

    public function offsetUnset($offset) {
        throw new BadMethodCallException();
        // this method may be confused by lazy loading
    }

    /** @deprecated */
    public function toArray() {
        $this->loadData();
        return $this->data;
    }


    # don't use these functions

    /**
     * @param $id int discipline id
     * @return array data from <tt>view_disciplines</tt> table
     * @throws HTTP_Exception if discipline does not exist
     */
    public static function getInfo($id) {
        $sql = "CALL `GetDisciplineInfo`('$id'); ";
        $info = DB::query(Database::SELECT, $sql)->execute();

        if ($info->count() == 0)
            throw new InvalidArgumentException(Error::DISCIPLINE_NOT_FOUND);
        return $info->offsetGet(0);
    }


    /** Change grade. */
    public static function changeGrade($DisciplineID, $teacherID, $Grade) {
        $sql = "SELECT `ChangeDisciplineGrade`('$teacherID', '$DisciplineID', '$Grade') AS `Num`;";
        return DB::query(Database::SELECT, $sql)->execute();
    }

    /**
     * @param $teacherID int
     * @param $disciplineID int
     * @param $milestone int
     * @return Database_Result
     */
    public static function setMilestone($teacherID, $disciplineID, $milestone) {
        $sql = "SELECT `RestrictAfterMilestone`('$teacherID', '$disciplineID', '$milestone') AS 'Num'";
        return DB::query(Database::SELECT, $sql)->execute();
    }

    /**
     * @param $facultyID int
     * @param $semesterID int
     * @return Database_Result
     */
    public static function getMilestone($facultyID, $semesterID) {
        $sql = "SELECT `GetMilestone`('$facultyID', '$semesterID') AS 'Num'";
        return DB::query(Database::SELECT, $sql)->execute();
    }


    /**
     * @param $teacherID int
     * @param $facultyID int
     * @param $milestone int
     * @return Database_Result
     */
    public static function setMilestoneForCredits($teacherID, $facultyID, $milestone) {
        $semesterID = User::instance()->offsetGet('SemesterID');
        $sql = "SELECT `RestrictAfterMilestoneForCredits`('$teacherID', '$facultyID', '$milestone', $semesterID) AS 'Num'";
        return DB::query(Database::SELECT, $sql)->execute();
    }

}