From e52d31a783394c50bc49c3516d1fee25cf3b9d23 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 15 Oct 2026 20:45:08 +0200 Subject: [PATCH] Add saved test result preview --- README.md | 3 +- .../language/en-GB/com_testquestions.ini | 13 ++++++ .../sql/updates/mysql/1.18.0.sql | 1 + .../src/Model/ResultModel.php | 44 +++++++++++++++++++ .../src/Model/ResultsModel.php | 35 +++++++++++++++ .../src/View/Questions/HtmlView.php | 6 +++ .../src/View/Result/HtmlView.php | 28 ++++++++++++ .../src/View/Results/HtmlView.php | 28 ++++++++++++ .../src/View/Sets/HtmlView.php | 5 +++ .../com_testquestions/tmpl/result/default.php | 26 +++++++++++ .../tmpl/results/default.php | 36 +++++++++++++++ com_testquestions.xml | 2 +- 12 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 administrator/components/com_testquestions/sql/updates/mysql/1.18.0.sql create mode 100644 administrator/components/com_testquestions/src/Model/ResultModel.php create mode 100644 administrator/components/com_testquestions/src/Model/ResultsModel.php create mode 100644 administrator/components/com_testquestions/src/View/Result/HtmlView.php create mode 100644 administrator/components/com_testquestions/src/View/Results/HtmlView.php create mode 100644 administrator/components/com_testquestions/tmpl/result/default.php create mode 100644 administrator/components/com_testquestions/tmpl/results/default.php diff --git a/README.md b/README.md index 61d7164..eb3f26a 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Szkielet komponentu Joomla 6 do gromadzenia pytań testowych. - dwuetapowe rozpoczęcie testu z loginem użytkownika i możliwością przedłużenia czasu, - zegar odliczający czas testu i automatyczne zakończenie po jego upływie, - zapisywanie wyników testów i zaznaczonych odpowiedzi w bazie danych, +- podgląd zapisanych testów w panelu administratora, - pozycję menu „Arkusz egzaminacyjny” z opcjonalnym symbolem arkusza, - listę wyboru dostępnych symboli arkuszy na stronie klienckiej, - możliwość rozwiązania arkusza i wyświetlenia wyniku oraz odpowiedzi poprawnych i zaznaczonych, @@ -28,6 +29,6 @@ Szkielet komponentu Joomla 6 do gromadzenia pytań testowych. ## Instalacja -W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.17.0). +W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.18.0). Po instalacji komponent jest dostępny w panelu administratora jako **Pytania testowe**. diff --git a/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini b/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini index 7d4ed18..b947e9a 100644 --- a/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini +++ b/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini @@ -62,6 +62,19 @@ COM_TESTQUESTIONS_SET_DURATION="Czas trwania testu (minuty)" COM_TESTQUESTIONS_SET_DURATION_DESC="Ustaw czas trwania testu w minutach za pomocą suwaka." COM_TESTQUESTIONS_SET_TEST_CONTENT="Treść testu" COM_TESTQUESTIONS_SET_IMAGE="Obraz testu" +COM_TESTQUESTIONS_RESULTS="Zapisane testy" +COM_TESTQUESTIONS_RESULT_PREVIEW="Podgląd zapisanego testu" +COM_TESTQUESTIONS_RESULT_NOT_FOUND="Nie znaleziono zapisanego testu." +COM_TESTQUESTIONS_RESULT_PARTICIPANT="Użytkownik" +COM_TESTQUESTIONS_RESULT_SCORE="Wynik" +COM_TESTQUESTIONS_RESULT_DATE="Data zakończenia" +COM_TESTQUESTIONS_RESULT_ANSWERS="Odpowiedzi" +COM_TESTQUESTIONS_RESULTS_SEARCH="Szukaj po użytkowniku lub zestawie..." +COM_TESTQUESTIONS_YOUR_ANSWER="Twoja odpowiedź" +COM_TESTQUESTIONS_SELECTED_ANSWER="Zaznaczona odpowiedź" +COM_TESTQUESTIONS_ANSWER_CORRECT="Poprawna odpowiedź" +COM_TESTQUESTIONS_ANSWER_INCORRECT="Niepoprawna odpowiedź" +COM_TESTQUESTIONS_CORRECT_PATTERN="Wzorzec poprawnej odpowiedzi" COM_TESTQUESTIONS_SUBJECT="Przedmiot" COM_TESTQUESTIONS_SUBJECT_TITLE="Nazwa przedmiotu" COM_TESTQUESTIONS_NEW_SUBJECT="Nowy przedmiot" diff --git a/administrator/components/com_testquestions/sql/updates/mysql/1.18.0.sql b/administrator/components/com_testquestions/sql/updates/mysql/1.18.0.sql new file mode 100644 index 0000000..e90b6bd --- /dev/null +++ b/administrator/components/com_testquestions/sql/updates/mysql/1.18.0.sql @@ -0,0 +1 @@ +-- No database changes required for version 1.18.0. diff --git a/administrator/components/com_testquestions/src/Model/ResultModel.php b/administrator/components/com_testquestions/src/Model/ResultModel.php new file mode 100644 index 0000000..613fc84 --- /dev/null +++ b/administrator/components/com_testquestions/src/Model/ResultModel.php @@ -0,0 +1,44 @@ +getInput()->getInt('id')); + $db = Factory::getContainer()->get('DatabaseDriver'); + $item = $db->setQuery( + $db->getQuery(true) + ->select(['r.*', 's.title AS set_title', 'sub.title AS subject_title']) + ->from($db->quoteName('#__testquestions_results', 'r')) + ->leftJoin($db->quoteName('#__testquestions_sets', 's') . ' ON s.id = r.set_id') + ->leftJoin($db->quoteName('#__testquestions_subjects', 'sub') . ' ON sub.id = s.subject_id') + ->where('r.id = ' . $id) + )->loadObject(); + + if (!$item) { + return null; + } + + $item->answers = json_decode((string) $item->answers, true) ?: []; + $ids = array_map('intval', array_keys($item->answers)); + $item->questions = []; + + if ($ids) { + $item->questions = $db->setQuery( + $db->getQuery(true) + ->select(['id', 'question_type', 'question', 'answer_a', 'answer_b', 'answer_c', 'answer_d', 'answer_open', 'correct_answer']) + ->from($db->quoteName('#__testquestions_questions')) + ->where('id IN (' . implode(',', $ids) . ')') + )->loadObjectList('id'); + } + + return $item; + } +} diff --git a/administrator/components/com_testquestions/src/Model/ResultsModel.php b/administrator/components/com_testquestions/src/Model/ResultsModel.php new file mode 100644 index 0000000..e22138b --- /dev/null +++ b/administrator/components/com_testquestions/src/Model/ResultsModel.php @@ -0,0 +1,35 @@ +setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); + } + + protected function getListQuery() + { + $db = Factory::getContainer()->get('DatabaseDriver'); + $query = $db->getQuery(true) + ->select(['r.*', 's.title AS set_title', 'sub.title AS subject_title']) + ->from($db->quoteName('#__testquestions_results', 'r')) + ->leftJoin($db->quoteName('#__testquestions_sets', 's') . ' ON s.id = r.set_id') + ->leftJoin($db->quoteName('#__testquestions_subjects', 'sub') . ' ON sub.id = s.subject_id'); + + $search = trim((string) $this->getState('filter.search')); + if ($search !== '') { + $needle = $db->quote('%' . $db->escape($search, true) . '%', false); + $query->where('(r.participant_name LIKE ' . $needle . ' OR s.title LIKE ' . $needle . ')'); + } + + return $query->order('r.created DESC, r.id DESC'); + } +} diff --git a/administrator/components/com_testquestions/src/View/Questions/HtmlView.php b/administrator/components/com_testquestions/src/View/Questions/HtmlView.php index 6007765..2e2c729 100644 --- a/administrator/components/com_testquestions/src/View/Questions/HtmlView.php +++ b/administrator/components/com_testquestions/src/View/Questions/HtmlView.php @@ -57,5 +57,11 @@ class HtmlView extends BaseHtmlView 'COM_TESTQUESTIONS_SETS', 'list' ); + + ToolbarHelper::link( + 'index.php?option=com_testquestions&view=results', + 'COM_TESTQUESTIONS_RESULTS', + 'list' + ); } } diff --git a/administrator/components/com_testquestions/src/View/Result/HtmlView.php b/administrator/components/com_testquestions/src/View/Result/HtmlView.php new file mode 100644 index 0000000..406c3d5 --- /dev/null +++ b/administrator/components/com_testquestions/src/View/Result/HtmlView.php @@ -0,0 +1,28 @@ +item = $this->get('Item'); + + if (!$this->item) { + throw new \RuntimeException(Text::_('COM_TESTQUESTIONS_RESULT_NOT_FOUND')); + } + + ToolbarHelper::title(Text::_('COM_TESTQUESTIONS_RESULT_PREVIEW')); + ToolbarHelper::link('index.php?option=com_testquestions&view=results', 'COM_TESTQUESTIONS_RESULTS', 'back'); + + return parent::display($tpl); + } +} diff --git a/administrator/components/com_testquestions/src/View/Results/HtmlView.php b/administrator/components/com_testquestions/src/View/Results/HtmlView.php new file mode 100644 index 0000000..2530a7a --- /dev/null +++ b/administrator/components/com_testquestions/src/View/Results/HtmlView.php @@ -0,0 +1,28 @@ +items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + ToolbarHelper::title(Text::_('COM_TESTQUESTIONS_RESULTS')); + ToolbarHelper::link('index.php?option=com_testquestions&view=sets', 'COM_TESTQUESTIONS_SETS', 'back'); + + return parent::display($tpl); + } +} diff --git a/administrator/components/com_testquestions/src/View/Sets/HtmlView.php b/administrator/components/com_testquestions/src/View/Sets/HtmlView.php index dbc42fd..60cf9f0 100644 --- a/administrator/components/com_testquestions/src/View/Sets/HtmlView.php +++ b/administrator/components/com_testquestions/src/View/Sets/HtmlView.php @@ -57,5 +57,10 @@ class HtmlView extends BaseHtmlView 'COM_TESTQUESTIONS_SUBJECTS', 'list' ); + ToolbarHelper::link( + 'index.php?option=com_testquestions&view=results', + 'COM_TESTQUESTIONS_RESULTS', + 'list' + ); } } diff --git a/administrator/components/com_testquestions/tmpl/result/default.php b/administrator/components/com_testquestions/tmpl/result/default.php new file mode 100644 index 0000000..34a6f2e --- /dev/null +++ b/administrator/components/com_testquestions/tmpl/result/default.php @@ -0,0 +1,26 @@ + +
+
+
+
escape($this->item->participant_name); ?>
+
+
escape(($this->item->subject_title ? $this->item->subject_title . ' — ' : '') . $this->item->set_title); ?>
+
+
item->correct_count; ?> / item->total_count; ?> (item->percentage, ENT_QUOTES, 'UTF-8'); ?>%)
+
+

+ item->answers as $questionId => $answer) : ?> + item->questions[(int) $questionId] ?? null; if (!$question) continue; ?> +
+
question; ?>
+ question_type === 'open') : ?> +
:
+
: answer_open, ENT_QUOTES, 'UTF-8'); ?>
+ +
:
+
: correct_answer); ?>
+ +
+
+ +
diff --git a/administrator/components/com_testquestions/tmpl/results/default.php b/administrator/components/com_testquestions/tmpl/results/default.php new file mode 100644 index 0000000..f84f0da --- /dev/null +++ b/administrator/components/com_testquestions/tmpl/results/default.php @@ -0,0 +1,36 @@ + +
+
+
+ +
+
+
+ + + + + + + + + items as $item) : ?> + + + + + + + + +
escape($item->participant_name); ?>escape(($item->subject_title ? $item->subject_title . ' — ' : '') . $item->set_title); ?>correct_count; ?> / total_count; ?> (percentage, ENT_QUOTES, 'UTF-8'); ?>%)created, 'Y-m-d H:i'); ?>
+ pagination->getListFooter(); ?> + + +
diff --git a/com_testquestions.xml b/com_testquestions.xml index 167088a..b1ce85a 100644 --- a/com_testquestions.xml +++ b/com_testquestions.xml @@ -4,7 +4,7 @@ 2026-10-14 Komponent GNU General Public License version 2 or later - 1.17.0 + 1.18.0 COM_TESTQUESTIONS_DESCRIPTION com_testquestions Komponent\Component\Testquestions