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/classes/DataFieldEntry.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/DataFieldEntry.php')
| -rw-r--r-- | lib/classes/DataFieldEntry.php | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/lib/classes/DataFieldEntry.php b/lib/classes/DataFieldEntry.php new file mode 100644 index 0000000..eca0b4a --- /dev/null +++ b/lib/classes/DataFieldEntry.php @@ -0,0 +1,588 @@ +<?php +/** + * DataFieldEntry.php + * + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @author Marcus Lunzenauer <mlunzena@uos.de> + * @author Martin Gieseking <mgieseki@uos.de> + * @license GPL2 or any later version + */ +abstract class DataFieldEntry +{ + protected static $supported_types = [ + 'bool', + 'textline', + 'textlinei18n', + 'textarea', + 'textareai18n', + 'textmarkup', + 'textmarkupi18n', + 'selectbox', + 'selectboxmultiple', + 'date', + 'time', + 'email', + 'phone', + 'radio', + 'combo', + 'link', + ]; + + protected $language = ''; + protected $template = null; + + /** + * Returns all supported datafield types. + * + * @param string Object type of the datafield. + * @return array of supported types + */ + public static function getSupportedTypes($object_type = null) + { + // no i18n fields for descriptors + if (in_array($object_type, ['moduldeskriptor', 'modulteildeskriptor'])) { + return array_diff( + self::$supported_types, + [ + 'textlinei18n', + 'textareai18n', + 'textmarkupi18n' + ]); + } + return self::$supported_types; + } + + /** + * Returns the according class for a given type. + * + * @param String $type Type of the datafield + * @return String class name + */ + private static function getClassForType($type) + { + if ($type === 'selectboxmultiple') { + return 'DataFieldSelectboxMultipleEntry'; + } + return 'DataField' . ucfirst($type) . 'Entry'; + } + + /** + * Factory method that returns the appropriate datafield object + * for the given parameters. + * + * @param DataField $datafield Underlying structure + * @param String $rangeID Range id + * @param mixed $value Value of the entry + * @return DataFieldEntry instance of appropriate type + */ + public static function createDataFieldEntry(DataField $datafield, $rangeID = '', $value = null) + { + $type = $datafield->type; + if (!in_array($type, self::getSupportedTypes())) { + return false; + } + + $entry_class = self::getClassForType($type); + $entry = new $entry_class($datafield, $rangeID, $value); + + return $entry; + } + + /** + * Enter description here... + * + * @param string $range_id + * @param string $object_type + * @param string $object_class_hint + * @return array + */ + public static function getDataFieldEntries($range_id, $object_type = '', $object_class_hint = '') + { + if (!$range_id) { + return []; // we necessarily need a range ID + } + $parameters = []; + $clause1 = ''; + $clause2 = ''; + $clause3 = ''; + if(is_array($range_id)) { + // rangeID may be an array ("classic" rangeID and second rangeID used for user roles) + $secRangeID = $range_id[1]; + $rangeID = $range_id[0]; // to keep compatible with following code + if('usersemdata' !== $object_type && 'roleinstdata' !== $object_type) { + $object_type = 'userinstrole'; + } + $clause1 = "AND sec_range_id= :sec_range_id"; + $parameters[':sec_range_id'] = $secRangeID; + } else { + $rangeID = $range_id; + } + if (!$object_type) { + $object_type = get_object_type($rangeID); + } + + if($object_type) { + switch ($object_type) { + case 'sem': + if ($object_class_hint) { + $object_class = SeminarCategories::GetByTypeId($object_class_hint); + } else { + $object_class = SeminarCategories::GetBySeminarId($rangeID); + } + + $clause2 = "object_class = :object_class OR object_class IS NULL"; + $parameters[':object_class'] = (int) $object_class->id; + $clause3 = 'a.institut_id IS NULL OR a.institut_id IN (:institut_ids)'; + $query = "SELECT institut_id FROM seminar_inst WHERE seminar_id = :seminar_id"; + $statement = DBManager::get()->prepare($query); + $statement->execute([':seminar_id' => $rangeID]); + $parameters[':institut_ids'] = array_keys($statement->fetchGrouped()); + break; + case 'inst': + case 'fak': + + if ($object_class_hint) { + $object_class = $object_class_hint; + } else { + $query = "SELECT type FROM Institute WHERE Institut_id = ?"; + $statement = DBManager::get()->prepare($query); + $statement->execute([$rangeID]); + $object_class = $statement->fetchColumn(); + } + $object_type = "inst"; + $clause2 = "object_class = :object_class OR object_class IS NULL"; + $parameters[':object_class'] = (int) $object_class; + $clause3 = 'a.institut_id IS NULL OR a.institut_id = :institut_id'; + $parameters[':institut_id'] = $rangeID; + break; + case 'roleinstdata': //hmm tja, vermutlich so + case 'moduldeskriptor': + case 'modulteildeskriptor': + case 'studycourse': + $clause2 = '1'; + $clause3 = '1'; + if (is_array($range_id) && isset($range_id[0])) { + $clause3 = 'a.institut_id IS NULL OR a.institut_id = :institut_id'; + $parameters[':institut_id'] = $range_id[0]; + } + break; + case 'user': + case 'userinstrole': + case 'usersemdata': + $object_class = is_object($GLOBALS['perm']) ? DataField::permMask($GLOBALS['perm']->get_perm($rangeID)) : 0; + $clause2 = "((object_class & :object_class) OR object_class IS NULL)"; + $parameters[':object_class'] = (int) $object_class; + + $clause3 = 'a.institut_id IS NULL OR a.institut_id IN (:institut_ids)'; + $query = "SELECT institut_id FROM user_inst WHERE user_id = :user_id"; + $statement = DBManager::get()->prepare($query); + $statement->execute([':user_id' => $rangeID]); + $parameters[':institut_ids'] = array_keys($statement->fetchGrouped()); + break; + } + $query = "SELECT a.*, content + FROM datafields AS a + LEFT JOIN datafields_entries AS b + ON (a.datafield_id = b.datafield_id AND range_id = :range_id {$clause1}) + WHERE object_type = :object_type AND ({$clause2}) AND ($clause3) + ORDER BY priority"; + $parameters[':range_id'] = $rangeID; + $parameters[':object_type'] = $object_type; + + $rs = DBManager::get()->prepare($query); + $rs->execute($parameters); + + $entries = []; + while ($data = $rs->fetch(PDO::FETCH_ASSOC)) { + $datafield = DataField::buildExisting($data); + $entries[$data['datafield_id']] = DataFieldEntry::createDataFieldEntry($datafield, $range_id, $data['content']); + } + } + return $entries ?: []; + } + + /** + * Removes all datafields from a given range_id (and secondary range + * id if passed as array) + * + * @param mixed $range_id Range id (or array with range id and secondary + * range id) + * @return int representing the number of deleted entries + */ + public static function removeAll($range_id) + { + if (is_array($range_id)) { + list ($rangeID, $secRangeID) = $range_id; + } else { + $rangeID = $range_id; + $secRangeID = ""; + } + + if (!$rangeID && !$secRangeID) { + return; + } + + $conditions = []; + $parameters = []; + + if ($rangeID) { + $conditions[] = 'range_id = ?'; + $parameters[] = $rangeID; + } + if ($secRangeID) { + $conditions[] = 'sec_range_id = ?'; + $parameters[] = $secRangeID; + } + + $where = implode(' AND ', $conditions); + + return DatafieldEntryModel::deleteBySQL($where, $parameters); + } + + public $value; + public $model; + public $rangeID; + + /** + * Constructs this datafield + * + * @param DataField $datafield Underlying model + * @param mixed $range_id Range id (or array with range id and secondary + * range id) + * @param mixed $value Value + */ + public function __construct(DataField $datafield = null, $rangeID = '', $value = null) + { + $this->model = $datafield; + $this->rangeID = $rangeID; + $this->value = isset($value) ? $value : $datafield->default_value; + } + + /** + * Stores this datafield entry + * + * @return int representing the number of changed entries + */ + public function store() + { + $id = [ + $this->model->id, + (string) $this->getRangeID(), + (string) $this->getSecondRangeID(), + (string) $this->language + ]; + $entry = new DatafieldEntryModel($id); + $entry->lang = (string) $this->language; + + $old_value = $entry->content; + $entry->content = $this->getValue(); + + if ($entry->content == $this->model->default_value) { + $result = $entry->isNew() ? 0 : $entry->delete(); + } else { + $result = $entry->store(); + } + + if ($result) { + NotificationCenter::postNotification('DatafieldDidUpdate', $this, [ + 'changed' => $result, + 'old_value' => $old_value, + ]); + } + + return $result; + } + + /** + * Returns whether this datafield is required + * + * @return bool indicating whether the datafield is required or not + */ + public function isRequired() + { + return $this->model->is_required; + } + + /** + * Returns the description of this datafield + * + * @return String containing the description + */ + public function getDescription() + { + return $this->model->description; + } + + /** + * Returns the type of this datafield + * + * @return string type of entry + */ + public function getType() + { + $class = mb_strtolower(get_class($this)); + return mb_substr($class, 9, mb_strpos($class, 'entry') - 9); + } + + /** + * Returns the display/rendered value of this datafield + * + * @param bool $entities Should html entities be encoded (defaults to true) + * @return String containg the rendered value + */ + public function getDisplayValue($entities = true) + { + if ($entities) { + return htmlReady($this->getValue()); + } + return $this->getValue(); + } + + /** + * Returns the value of the datafield + * + * @return mixed containing the value + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the name of the datafield + * + * @return String containing the name + */ + public function getName() + { + return $this->model->name; + } + + /** + * Returns the id of the datafield + * + * @return String containing the id + */ + public function getId() + { + return $this->model->id; + } + + /** + * Returns the according input elements as html for this datafield + * + * @param String $name Name prefix of the associated input + * @param Array $variables Additional variables + * @return String containing the required html + */ + public function getHTML($name = '', $variables = []) + { + $variables = array_merge([ + 'name' => $name, + 'entry' => $this, + 'model' => $this->model, + 'value' => $this->getValue(), + ], $variables); + + return $GLOBALS['template_factory']->render('datafields/' . $this->template, $variables); + } + + /** + * Sets the value + * + * @param mixed $value The value + */ + public function setValue($value) + { + $this->value = $value; + } + + /** + * Sets the value from a post request + * + * @param mixed $submitted_value The value from request + */ + public function setValueFromSubmit($submitted_value) + { + $this->setValue($submitted_value); + } + + /** + * Sets the range id + * + * @param String $range_id Range id + */ + public function setRangeID($range_id) + { + $this->rangeID = $range_id; + } + + /** + * Sets the secondary range id + * + * @param String $sec_range_id Secondary range id + */ + public function setSecondRangeID($sec_range_id) + { + $this->rangeID = [$this->getRangeID(), $sec_range_id]; + } + + /** + * Sets the prefered content language if this is an i18n datafield. + * + * @param string $language The prefered display language + */ + public function setContentLanguage($language) + { + if (!Config::get()->CONTENT_LANGUAGES[$language]) { + throw new InvalidArgumentException('Language not configured.'); + } + + $languages = array_keys(Config::get()->CONTENT_LANGUAGES); + if ($language == reset($languages)) { + $language = ''; + } + + $this->language = $language; + } + + /** + * Checks if datafield is empty (was not set) + * + * @return bool true if empty, else false + */ + public function isEmpty() + { + return $this->getValue() == ''; + } + + /** + * Returns whether the datafield contents are valid + * + * @return boolean indicating whether the datafield contents are valid + */ + public function isValid() + { + return trim($this->getValue()) + || !$this->model->is_required; + } + + /** + * Returns the number of html fields this datafield uses for input. + * + * @return int representing the number of html fields + */ + public function numberOfHTMLFields() + { + return 1; + } + + /** + * Returns the range id + * + * @return String containing the range id + */ + public function getRangeID() + { + if (is_array($this->rangeID)) { + return reset($this->rangeID); + } + return $this->rangeID; + } + + /** + * Returns the secondary range id + * + * @return String containing the secondary range id + */ + public function getSecondRangeID() + { + if (is_array($this->rangeID)) { + list (, $secRangeID) = $this->rangeID; + return $secRangeID; + } + return ''; + } + + /** + * Returns whether the datafield is visible for the current user + * + * @param String $perm Permissions to test against (optional, default to + * the current user's permissions) + * @param bool $test_ownership Defines whether the ownership of the field + * should be taken into account; a field may + * be invisible for a user according to the + * permissions but since the datafield belongs + * to the user, it is visible. + * @return boolean indicating whether the datafield is visible + */ + public function isVisible($perm = null, $test_ownership = true) + { + if ($test_ownership) { + return $this->model->accessAllowed($perm, + $GLOBALS['user']->id, + $this->getRangeID()); + } + return $this->model->accessAllowed($perm); + } + + /** + * Returns whether the datafield is editable for the current user + * + * @param mixed $perms Perms to test against (optional, defaults to logged + * in user's perms) + * @return boolean indicating whether the datafield is editable + */ + public function isEditable($perms = null) + { + return $this->model->editAllowed($perms ?: $GLOBALS['perm']->get_perm()); + } + + /** + * Returns a human readable string describing the view permissions + * + * @return String containing the descriptons of the view permissions + */ + public function getPermsDescription() + { + if ($this->model->view_perms === 'all') { + return _('sichtbar für alle'); + } + return sprintf(_('sichtbar nur für Sie und alle %s'), + $this->prettyPrintViewPerms()); + } + + /** + * Generates a full status description depending on the the perms + * + * @return string + */ + protected function prettyPrintViewPerms() + { + switch ($this->model->view_perms) { + case 'all': + return _('alle'); + break; + case 'root': + return _('Systemadministrator/-innen'); + break; + case 'admin': + return _('Administrator/-innen'); + break; + case 'dozent': + return _('Lehrenden'); + break; + case 'tutor': + return _('Tutor/-innen'); + break; + case 'autor': + return _('Studierenden'); + break; + case 'user': + return _('Nutzer/-innen'); + break; + } + return ''; + } + +} |
