diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php')
| -rw-r--r-- | lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php | 563 |
1 files changed, 0 insertions, 563 deletions
diff --git a/lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php b/lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php deleted file mode 100644 index 63275f0..0000000 --- a/lib/admissionrules/conditionaladmission/ConditionalAdmission.class.php +++ /dev/null @@ -1,563 +0,0 @@ -<?php - -/** - * ConditionalAdmission.class.php - * - * An admission rule that specifies conditions for course admission, like - * degree, study course or semester. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author Thomas Hackl <thomas.hackl@uni-passau.de> - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - */ - -class ConditionalAdmission extends AdmissionRule -{ - // --- ATTRIBUTES --- - - /** - * All conditions that must be fulfilled for successful admission. - */ - public $conditions = []; - - /** - * Grouped conditions that must be fulfilled for successful admission. - */ - public $conditiongroups = []; - - /** - * Conditions that must be fulfilled for successful admission. - */ - public $ungrouped_conditions = []; - - /** - * Quota for grouped conditions - */ - public $quota = []; - - /** - * Are condition groups allowed? - */ - public $conditiongroups_allowed = null; - - /** - * courseset siblings of this rule - */ - public $siblings = []; - - // --- OPERATIONS --- - - /** - * Standard constructor. - * - * @param String $ruleId If this rule has been saved previously, it - * will be loaded from database. - * @return ConditionalAdmission the current object (this). - */ - public function __construct($ruleId='', $courseSetId = '') - { - parent::__construct($ruleId, $courseSetId); - $this->default_message = _('Sie erfüllen nicht die Bedingung: %s'); - if ($ruleId) { - $this->load(); - } else { - $this->id = $this->generateId('conditionaladmissions'); - } - return $this; - } - - /** - * Adds a new UserFilter to this rule. - * - * @param UserFilter $condition - * @param String $group - * @param Int $quota - * @return ConditionalAdmission - */ - public function addCondition($condition, $group = '', $quota = 0) - { - if ($group) { - $this->conditiongroups[$group][$condition->getId()] = $condition; - $this->quota[$group] = $quota; - } else { - $this->ungrouped_conditions[$condition->getId()] = $condition; - } - return $this; - } - - /** - * Deletes the admission rule and all associated data. - */ - public function delete() - { - parent::delete(); - // Delete rule data. - $stmt = DBManager::get()->prepare("DELETE FROM `conditionaladmissions` - WHERE `rule_id`=?"); - $stmt->execute([$this->id]); - // Delete all associated conditions... - foreach ($this->ungrouped_conditions as $condition) { - $condition->delete(); - } - foreach ($this->conditiongroups as $conditions) { - foreach ($conditions as $condition) { - $condition->delete(); - } - } - // ... and their connection to this rule. - $stmt = DBManager::get()->prepare("DELETE `admission_condition`, `admission_conditiongroup` FROM `admission_condition` - LEFT JOIN `admission_conditiongroup` USING( `conditiongroup_id`) - WHERE `rule_id`=?"); - $stmt->execute([$this->id]); - } - - /** - * Gets all users that are matched by thís rule. - * - * @return Array An array containing IDs of users who are matched by - * this rule. - */ - public function getAffectedUsers() - { - $users = []; - foreach ($this->ungrouped_conditions as $condition) { - $users = array_intersect($users, $condition->getAffectedUsers()); - } - foreach ($this->conditiongroups as $conditions) { - foreach ($conditions as $condition) { - $users = array_intersect($users, $condition->getAffectedUsers()); - } - } - return $users; - } - - /** - * Gets all defined conditions. - * - * @return Array - */ - public function getConditions() - { - return $this->conditions; - } - - /** - * Gets all grouped conditiongroups. - * - * @return Array - */ - public function getConditionGroups() - { - return $this->conditiongroups; - } - - /** - * Gets all grouped conditiongroups. - * - * @return Array - */ - public function getUngroupedConditions() - { - return $this->ungrouped_conditions; - } - - /** - * Gets quota for given conditiongroup. - * - * @return Array - */ - public function getQuota($group_id) - { - return $this->quota[$group_id]; - } - - /** - * Gets some text that describes what this AdmissionRule (or respective - * subclass) does. - */ - public static function getDescription() - { - return _('Über eine Menge von Bedingungen kann festgelegt werden, '. - 'wer zur Anmeldung zu den Veranstaltungen des Anmeldesets '. - 'zugelassen ist. Es muss nur eine der Bedingungen erfüllt sein, '. - 'innerhalb einer Bedingung müssen aber alle Datenfelder '. - 'zutreffen.'); - } - - /** - * Return this rule's name. - */ - public static function getName() - { - return _('Bedingte Anmeldung'); - } - - /** - * Gets the template that provides a configuration GUI for this rule. - * - * @return String - */ - public function getTemplate() - { - // Open generic admission rule template. - $tpl = $GLOBALS['template_factory']->open('admission/rules/configure'); - $tpl->set_attribute('rule', $this); - $factory = new Flexi_TemplateFactory(dirname(__FILE__).'/templates/'); - // Now open specific template for this rule and insert base template. - $tpl2 = $factory->open('configure'); - $tpl2->set_attribute('rule', $this); - $tpl2->set_attribute('tpl', $tpl->render()); - return $tpl2->render(); - } - - /** - * Helper function for loading data from DB. Generic AdmissionRule data is - * loaded with the parent load() method. - */ - public function load() - { - // Load basic data. - $stmt = DBManager::get()->prepare("SELECT * - FROM `conditionaladmissions` WHERE `rule_id`=? LIMIT 1"); - $stmt->execute([$this->id]); - if ($current = $stmt->fetch(PDO::FETCH_ASSOC)) { - $this->message = $current['message']; - $this->startTime = $current['start_time']; - $this->endTime = $current['end_time']; - // Retrieve conditions. - $stmt = DBManager::get()->prepare("SELECT * - FROM `admission_condition` LEFT JOIN `admission_conditiongroup` USING (`conditiongroup_id`) WHERE `rule_id`=?"); - $stmt->execute([$this->id]); - $conditions = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($conditions as $condition) { - $currentCondition = new UserFilter($condition['filter_id']); - if ($condition['conditiongroup_id']) { - $this->conditiongroups[$condition['conditiongroup_id']][$condition['filter_id']] = $currentCondition; - $this->quota[$condition['conditiongroup_id']] = $condition['quota']; - } else { - $this->ungrouped_conditions[$condition['filter_id']] = $currentCondition; - } - } - } - } - - /** - * Checks if condition groups are allowed. - * - * @return Boolean - */ - public function conditiongroupsAllowed() - { - if ($this->conditiongroups_allowed === null) { - foreach ($this->getSiblings() as $rule) { - if (get_class($rule) == 'ParticipantRestrictedAdmission') { - if ($rule->getDistributionTime() > time()) { - $this->conditiongroups_allowed = true; - } - } - } - } - return $this->conditiongroups_allowed; - } - - /** - * Removes condition groups and sets all conditions as ungrouped. - * - */ - public function removeConditionGroups() - { - foreach ($this->conditiongroups as $conditiongroup_id => $conditions) { - foreach ($conditions as $condition_id => $condition) { - $this->ungrouped_conditions[$condition_id] = $condition; - } - } - $this->conditiongroups = []; - } - - /** - * Removes the condition with the given ID from the rule. - * - * @param String $conditionId - * @return ConditionalAdmission - */ - public function removeCondition($conditionId) - { - if (isset($this->ungrouped_conditions[$conditionId])) { - $this->ungrouped_conditions[$conditionId]->delete(); - unset($this->ungrouped_conditions[$conditionId]); - } else { - foreach ($this->conditiongroups as $conditiongroup_id => $conditions) { - if (isset($conditions[$conditionId])) { - $this->conditiongroups[$conditiongroup_id]->conditions[$conditionId]->delete(); - unset($this->conditiongroups[$conditiongroup_id]->conditions[$conditionId]); - } - } - } - return $this; - } - - /** - * Checks whether the given user fulfills the configured - * admission conditions. Only one of the conditions needs to be - * fulfilled (logical operator OR). The fields in a condition are - * in conjunction (logical operator AND). - * - * @param String $userId - * @param String $courseId - * @return Array Array with conditions that have failed. If array - * is empty, everything's all right. - */ - public function ruleApplies($userId, $courseId) - { - $failed = []; - // Check for rule validity time frame. - if ($this->checkTimeFrame()) { - // Check all configured conditions. - foreach ($this->ungrouped_conditions as $condition) { - if (!$condition->isFulfilled($userId)) { - $failed[] = $this->getMessage($condition->toString()); - } else { - $failed = []; - break; - } - } - foreach ($this->conditiongroups as $conditions) { - foreach ($conditions as $condition) { - if (!$condition->isFulfilled($userId)) { - $failed[] = $this->getMessage($condition->toString()); - } else { - $failed = []; - break 2; - } - } - } - } - return $failed; - } - - /** - * Uses the given data to fill the object values. This can be used - * as a generic function for storing data if the concrete rule type - * isn't known in advance. - * - * @param Array $data - * @return AdmissionRule This object. - */ - public function setAllData($data) - { - UserFilterField::getAvailableFilterFields(); - parent::setAllData($data); - $this->conditions = []; - $this->ungrouped_conditions = []; - $this->conditiongroups = []; - $this->quota = []; - foreach ($data['conditions'] as $ser_con) { - $condition = ObjectBuilder::build($ser_con, 'UserFilter'); - $this->addCondition($condition, $data['conditiongroup_'.$condition->getId()], $data['quota_'.$data['conditiongroup_'.$condition->getId()]] ?? 0); - } - foreach ($this->getConditiongroups() as $conditiongroup_id => $conditions) { - if (mb_strlen($conditiongroup_id) < 32) { - $group = md5(uniqid('conditiongroups' . microtime(), true)); - - $this->conditiongroups[$group] = $this->conditiongroups[$conditiongroup_id]; - unset($this->conditiongroups[$conditiongroup_id]); - - $this->quota[$group] = $this->quota[$conditiongroup_id]; - unset($this->quota[$conditiongroup_id]); - } - } - if (count($this->getConditiongroups()) && $data['conditiongroups_allowed']) { - $this->conditiongroups_allowed = true; - } - - return $this; - } - - /** - * Helper function for storing data to DB. - */ - public function store() - { - // Store rule data. - $stmt = DBManager::get()->prepare("INSERT INTO `conditionaladmissions` - (`rule_id`, `message`, `start_time`, `end_time`, `mkdate`, `chdate`) - VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - `message`=VALUES(`message`), - `start_time`=VALUES(`start_time`), - `end_time`=VALUES(`end_time`), - `chdate`=VALUES(`chdate`)"); - $stmt->execute([$this->id, $this->message, (int)$this->startTime, - (int)$this->endTime, time(), time()]); - // prepare condition data. - $keys = array_keys($this->ungrouped_conditions); - foreach ($this->conditiongroups as $conditiongroup_id => $conditions) { - $keys = array_merge($keys, array_keys($conditions)); - } - - // Delete removed conditions from DB. - $stmt = DBManager::get()->prepare("SELECT `filter_id`, `conditiongroup_id` FROM - `admission_condition` WHERE `rule_id`=? AND `filter_id` NOT IN ('". - implode("', '", $keys)."')"); - $stmt->execute([$this->id]); - $groups = []; - foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $entry) { - $current = new UserFilter($entry['filter_id']); - $current->delete(); - $groups[] = $entry['conditiongroup_id']; - } - DBManager::get()->exec("DELETE FROM `admission_condition` - WHERE `rule_id`='".$this->id."' AND `filter_id` NOT IN ('". - implode("', '", $keys)."')"); - // Store all conditions. - $queries = []; - $parameters = []; - $groupqueries = []; - $groupparameters = []; - foreach ($this->ungrouped_conditions as $condition) { - // Store each ungrouped condition... - $condition->store(); - $queries[] = "(?, ?, ?, ?)"; - $parameters[] = $this->id; - $parameters[] = $condition->getId(); - $parameters[] = ''; - $parameters[] = time(); - } - - foreach ($this->conditiongroups as $conditiongroup_id => $conditions) { - $groupqueries[] = "(?, ?)"; - $groupparameters[] = $conditiongroup_id; - $groupparameters[] = $this->quota[$conditiongroup_id]; - foreach ($conditions as $condition) { - // Store each group of conditions... - $condition->store(); - $queries[] = "(?, ?, ?, ?)"; - $parameters[] = $this->id; - $parameters[] = $condition->getId(); - $parameters[] = $conditiongroup_id; - $parameters[] = time(); - } - } - - // Store all assignments between rule and condition. - if (count($queries) > 0) { - $stmt = DBManager::get()->prepare("INSERT INTO `admission_condition` - (`rule_id`, `filter_id`, `conditiongroup_id`, `mkdate`) - VALUES " . implode(',', $queries) . " ON DUPLICATE KEY UPDATE - `filter_id`=VALUES(`filter_id`), `conditiongroup_id`=VALUES(`conditiongroup_id`)"); - $stmt->execute($parameters); - } - - // Store all assignments between condition and conditiongroup. - if (count($groupqueries) > 0) { - $stmt = DBManager::get()->prepare("INSERT INTO `admission_conditiongroup` - (`conditiongroup_id`, `quota`) - VALUES " . implode(',', $groupqueries) . " ON DUPLICATE KEY UPDATE - `quota`=VALUES(`quota`)"); - $stmt->execute($groupparameters); - } - - return $this; - } - - /** - * A textual description of the current rule. - * - * @return String - */ - public function toString() - { - $factory = new Flexi_TemplateFactory(dirname(__FILE__).'/templates/'); - $tpl = $factory->open('info'); - $tpl->set_attribute('rule', $this); - return $tpl->render(); - } - - /** - * Validates if the given request data is sufficient to configure this rule - * (e.g. if required values are present). - * - * @param Array $data Request data - * @return Array Error messages. - */ - public function validate($data) - { - $errors = parent::validate($data); - if (!$data['conditions'] || !is_array($data['conditions'])) { - $errors[] = _('Es muss mindestens eine Auswahlbedingung angegeben werden.'); - return $errors; - } - $quota = []; - $quota_total = 0; - $grouped = 0; - $ungrouped = 0; - $no_quota = 0; - foreach ($data['conditions'] as $ser_con) { - $condition = ObjectBuilder::build($ser_con, 'UserFilter'); - if ($data['conditiongroup_'.$condition->getId()]) { - $grouped++; - } else { - $ungrouped++; - } - $quota[$data['conditiongroup_' . $condition->getId()]] = $data['quota_' . $data['conditiongroup_' . $condition->getId()]] ?? 0; - if (!$quota[$data['conditiongroup_' . $condition->getId()]]) { - $no_quota++; - } - } - foreach ($quota as $part) { - $quota_total += $part; - } - if ($grouped && $ungrouped) { - $errors[] = sprintf(_('Es müssen entweder alle Bedingungen Teil einer Gruppe sein, oder keine. %s Bedingungen sind keiner Gruppe zugeordnet.'), $ungrouped); - } elseif ($grouped && $quota_total !== 100) { - $errors[] = _('Die Gesamtsumme der Kontingente muss 100 Prozent betragen.'); - } elseif ($grouped && $no_quota) { - $errors[] = sprintf(_('Für %s Gruppen muss noch ein Kontingent festgelegt werden.'), $no_quota); - } - return $errors; - } - - public function getMessage($condition = null) - { - $message = parent::getMessage(); - if ($condition) { - return sprintf($message, $condition); - } else { - return $message; - } - } - - public function __clone() - { - $this->id = md5(uniqid(get_class($this))); - $this->courseSetId = null; - $cloned_conditions = []; - foreach ($this->ungrouped_conditions as $condition) { - $dolly = clone $condition; - $cloned_conditions[$dolly->id] = $dolly; - } - $this->ungrouped_conditions = $cloned_conditions; - $cloned_conditiongroups = []; - $cloned_quota = []; - foreach ($this->conditiongroups as $conditiongroup_id => $conditions) { - $cloned_conditiongroup_id = md5(uniqid($conditiongroup_id)); - $cloned_quota[$cloned_conditiongroup_id] = $this->quota[$conditiongroup_id]; - foreach ($conditions as $condition) { - $dolly = clone $condition; - $cloned_conditiongroups[$cloned_conditiongroup_id][$dolly->id] = $dolly; - } - } - $this->conditiongroups = $cloned_conditiongroups; - $this->quota = $cloned_quota; - } - - public function setSiblings($siblings = []) - { - parent::setSiblings($siblings); - $this->conditiongroups_allowed = null; - } -} |
