diff options
| author | Rasmus Fuhse <fuhse@data-quest.de> | 2022-12-16 13:13:32 +0000 |
|---|---|---|
| committer | Rasmus Fuhse <fuhse@data-quest.de> | 2022-12-16 13:13:32 +0000 |
| commit | 653fcaba5a06b8098f9bdb98c051c35a567a4513 (patch) | |
| tree | 4c0cb47566019bbab09401b7287ef188322239b5 /lib | |
| parent | f127f0fb49c0f687f80588e0e1008e95be37d6ce (diff) | |
Resolve "Evaluationen mit Fragebögen"
Closes #703
Merge request studip/studip!363
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/classes/QuestionType.interface.php | 39 | ||||
| -rw-r--r-- | lib/models/Freetext.php | 75 | ||||
| -rw-r--r-- | lib/models/LikertScale.php | 115 | ||||
| -rw-r--r-- | lib/models/Questionnaire.php | 29 | ||||
| -rw-r--r-- | lib/models/QuestionnaireAnswer.php | 4 | ||||
| -rw-r--r-- | lib/models/QuestionnaireInfo.php | 68 | ||||
| -rw-r--r-- | lib/models/QuestionnaireQuestion.php | 25 | ||||
| -rw-r--r-- | lib/models/RangeScale.php | 114 | ||||
| -rw-r--r-- | lib/models/Test.php | 189 | ||||
| -rw-r--r-- | lib/models/Vote.php | 103 | ||||
| -rw-r--r-- | lib/modules/CoreAdmin.class.php | 3 | ||||
| -rw-r--r-- | lib/modules/EvaluationsWidget.php | 4 | ||||
| -rw-r--r-- | lib/navigation/AdminNavigation.php | 2 | ||||
| -rw-r--r-- | lib/navigation/ContentsNavigation.php | 2 | ||||
| -rw-r--r-- | lib/navigation/StartNavigation.php | 15 |
15 files changed, 438 insertions, 349 deletions
diff --git a/lib/classes/QuestionType.interface.php b/lib/classes/QuestionType.interface.php index 342a0bb..ada6005 100644 --- a/lib/classes/QuestionType.interface.php +++ b/lib/classes/QuestionType.interface.php @@ -14,7 +14,14 @@ interface QuestionType { * object but called staticly. * @return Icon the specific icon for this type of question */ - static public function getIcon($active = false, $add = false); + static public function getIcon(bool $active = false) : Icon; + + + /** + * Returns the shape of the icon that is used in vue. + * @return string + */ + static public function getIconShape(); /** * Returns the name of the type of question like "Frage" or "Test" or "Dateiablage" @@ -26,19 +33,20 @@ interface QuestionType { static public function getName(); /** - * Returns a template that is used to edit or create the question. Note that - * $this['data'] might already be filled with data, when the user is editing an - * existing question. - * @return Flexi_Template + * Returns an array with two parts: First one is the name of the component for editing the question. Second + * one is the import path of the component. Plugins can use this to get their component imported. + * @return Array */ - public function getEditingTemplate(); + static public function getEditingComponent(); /** - * Called right before the questionnaire and the question is stored or when the user - * needs to refresh the editing-window, This method is called to store the - * request-values into $this['data']. You get them from the Request-class as usual. + * Usually the $questiondata is already in the correct format. But for some question types + * some data have to be manipulated by for example the HTML-purifier. So this takes + * the questiondata and changed them before they get stored. + * @param $questiondata + * @return mixed */ - public function createDataFromRequest(); + public function beforeStoringQuestiondata($questiondata); /** * Display the question to the user. This template will be embedded into a @@ -64,6 +72,15 @@ interface QuestionType { public function createAnswer(); /** + * In the evaluation of the questionnaire you can click on a certain answer and get the evaluation filtered + * by the the people that have given that answer. This method asks from the question, what user_ids have + * given the answer_option. Answer option could be anything that this question understands as an answer. + * @param $answer_option + * @return mixed + */ + public function getUserIdsOfFilteredAnswer($answer_option); + + /** * Returns a template with the results of this question. * @param $only_user_ids : array\null array of user_ids that the results should be restricted to. * this is used to show only a subset of results to the user for @@ -95,4 +112,4 @@ interface QuestionType { * @return void */ public function onEnding(); -}
\ No newline at end of file +} diff --git a/lib/models/Freetext.php b/lib/models/Freetext.php index 0c8272b..4cc8b62 100644 --- a/lib/models/Freetext.php +++ b/lib/models/Freetext.php @@ -2,73 +2,50 @@ require_once 'lib/classes/QuestionType.interface.php'; -use eTask\Task; - class Freetext extends QuestionnaireQuestion implements QuestionType { /** * Returns the Icon-object to this QuestionType. * @param bool $active: true if Icon should be clickable, false for black info-icon. - * @param bool $add : true if the add-appendix shoudl be added to the icon. * @return Icon : guestbook-icon. */ - public static function getIcon($active = false, $add = false) + public static function getIcon(bool $active = false) : Icon { return Icon::create( - 'guestbook', + static::getIconShape(), $active ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO ); } /** - * Returns the name of this QuestionType "Freitextfrage". + * Returns the shape of the icon of this QuestionType * @return string */ - public static function getName() + public static function getIconShape() { - return _('Freitextfrage'); + return 'guestbook'; } /** - * Returns the template to edit this question - * @return Flexi_Template - * @throws Flexi_TemplateNotFoundException if there is no template. + * Returns the name of this QuestionType "Freitextfrage". + * @return string */ - public function getEditingTemplate() + public static function getName() { - $factory = new Flexi_TemplateFactory(realpath(__DIR__ . '/../../app/views')); - $template = $factory->open('questionnaire/question_types/freetext/freetext_edit.php'); - $template->vote = $this; - return $template; + return _('Freitextfrage'); } - /** - * Processes the request and stores the given values into the etask-object. - * Called when the question is saved by the user. - */ - public function createDataFromRequest() + static public function getEditingComponent() { - $questions = Request::getArray('questions'); - $data = $questions[$this->getId()]; - - if (!$this->etask) { - $this->etask = Task::create([ - 'type' => 'freetext', - 'user_id' => $GLOBALS['user']->id, - ]); - } - - $this->etask->description = Studip\Markup::purifyHtml($data['description']); - $this->etask->task = []; - - // update mandatory option - if (isset($data['options']['mandatory'])) { - $options = $this->etask->options; - $options['mandatory'] = (bool) $data['options']['mandatory']; - $this->etask->options = $options; - } + return ['freetext-edit', '']; + } - $this->etask->store(); + public function beforeStoringQuestiondata($questiondata) + { + $questiondata['description'] = \Studip\Markup::markAsHtml( + \Studip\Markup::purifyHtml($questiondata['description']) + ); + return $questiondata; } /** @@ -98,6 +75,11 @@ class Freetext extends QuestionnaireQuestion implements QuestionType return $answer; } + public function getUserIdsOfFilteredAnswer($answer_option) + { + return []; + } + /** * Returns the template with the answers of the question so far. * @param null $only_user_ids : array of user_ids @@ -106,9 +88,18 @@ class Freetext extends QuestionnaireQuestion implements QuestionType */ public function getResultTemplate($only_user_ids = null) { + $answers = $this->answers; + if ($only_user_ids !== null) { + foreach ($answers as $key => $answer) { + if (!in_array($answer['user_id'], $only_user_ids)) { + unset($answers[$key]); + } + } + } $factory = new Flexi_TemplateFactory(realpath(__DIR__ . '/../../app/views')); $template = $factory->open('questionnaire/question_types/freetext/freetext_evaluation.php'); $template->vote = $this; + $template->set_attribute('answers', $answers); return $template; } @@ -121,7 +112,7 @@ class Freetext extends QuestionnaireQuestion implements QuestionType $output = []; $countNobodys = 0; - $question = trim(strip_tags($this->etask->description)); + $question = trim(strip_tags($this->questiondata['description'])); foreach ($this->answers as $answer) { if ($answer['user_id'] && $answer['user_id'] != 'nobody') { $userId = $answer['user_id']; diff --git a/lib/models/LikertScale.php b/lib/models/LikertScale.php new file mode 100644 index 0000000..d5d2d06 --- /dev/null +++ b/lib/models/LikertScale.php @@ -0,0 +1,115 @@ +<?php +require_once 'lib/classes/QuestionType.interface.php'; + +class LikertScale extends QuestionnaireQuestion implements QuestionType +{ + public static function getIcon(bool $active = false) : Icon + { + return Icon::create(static::getIconShape(), $active ? 'clickable' : 'info'); + } + + /** + * Returns the shape of the icon of this QuestionType + * @return string + */ + public static function getIconShape() + { + return 'likert'; + } + + public static function getName() + { + return _('Likert-Skala'); + } + + static public function getEditingComponent() + { + return ['likert-edit', '']; + } + + public function beforeStoringQuestiondata($questiondata) + { + $questiondata['description'] = \Studip\Markup::markAsHtml( + \Studip\Markup::purifyHtml($questiondata['description']) + ); + $questiondata['statements'] = array_filter($questiondata['statements']); + return $questiondata; + } + + public function getDisplayTemplate() + { + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/likert/likert_answer'); + $template->set_attribute('vote', $this); + return $template; + } + + public function createAnswer() + { + $answer = $this->getMyAnswer(); + + $answers = Request::getArray('answers'); + $userAnswer = (array) $answers[$this->getId()]['answerdata']['answers']; + $userAnswer = array_map(function ($val) { return (int) $val; }, $userAnswer); + $answer->setData(['answerdata' => ['answers' => $userAnswer ] ]); + return $answer; + } + + public function getUserIdsOfFilteredAnswer($answer_option) + { + $user_ids = []; + list($statement_key, $options_key) = explode('_', $answer_option); + foreach ($this->answers as $answer) { + $answerData = $answer['answerdata']->getArrayCopy(); + if ($answerData['answers'][$statement_key] == $options_key) { + $user_ids[] = $answer['user_id']; + } + } + return $user_ids; + } + + public function getResultTemplate($only_user_ids = null, $filtered = null) + { + $answers = $this->answers; + if ($only_user_ids !== null) { + foreach ($answers as $key => $answer) { + if (!in_array($answer['user_id'], $only_user_ids)) { + unset($answers[$key]); + } + } + } + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/likert/likert_evaluation'); + $template->set_attribute('vote', $this); + $template->set_attribute('answers', $answers); + $template->set_attribute('filtered', $filtered); + return $template; + } + + public function getResultArray() + { + $output = []; + + $statements = $this['questiondata']['statements']->getArrayCopy(); + + foreach ($statements as $statement_key => $statement) { + $answerOption = []; + $countNobodys = 0; + + foreach ($this->answers as $answer) { + $answerData = $answer['answerdata']->getArrayCopy(); + + if ($answer['user_id'] && $answer['user_id'] != 'nobody') { + $userId = $answer['user_id']; + } else { + $countNobodys++; + $userId = _('unbekannt').' '.$countNobodys; + } + + $answerOption[$userId] = $this['questiondata']['options'][$answerData['answers'][$statement_key]]; + } + $output[$statement] = $answerOption; + } + return $output; + } +} diff --git a/lib/models/Questionnaire.php b/lib/models/Questionnaire.php index cd18082..f221ca1 100644 --- a/lib/models/Questionnaire.php +++ b/lib/models/Questionnaire.php @@ -8,6 +8,7 @@ class Questionnaire extends SimpleORMap implements PrivacyObject $config['has_many']['questions'] = [ 'class_name' => QuestionnaireQuestion::class, + 'order_by' => 'ORDER BY position ASC', 'on_delete' => 'delete', 'on_store' => 'store' ]; @@ -214,7 +215,8 @@ class Questionnaire extends SimpleORMap implements PrivacyObject } return $this['resultvisibility'] === "always" || $this->isEditable() - || ($this['resultvisibility'] === "afterending" && $this->isStopped()); + || ($this['resultvisibility'] === "afterending" && $this->isStopped()) + || ($this['resultvisibility'] === 'afterparticipation' && $this->isAnswered()); } /** @@ -236,4 +238,29 @@ class Questionnaire extends SimpleORMap implements PrivacyObject } } } + + /** + * Returns all data as an array that could be stored as JSON. + * @return array + */ + public function exportAsFile() + { + $data = [ + 'questionnaire' => [ + 'title' => $this['title'], + 'anonymous' => $this['anonymous'], + 'resultvisibility' => $this['resultvisibility'], + 'editanswers' => $this['editanswers'] + ], + 'questions_data' => [] + ]; + foreach ($this->questions as $question) { + $data['questions_data'][] = [ + 'questiontype' => $question['questiontype'], + 'internal_name' => $question['internal_name'], + 'questiondata' => $question['questiondata']->getArrayCopy() + ]; + } + return $data; + } } diff --git a/lib/models/QuestionnaireAnswer.php b/lib/models/QuestionnaireAnswer.php index 6e895b6..4713b7f 100644 --- a/lib/models/QuestionnaireAnswer.php +++ b/lib/models/QuestionnaireAnswer.php @@ -9,6 +9,10 @@ class QuestionnaireAnswer extends SimpleORMap implements PrivacyObject $config['belongs_to']['question'] = [ 'class_name' => QuestionnaireQuestion::class, ]; + $config['belongs_to']['user'] = [ + 'class_name' => User::class, + 'foreign_key' => 'user_id' + ]; $config['serialized_fields']['answerdata'] = "JSONArrayObject"; parent::configure($config); diff --git a/lib/models/QuestionnaireInfo.php b/lib/models/QuestionnaireInfo.php new file mode 100644 index 0000000..7596586 --- /dev/null +++ b/lib/models/QuestionnaireInfo.php @@ -0,0 +1,68 @@ +<?php +require_once 'lib/classes/QuestionType.interface.php'; + +class QuestionnaireInfo extends QuestionnaireQuestion implements QuestionType +{ + public static function getIcon(bool $active = false) : Icon + { + return Icon::create(static::getIconShape(), $active ? 'clickable' : 'info'); + } + + /** + * Returns the shape of the icon of this QuestionType + * @return string + */ + public static function getIconShape() + { + return 'info-circle'; + } + + public static function getName() + { + return _('Information'); + } + + static public function getEditingComponent() + { + return ['questionnaire-info-edit', '']; + } + + public function beforeStoringQuestiondata($questiondata) + { + $questiondata['description'] = \Studip\Markup::markAsHtml( + \Studip\Markup::purifyHtml($questiondata['description']) + ); + return $questiondata; + } + + public function getDisplayTemplate() + { + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/info/info'); + $template->set_attribute('vote', $this); + return $template; + } + + public function createAnswer() + { + + } + + public function getUserIdsOfFilteredAnswer($answer_option) + { + return []; + } + + public function getResultTemplate($only_user_ids = null) + { + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/info/info'); + $template->set_attribute('vote', $this); + return $template; + } + + public function getResultArray() + { + return []; + } +} diff --git a/lib/models/QuestionnaireQuestion.php b/lib/models/QuestionnaireQuestion.php index 93c3279..1e37340 100644 --- a/lib/models/QuestionnaireQuestion.php +++ b/lib/models/QuestionnaireQuestion.php @@ -17,11 +17,7 @@ class QuestionnaireQuestion extends SimpleORMap 'on_delete' => 'delete', 'on_store' => 'store' ]; - $config['belongs_to']['etask'] = [ - 'class_name' => \eTask\Task::class, - 'foreign_key' => 'etask_task_id' - ]; - + $config['serialized_fields']['questiondata'] = 'JSONArrayObject'; parent::configure($config); } @@ -38,24 +34,7 @@ class QuestionnaireQuestion extends SimpleORMap $data = $statement->fetchAll(); $questions = []; foreach ($data as $questionnaire_data) { - - if (!$task = Task::find($questionnaire_data['etask_task_id'])) { - continue; - } - - $class = $task->type; - - if ($class === 'multiple-choice') { - $totalScore = array_reduce( - isset($task->task['answers']) ? $task->task['answers']->getArrayCopy() : [], - function ($totalScore, $answer) { - return $totalScore + intval($answer['score'] ?: 0); - }, - 0 - ); - $class = $totalScore === 0 ? 'Vote' : 'Test'; - } - + $class = $questionnaire_data['questiontype']; if (class_exists(ucfirst($class))) { $questions[] = $class::buildExisting($questionnaire_data); } diff --git a/lib/models/RangeScale.php b/lib/models/RangeScale.php new file mode 100644 index 0000000..a196462 --- /dev/null +++ b/lib/models/RangeScale.php @@ -0,0 +1,114 @@ +<?php +require_once 'lib/classes/QuestionType.interface.php'; + +class RangeScale extends QuestionnaireQuestion implements QuestionType +{ + public static function getIcon(bool $active = false) : Icon + { + return Icon::create(static::getIconShape(), $active ? 'clickable' : 'info'); + } + + /** + * Returns the shape of the icon of this QuestionType + * @return string + */ + public static function getIconShape() + { + return 'rangescale'; + } + + public static function getName() + { + return _('Pol-Skala'); + } + + public function beforeStoringQuestiondata($questiondata) + { + $questiondata['description'] = \Studip\Markup::markAsHtml( + \Studip\Markup::purifyHtml($questiondata['description']) + ); + $questiondata['statements'] = array_filter($questiondata['statements']); + return $questiondata; + } + + static public function getEditingComponent() + { + return ['rangescale-edit', '']; + } + + public function getDisplayTemplate() + { + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/rangescale/rangescale_answer'); + $template->set_attribute('vote', $this); + return $template; + } + + public function createAnswer() + { + $answer = $this->getMyAnswer(); + + $answers = Request::getArray('answers'); + $userAnswer = (array) $answers[$this->getId()]['answerdata']['answers']; + $answer->setData(['answerdata' => ['answers' => $userAnswer ] ]); + return $answer; + } + + public function getUserIdsOfFilteredAnswer($answer_option) + { + $user_ids = []; + list($statement_key, $options_key) = explode('_', $answer_option); + foreach ($this->answers as $answer) { + $answerData = $answer['answerdata']->getArrayCopy(); + if ($answerData['answers'][$statement_key] == $options_key) { + $user_ids[] = $answer['user_id']; + } + } + return $user_ids; + } + + public function getResultTemplate($only_user_ids = null, $filtered = null) + { + $answers = $this->answers; + if ($only_user_ids !== null) { + foreach ($answers as $key => $answer) { + if (!in_array($answer['user_id'], $only_user_ids)) { + unset($answers[$key]); + } + } + } + $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); + $template = $factory->open('questionnaire/question_types/rangescale/rangescale_evaluation'); + $template->set_attribute('vote', $this); + $template->set_attribute('answers', $answers); + $template->set_attribute('filtered', $filtered); + return $template; + } + + public function getResultArray() + { + $output = []; + + $statements = $this['questiondata']['statements']->getArrayCopy(); + + foreach ($statements as $statement_key => $statement) { + $answerOption = []; + $countNobodys = 0; + + foreach ($this->answers as $answer) { + $answerData = $answer['answerdata']->getArrayCopy(); + + if ($answer['user_id'] && $answer['user_id'] != 'nobody') { + $userId = $answer['user_id']; + } else { + $countNobodys++; + $userId = _('unbekannt').' '.$countNobodys; + } + + $answerOption[$userId] = $answerData['answers'][$statement_key]; + } + $output[$statement] = $answerOption; + } + return $output; + } +} diff --git a/lib/models/Test.php b/lib/models/Test.php deleted file mode 100644 index 53e8790..0000000 --- a/lib/models/Test.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php - -require_once 'lib/classes/QuestionType.interface.php'; - -use eTask\Task; - -class Test extends QuestionnaireQuestion implements QuestionType -{ - public static function getIcon($active = false, $add = false) - { - return Icon::create('test', $active ? 'clickable' : 'info'); - } - - public static function getName() - { - return _('Test'); - } - - public function getEditingTemplate() - { - $tf = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); - $template = $tf->open('questionnaire/question_types/test/test_edit'); - $template->set_attribute('vote', $this); - return $template; - } - - public function createDataFromRequest() - { - $questions = Request::getArray('questions'); - $requestData = $questions[$this->getId()]; - - // create a new eTask if this is a new question - if (!$this->etask) { - $this->etask = Task::create( - [ - 'type' => 'multiple-choice', - 'user_id' => $GLOBALS['user']->id, - ] - ); - } - - // update description - $this->etask->description = Studip\Markup::purifyHtml($requestData['description']); - - // update task's type (single|multiple) - $task = [ - 'type' => $requestData['task']['type'] === 'multiple' ? 'multiple' : 'single', - 'answers' => [] - ]; - - // update task's answers - $correct = isset($requestData['task']['correct']) ? $requestData['task']['correct'] : []; - foreach ($requestData['task']['answers'] as $index => $text) { - $trimmedText = trim($text); - if ($trimmedText === '') { - continue; - } - - $task['answers'][] = [ - 'text' => $trimmedText, - 'score' => in_array($index + 1, $correct) ? 1 : 0, - 'feedback' => '' - ]; - } - - $this->etask->task = $task; - - // update randomize option - if (isset($requestData['options']['randomize'])) { - $options = $this->etask->options; - $options['randomize'] = (bool) $requestData['options']['randomize']; - $this->etask->options = $options; - } - - // store the eTask instance - $this->etask->store(); - } - - public function getDisplayTemplate() - { - $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); - $template = $factory->open('questionnaire/question_types/vote/vote_answer'); - $template->set_attribute('vote', $this); - return $template; - } - - public function createAnswer() - { - $answer = $this->getMyAnswer(); - - $answers = Request::getArray('answers'); - if (array_key_exists($this->getId(), $answers)) { - $userAnswer = $answers[$this->getId()]['answerdata']['answers']; - if (is_array($userAnswer)) { - $userAnswer = array_map('intval', $userAnswer); - } - else { - $userAnswer = (int) $userAnswer; - } - } - $answer->setData(['answerData' => ['answers' => $userAnswer ] ]); - return $answer; - } - - public function getResultTemplate($only_user_ids = null) - { - $answers = $this->answers; - if ($only_user_ids !== null) { - foreach ($answers as $key => $answer) { - if (!in_array($answer['user_id'], $only_user_ids)) { - unset($answers[$key]); - } - } - } - $factory = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); - $template = $factory->open('questionnaire/question_types/test/test_evaluation'); - $template->set_attribute('vote', $this); - $template->set_attribute('answers', $answers); - return $template; - } - - public function getResultArray() - { - $output = []; - - $taskAnswers = $this->etask->task['answers']; - - foreach ($taskAnswers as $key => $option) { - $answerOption = []; - $countNobodys = 0; - - foreach ($this->answers as $answer) { - $answerData = $answer['answerdata']->getArrayCopy(); - - if ($answer['user_id'] && $answer['user_id'] != 'nobody') { - $userId = $answer['user_id']; - } else { - $countNobodys++; - $userId = _('unbekannt').' '.$countNobodys; - } - - if (in_array($key, (array) $answerData['answers'])) { - $answerOption[$userId] = 1; - } else { - $answerOption[$userId] = 0; - } - } - $output[$option['text']] = $answerOption; - } - return $output; - } - - public function correctAnswered($userId = null, $answersToCheck = null) - { - $userId = $userId ?: $GLOBALS['user']->id; - $correctAnswered = true; - $task = $this->etask->task; - $numTaskAnswers = count($task['answers']); - $resultsUsers = array_fill(0, $numTaskAnswers, []); - if ($answersToCheck && !is_array($answersToCheck)) { - $answersToCheck = [$answersToCheck]; - } - $answersToCheck = is_array($answersToCheck) ? $answersToCheck : $this->answers->findBy('user_id', $userId); - - foreach ($answersToCheck as $answer) { - if ($task['type'] === 'multiple' && is_object($answer['answerdata']['answers'])) { - foreach ($answer['answerdata']['answers'] as $a) { - $resultsUsers[(int) $a][] = $answer['user_id']; - } - } else { - $resultsUsers[(int) $answer['answerdata']['answers']][] = $answer['user_id']; - } - } - foreach ($task['answers'] as $index => $option) { - if ($option['score']) { - if (!in_array($userId, $resultsUsers[$index])) { - $correctAnswered = false; - break; - } - } else { - if (in_array($userId, $resultsUsers[$index])) { - $correctAnswered = false; - break; - } - } - } - return $correctAnswered; - } -} diff --git a/lib/models/Vote.php b/lib/models/Vote.php index 6060f0b..12c8fee 100644 --- a/lib/models/Vote.php +++ b/lib/models/Vote.php @@ -1,13 +1,20 @@ <?php require_once 'lib/classes/QuestionType.interface.php'; -use eTask\Task; - class Vote extends QuestionnaireQuestion implements QuestionType { - public static function getIcon($active = false, $add = false) + public static function getIcon(bool $active = false) : Icon + { + return Icon::create(static::getIconShape(), $active ? 'clickable' : 'info'); + } + + /** + * Returns the shape of the icon of this QuestionType + * @return string + */ + public static function getIconShape() { - return Icon::create('vote', $active ? 'clickable' : 'info'); + return 'vote'; } public static function getName() @@ -15,69 +22,18 @@ class Vote extends QuestionnaireQuestion implements QuestionType return _('Auswahlfrage'); } - public function getEditingTemplate() + static public function getEditingComponent() { - $tf = new Flexi_TemplateFactory(realpath(__DIR__.'/../../app/views')); - $template = $tf->open('questionnaire/question_types/vote/vote_edit'); - $template->set_attribute('vote', $this); - return $template; + return ['vote-edit', '']; } - public function createDataFromRequest() + public function beforeStoringQuestiondata($questiondata) { - $questions = Request::getArray('questions'); - $data = $questions[$this->getId()]; - - // create a new eTask if this is a new question - if (!$this->etask) { - $this->etask = Task::create( - [ - 'type' => 'multiple-choice', - 'user_id' => $GLOBALS['user']->id, - ] - ); - } - - // update description - $this->etask->description = Studip\Markup::purifyHtml($data['description']); - - // update task's type (single|multiple) - $task = [ - 'type' => $data['task']['type'] === 'multiple' ? 'multiple' : 'single', - 'answers' => [] - ]; - - // update task's answers - foreach ($data['task']['answers'] as $index => $text) { - $trimmedText = trim($text); - if ($trimmedText === '') { - continue; - } - - $task['answers'][] = [ - 'text' => $trimmedText, - 'score' => 0, - 'feedback' => '' - ]; - } - - $this->etask->task = $task; - - // update randomize option - if (isset($data['options']['randomize'])) { - $options = $this->etask->options; - $options['randomize'] = (bool) $data['options']['randomize']; - $this->etask->options = $options; - } - // update mandatory option - if (isset($data['options']['mandatory'])) { - $options = $this->etask->options; - $options['mandatory'] = (bool) $data['options']['mandatory']; - $this->etask->options = $options; - } - - // store the eTask instance - $this->etask->store(); + $questiondata['description'] = \Studip\Markup::markAsHtml( + \Studip\Markup::purifyHtml($questiondata['description']) + ); + $questiondata['options'] = array_filter($questiondata['options']); + return $questiondata; } public function getDisplayTemplate() @@ -106,7 +62,19 @@ class Vote extends QuestionnaireQuestion implements QuestionType return $answer; } - public function getResultTemplate($only_user_ids = null) + public function getUserIdsOfFilteredAnswer($answer_option) + { + $user_ids = []; + foreach ($this->answers as $answer) { + $answerData = $answer['answerdata']->getArrayCopy(); + if (in_array($answer_option, (array) $answerData['answers'])) { + $user_ids[] = $answer['user_id']; + } + } + return $user_ids; + } + + public function getResultTemplate($only_user_ids = null, $filtered = null) { $answers = $this->answers; if ($only_user_ids !== null) { @@ -120,6 +88,7 @@ class Vote extends QuestionnaireQuestion implements QuestionType $template = $factory->open('questionnaire/question_types/vote/vote_evaluation'); $template->set_attribute('vote', $this); $template->set_attribute('answers', $answers); + $template->set_attribute('filtered', $filtered); return $template; } @@ -127,9 +96,9 @@ class Vote extends QuestionnaireQuestion implements QuestionType { $output = []; - $taskAnswers = $this->etask->task['answers']; + $options = $this['questiondata']['options'] ? $this['questiondata']['options']->getArrayCopy() : []; - foreach ($taskAnswers as $key => $option) { + foreach ($options as $key => $option) { $answerOption = []; $countNobodys = 0; @@ -149,7 +118,7 @@ class Vote extends QuestionnaireQuestion implements QuestionType $answerOption[$userId] = 0; } } - $output[$option['text']] = $answerOption; + $output[$option] = $answerOption; } return $output; } diff --git a/lib/modules/CoreAdmin.class.php b/lib/modules/CoreAdmin.class.php index b307b6f..b02cf93 100644 --- a/lib/modules/CoreAdmin.class.php +++ b/lib/modules/CoreAdmin.class.php @@ -88,7 +88,8 @@ class CoreAdmin extends CorePlugin implements StudipModule $item->setImage(Icon::create('vote')); $item->setDescription(_('Erstellen und bearbeiten von Fragebögen.')); $navigation->addSubNavigation('questionnaires', $item); - + } + if (Config::get()->EVAL_ENABLE) { $item = new Navigation(_('Evaluationen'), 'admin_evaluation.php?view=eval_sem'); $item->setImage(Icon::create('evaluation')); $item->setDescription(_('Richten Sie fragebogenbasierte Umfragen und Lehrevaluationen ein.')); diff --git a/lib/modules/EvaluationsWidget.php b/lib/modules/EvaluationsWidget.php index 3c5cf6f..64458d9 100644 --- a/lib/modules/EvaluationsWidget.php +++ b/lib/modules/EvaluationsWidget.php @@ -46,7 +46,9 @@ class EvaluationsWidget extends CorePlugin implements PortalPlugin $controller = app(AuthenticatedController::class, ['dispatcher' => app(\Trails_Dispatcher::class)]); $controller->suppress_empty_output = true; - $response = $controller->relay('evaluation/display/studip')->body; + if (Config::get()->EVAL_ENABLE) { + $response = $controller->relay('evaluation/display/studip')->body; + } $controller->suppress_empty_output = (bool)$response; $response .= $controller->relay('questionnaire/widget/start')->body; diff --git a/lib/navigation/AdminNavigation.php b/lib/navigation/AdminNavigation.php index b45859c..de3481b 100644 --- a/lib/navigation/AdminNavigation.php +++ b/lib/navigation/AdminNavigation.php @@ -75,7 +75,7 @@ class AdminNavigation extends Navigation $navigation->addSubNavigation('faculty', new Navigation(_('Mitarbeiter'), 'dispatch.php/institute/members?admin_view=1')); $navigation->addSubNavigation('groups', new Navigation(_('Funktionen / Gruppen'), 'dispatch.php/admin/statusgroups?type=inst')); - if (Config::get()->VOTE_ENABLE) { + if (Config::get()->EVAL_ENABLE) { $navigation->addSubNavigation('evaluation', new Navigation(_('Evaluationen'), 'admin_evaluation.php?view=eval_inst')); } diff --git a/lib/navigation/ContentsNavigation.php b/lib/navigation/ContentsNavigation.php index 8e814ef..965f598 100644 --- a/lib/navigation/ContentsNavigation.php +++ b/lib/navigation/ContentsNavigation.php @@ -126,7 +126,9 @@ class ContentsNavigation extends Navigation ); $questionnaire->addSubNavigation('assign', $sub_nav); } + } + if (Config::get()->EVAL_ENABLE) { $eval = new Navigation(_('Evaluationen'), 'admin_evaluation.php', ['rangeID' => $GLOBALS['user']->username]); $eval->setImage(Icon::create('test')); $eval->setDescription(_('Erstellen Sie komplexe Befragungen')); diff --git a/lib/navigation/StartNavigation.php b/lib/navigation/StartNavigation.php index e5779a5..6f95971 100644 --- a/lib/navigation/StartNavigation.php +++ b/lib/navigation/StartNavigation.php @@ -55,19 +55,6 @@ class StartNavigation extends Navigation $statement->execute(['threshold' => $threshold, ':user_id' => $GLOBALS['user']->id, ':plugin_id' => -1]); $vote = (int) $statement->fetchColumn(); - $query = "SELECT COUNT(IF(chdate > IFNULL(b.visitdate, :threshold) AND d.author_id != :user_id, a.eval_id, NULL)) - FROM eval_range a - INNER JOIN eval d ON (a.eval_id = d.eval_id AND d.startdate < UNIX_TIMESTAMP() AND - (d.stopdate > UNIX_TIMESTAMP() OR d.startdate + d.timespan > UNIX_TIMESTAMP() OR (d.stopdate IS NULL AND d.timespan IS NULL))) - LEFT JOIN object_user_visits b ON (b.object_id = d.eval_id AND b.user_id = :user_id AND b.plugin_id = :plugin_id) - WHERE a.range_id = 'studip' - GROUP BY a.range_id"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':user_id', $GLOBALS['user']->id); - $statement->bindValue(':threshold', $threshold); - $statement->bindValue(':plugin_id', -2); - $statement->execute(); - $vote += (int)$statement->fetchColumn(); } } @@ -243,6 +230,8 @@ class StartNavigation extends Navigation if (Config::get()->VOTE_ENABLE) { $navigation->addSubNavigation('questionnaire', new Navigation(_('Ankündigungen'), 'dispatch.php/news/admin_news')); + } + if (Config::get()->EVAL_ENABLE) { $navigation->addSubNavigation('evaluation', new Navigation(_('Evaluationen'), 'admin_evaluation.php', ['rangeID' => $auth->auth['uname']])); } |
